Menjalankan deployment microservice Go Fiber dengan metode build manual berisiko menghasilkan artefak yang tidak konsisten dan ukuran image yang membengkak. Penggunaan base image umum seperti Alpine atau Ubuntu sering menyisakan celah keamanan (CVE) akibat adanya package manager dan shell sistem yang tidak diperlukan oleh runtime Go.
Kombinasi GoReleaser dan container image Distroless menyelesaikan masalah tersebut. GoReleaser mengotomasi kompilasi cross-platform, stripping binary, penataan tag semver, dan pembuatan changelog. Container base Distroless memangkas seluruh dependensi OS di level container, menghasilkan image produksi yang aman dan berukuran di bawah 30 MB.
1. Persiapan Kompilasi Static Go Fiber
Go secara default dapat menggunakan pustaka C lokal mesin host (via cgo) untuk fungsionalitas tertentu seperti DNS resolving atau deteksi sertifikat OS. Di dalam container Distroless atau scratch, pustaka dynamic linker (seperti glibc) tidak tersedia. Ketiadaan pustaka ini akan menghasilkan error file not found saat binary dieksekusi.
Kompilasi wajib dimatikan integrasi C-nya menggunakan instruksi CGO_ENABLED=0 agar Go menghasilkan single static binary.
// main.go
package main
import (
"github.com/gofiber/fiber/v2"
)
var version = "dev"
func main() {
app := fiber.New()
app.Get("/health", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": "ok",
"version": version,
})
})
_ = app.Listen(":8080")
}2. Desain Dockerfile Berbasis Distroless
Dalam pipeline GoReleaser, Dockerfile tidak melakukan proses go build (multi-stage build standar). GoReleaser mengompilasi binary terlebih dahulu di host runner, kemudian memasukkan binary yang sudah siap pakai ke konteks build Docker.
Gunakan image gcr.io/distroless/static-debian12:nonroot. Image ini memuat sertifikat CA dan file zona waktu minimal, tanpa shell (/bin/sh) atau package manager, serta dijalankan langsung dengan User ID non-root (65532).
# Dockerfile
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /app
COPY fiber-app /app/fiber-app
USER 65532:65532
EXPOSE 8080
ENTRYPOINT ["/app/fiber-app"]3. Konfigurasi .goreleaser.yaml Multi-Platform
Konfigurasi berikut menangani kompilasi matrix untuk arsitektur amd64 dan arm64, optimasi linker flags, pembuatan image terpisah per arsitektur, dan penggabungan manifest multi-arch.
version: 2
before:
hooks:
- go mod tidy
builds:
- id: fiber-app
main: ./main.go
binary: fiber-app
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
- amd64
- arm64
ldflags:
- -s -w
- -X main.version={{.Version}}
dockers:
- image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-amd64"
use: docker
build_flag_templates:
- "--platform=linux/amd64"
goos: linux
goarch: amd64
dockerfile: Dockerfile
files:
- fiber-app
- image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-arm64"
use: docker
build_flag_templates:
- "--platform=linux/arm64"
goos: linux
goarch: arm64
dockerfile: Dockerfile
files:
- fiber-app
docker_manifests:
- name_template: "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-arm64"
- name_template: "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:latest"
image_templates:
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-amd64"
- "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/fiber-app:{{ .Version }}-arm64"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'Catatan Optimasi: Flag-smenghapus tabel simbol debugging dan-wmenghapus informasi DWARF. Kedua flag ini memotong ukuran binary Go Fiber secara signifikan tanpa mengurangi fungsionalitas runtime.
4. Otomasi CI Menggunakan GitHub Actions
Workflow GitHub Actions di bawah dipicu secara eksklusif oleh tag Git yang valid (Semantic Versioning, misal v1.0.0). Pipeline mengautentikasi runner ke GitHub Packages (GHCR) dan menjalankan eksekusi GoReleaser.
# .github/workflows/release.yml
name: Release Pipeline
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
packages: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}5. Verifikasi dan Pengujian Lokal
Jangan menguji pipeline langsung pada remote repository dengan membuat fake tag berulang kali. Validasi konfigurasi secara lokal menggunakan flag --snapshot untuk memverifikasi proses build tanpa melakukan tagging atau push ke registry remote:
# Install goreleaser secara lokal terlebih dahulu
goreleaser release --snapshot --clean --skip=publishPeriksa direktori ./dist yang dihasilkan. Pastikan artefak binary terkompilasi untuk arsitektur yang ditentukan. Untuk memastikan binary benar-benar static, gunakan perintah file pada sistem Linux atau macOS:
file dist/fiber-app_linux_amd64_v1/fiber-app
# Output harus mengandung: statically linkedSetelah tag dirilis via GitHub Actions, verifikasi multi-arch manifest pada registry container target:
docker buildx imagetools inspect ghcr.io/<owner>/fiber-app:latestOutput perintah di atas wajib menampilkan dua platform target (linux/amd64 dan linux/arm64), mengonfirmasi bahwa image dapat di-pull dan dijalankan secara portabel pada VM x86_64 konvensional maupun instance berbasis ARM (seperti AWS Graviton).
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!