Dockerfile Gin untuk Local Development dan Stage Lainnya
Dalam pengembangan aplikasi backend menggunakan Golang + Gin, Docker sering kali langsung diasosiasikan dengan production. Padahal, Dockerfile yang baik justru harus mampu mendukung seluruh lifecycle aplikasi, mulai dari:
- Local development
- Testing
- Staging
- Production
Kesalahan umum adalah menggunakan satu Dockerfile yang sama untuk semua stage, sehingga:
- Local development jadi lambat
- Image production jadi besar
- Workflow tim tidak efisien
Artikel ini membahas bagaimana menyusun Dockerfile untuk Gin dengan pendekatan yang tepat untuk local development dan stage lainnya.
Prinsip Dasar Dockerfile untuk Gin
Dockerfile untuk aplikasi Gin pada dasarnya melakukan:
- Menentukan base image Go
- Mengunduh dependency
- Build binary
- Menjalankan aplikasi
Contoh paling dasar:
FROM golang:1.21
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o app
EXPOSE 8080
CMD ["./app"]
Dockerfile ini valid, tapi tidak ideal jika dipakai untuk semua kebutuhan.
Dockerfile untuk Local Development
Tujuan Local Development
Pada tahap ini, fokus utama adalah:
- Perubahan kode cepat
- Tidak rebuild image setiap save
- Mendukung hot reload
Pendekatan yang Tepat
Gunakan:
- Volume mount
- Tool hot reload (contoh:
air) - Image yang tidak terlalu dioptimasi
Contoh Dockerfile (Local Dev)
FROM golang:1.21
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go install github.com/air-verse/air@latest
CMD ["air"]
Dockerfile ini sengaja sederhana dan tidak mengejar ukuran image.
Dockerfile untuk Testing Stage
Untuk testing (unit/integration test), kita ingin:
- Environment konsisten
- Test berjalan otomatis
- Tidak menjalankan server
Contoh Dockerfile Testing
FROM golang:1.21
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
CMD ["go", "test", "./..."]
Biasanya Dockerfile ini dipanggil di CI pipeline.
Dockerfile untuk Production (Multi-Stage Build)
Kenapa Multi-Stage Build?
Jika Dockerfile dev dipakai di production:
- Image besar
- Banyak tool tidak diperlukan
- Surface attack lebih luas
Solusinya adalah multi-stage build.
Contoh Dockerfile Production
# Stage build
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app
# Stage runtime
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/app .
EXPOSE 8080
CMD ["./app"]
Hasilnya:
- Image jauh lebih kecil
- Tidak ada compiler Go di runtime
- Lebih aman dan cepat
Menggabungkan dengan Docker Compose
Biasanya setiap stage dipasangkan dengan Compose yang berbeda:
docker-compose.dev.ymldocker-compose.test.ymldocker-compose.prod.yml
Contoh untuk local dev:
services:
api:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
ports:
- "8080:8080"
Ini menjaga separation of concern antar environment.
Kesalahan Umum yang Harus Dihindari
❌ Satu Dockerfile untuk semua stage
❌ Mengoptimasi Dockerfile dev seperti production
❌ Menggunakan latest sebagai base image
❌ Menjalankan hot reload di production
Ringkasan
| Stage | Fokus | Pendekatan |
|---|---|---|
| Local Dev | Kecepatan | Volume + hot reload |
| Testing | Konsistensi | Run test di container |
| Staging | Mirip prod | Multi-stage build |
| Production | Ringan & aman | Multi-stage minimal |
Penutup
Dockerfile bukan sekadar alat untuk membungkus aplikasi.
Dockerfile adalah bagian dari workflow engineering.
Dengan memisahkan Dockerfile berdasarkan stage:
- Local development lebih nyaman
- CI lebih stabil
- Production lebih aman
Dan yang paling penting: engineer tidak melawan tool-nya sendiri.