Dockerfile Go Best Practice

Pendahuluan

Membuat container untuk aplikasi Go bukan hanya soal menjalankan docker build. Dalam production environment, tujuannya adalah menghasilkan Docker image yang sangat kecil, cepat di-build (dalam hitungan detik), dan sangat aman (lulus audit keamanan).

Ada empat pilar utama untuk Dockerfile Go yang efisien dan aman.

1. Multi-Stage Builds (Build Bertahap)

Ini adalah teknik paling fundamental. Kita tidak ingin mengirim Go SDK (yang berukuran >1GB) ke produksi

  • Tahap 1 (builder): Gunakan image lengkap seperti golang:1.25-alpine untuk meng-install dependensi dan mengkompilasi aplikasi Go Anda

  • Tahap 2 (final): Gunakan image kosong seperti scratch atau distroless. Kemudian, salin hanya hasil binary yang sudah dikompilasi dari tahap builder.

Hasil: Image final hanya berisi binary aplikasi Anda, mengurangi ukuran dari ~1GB menjadi di bawah beberapa MB.

2. Base Image Minimal (scratch vs distroless)

Menggunakan base image seperti ubuntu adalah kesalahan umum. Image besar ini mengandung ribuan paket dan library yang tidak Anda perlukan, yang masing-masing meningkatkan attack surface dan paparan CVE (kerentanan keamanan).

  • scratch: Image ini benar-benar kosong (0MB). Ini adalah yang paling minimal.

  • distroless: Image ini (seperti gcr.io/distroless/static-debian12) hanya berisi hal-hal esensial, seperti sertifikat CA dan data zona waktu, tetapi tidak memiliki shell atau package manager. Ini adalah pilihan yang sangat baik untuk keamanan.

3. Binary Statis (CGO_ENABLED=0)

Untuk menjalankan aplikasi Go di image scratch atau distroless, aplikasi tersebut harus berupa static binary (tidak memiliki dependensi eksternal seperti libc).

Anda dapat mencapainya dengan mengatur variabel lingkungan CGO_ENABLED=0 saat melakukan go build. Ini juga membantu mengurangi ukuran binary.

4. Jalankan sebagai Non-Root

Menjalankan container sebagai root adalah risiko keamanan besar. Jika terjadi container breakout, penyerang bisa mendapatkan akses root di host machine. Kepatuhan seperti SOC2 dan PCI-DSS secara eksplisit melarang eksekusi container sebagai root.

  • Cara Mudah: Gunakan base image distroless:nonroot yang sudah dikonfigurasi untuk berjalan sebagai non-root secara otomatis.

  • Cara Manual (jika pakai scratch): Buat user di tahap builder (RUN adduser -D appuser)lalu salin file /etc/passwd ke tahap final, dan gunakan USER appuser.


2. Mengoptimalkan Kecepatan Build (Layer Caching)

Kecepatan build 2 detik vs 2 menit bergantung pada seberapa baik Anda memanfaatkan Docker layer caching. Aturan utamanya adalah: urutan perintah COPY dan RUN sangat penting.

Strukturkan Dockerfile Anda dari lapisan yang paling jarang berubah ke yang paling sering berubah.

  1. Dependensi Sistem: Install ca-certificates atau tzdata (jarang berubah).

  2. Dependensi Go: Salin go.mod dan go.sum terlebih dahulu.

  3. Download Dependensi: Jalankan go mod download. Docker akan menyimpan lapisan ini.

  4. Salin Kode Sumber: Baru salin sisa kode sumber aplikasi Anda (COPY . .).

  5. Build: Jalankan go build.

Dengan cara ini, jika Anda hanya mengubah kode aplikasi (Langkah 4) tanpa mengubah dependensi (Langkah 2), Docker akan menggunakan kembali cache dari Langkah 3 (go mod download) dan tidak perlu mengunduh ulang semua library.


3. Optimasi Tambahan

Mengurangi Ukuran Binary

Gunakan ldflags saat membangun untuk menghapus simbol debug dan informasi DWARF, yang dapat mengurangi ukuran binary secara signifikan.

go build -ldflags="-w -s"

Build-Time Variables

Suntikkan informasi versi, commit, atau waktu build ke dalam binary Anda menggunakan ARG dan ldflags. Ini sangat berguna untuk monitoring dan debugging.


4. Dockerfile Produksi Lengkap

Berikut adalah Dockerfile lengkap yang menggabungkan semua praktik terbaik: multi-stage, distroless:nonroot, caching dependensi, binary statis, dan build-time variables.

Hasil Akhir

Dengan mengikuti struktur ini, Anda akan mendapatkan image Docker untuk aplikasi Go Anda yang:

  • Berukuran 8-12MB (dibandingkan 850MB+).

  • Build dalam 12 detik (setelah cache awal).

  • Sangat aman, berjalan sebagai non-root, dan memiliki attack surface minimal yang lolos audit SOC2 dan ISO27001.

Last updated