Membangun API dalam Docker Image Kurang dari 20MB: Panduan Lengkap
Di era mikroservis dan containerization, ukuran image Docker menjadi krusial. Image yang lebih kecil berarti waktu deploy yang lebih cepat, pemanfaatan sumber daya yang lebih efisien, dan attack surface yang lebih rendah. Dalam panduan ini, kita akan membahas cara membangun API yang berjalan di dalam image Docker yang berukuran kurang dari 20MB. Ini adalah panduan langkah demi langkah yang ditujukan untuk pengembang backend, DevOps engineer, dan siapa pun yang ingin mengoptimalkan ukuran image Docker mereka.
Mengapa Ukuran Docker Image Penting?
Sebelum kita membahas detail teknisnya, mari kita pahami mengapa ukuran image Docker begitu penting:
- Waktu Deploy Lebih Cepat: Image yang lebih kecil dapat diunduh dan dijalankan lebih cepat, yang mengurangi waktu deploy secara signifikan. Ini sangat penting dalam lingkungan continuous integration dan continuous delivery (CI/CD).
- Penggunaan Sumber Daya yang Lebih Efisien: Image yang lebih kecil mengkonsumsi lebih sedikit ruang disk dan memori, memungkinkan Anda untuk menjalankan lebih banyak container pada hardware yang sama.
- Keamanan yang Ditingkatkan: Image yang lebih kecil cenderung memiliki lebih sedikit dependensi dan attack surface yang lebih kecil, yang mengurangi risiko kerentanan keamanan.
- Biaya Infrastruktur yang Lebih Rendah: Dengan penggunaan sumber daya yang lebih efisien, Anda dapat mengurangi biaya infrastruktur secara keseluruhan.
- Skalabilitas yang Lebih Baik: Image yang lebih kecil memungkinkan skalabilitas yang lebih cepat dan lebih efisien karena container dapat di-deploy dan di-scale dengan cepat.
Teknik untuk Mengurangi Ukuran Docker Image
Ada beberapa teknik yang dapat Anda gunakan untuk mengurangi ukuran image Docker Anda. Berikut adalah beberapa yang paling efektif:
- Gunakan Base Image yang Minimal: Pilih base image yang sekecil mungkin. Alpine Linux, distroless, dan scratch adalah pilihan populer untuk image yang minimal.
- Multi-Stage Builds: Gunakan multi-stage builds untuk memisahkan proses kompilasi dari lingkungan runtime. Ini memungkinkan Anda untuk hanya menyertakan artefak yang diperlukan dalam image akhir.
- Optimalkan Dependensi: Hanya instal dependensi yang benar-benar diperlukan oleh aplikasi Anda. Hapus dependensi yang tidak terpakai atau redundan.
- Bersihkan Cache dan File Sementara: Hapus cache paket dan file sementara setelah instalasi untuk mengurangi ukuran image.
-
Gunakan .dockerignore: Buat file
.dockerignore
untuk mengecualikan file dan direktori yang tidak perlu dari proses build. - Layer Caching: Manfaatkan layer caching Docker untuk mempercepat proses build dan mengurangi ukuran image.
- Kompresi: Pertimbangkan untuk menggunakan kompresi untuk mengurangi ukuran file dalam image Anda.
Studi Kasus: Membangun API Go dengan Alpine Linux
Mari kita lihat contoh konkret bagaimana membangun API Go dengan Alpine Linux untuk menghasilkan image Docker yang sangat kecil.
Prasyarat
- Go (versi 1.16 atau lebih baru)
- Docker
Langkah 1: Membuat API Go Sederhana
Pertama, kita akan membuat API Go sederhana yang mengembalikan pesan “Hello, World!”.
Buat direktori untuk proyek Anda:
mkdir go-api
cd go-api
Buat file main.go
:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
fmt.Println("Server listening on port 8080")
http.ListenAndServe(":8080", nil)
}
Inisialisasi modul Go:
go mod init example.com/go-api
Langkah 2: Membuat Dockerfile
Selanjutnya, kita akan membuat Dockerfile
untuk membangun image Docker kita.
Buat file bernama Dockerfile
di direktori proyek Anda:
# Stage 1: Build the Go application
FROM golang:1.17-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
# Stage 2: Create a minimal runtime image
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]
Mari kita uraikan Dockerfile
ini:
-
Stage 1 (builder):
- Menggunakan
golang:1.17-alpine
sebagai base image. - Menetapkan direktori kerja menjadi
/app
. - Menyalin file
go.mod
dango.sum
untuk mengunduh dependensi. - Menyalin semua file sumber.
- Membangun aplikasi Go menjadi executable bernama
main
.
- Menggunakan
-
Stage 2 (runtime):
- Menggunakan
alpine:latest
sebagai base image minimal. - Menetapkan direktori kerja menjadi
/app
. - Menyalin executable
main
dari stage builder. - Mengekspos port 8080.
- Menjalankan executable
main
saat container dimulai.
- Menggunakan
Langkah 3: Membangun Docker Image
Sekarang, kita akan membangun image Docker menggunakan Dockerfile
kita.
Jalankan perintah berikut di direktori proyek Anda:
docker build -t go-api .
Langkah 4: Memeriksa Ukuran Image
Setelah image dibangun, kita dapat memeriksa ukurannya.
Jalankan perintah berikut:
docker images go-api
Anda akan melihat output yang mirip dengan ini:
REPOSITORY TAG IMAGE ID CREATED SIZE
go-api latest xxxxxxxxxxxx 5 seconds ago 8.5MB
Seperti yang Anda lihat, ukuran image adalah sekitar 8.5MB, yang jauh di bawah target 20MB kita!
Langkah 5: Menjalankan Container
Terakhir, kita akan menjalankan container untuk menguji API kita.
Jalankan perintah berikut:
docker run -p 8080:8080 go-api
Sekarang, Anda dapat mengakses API Anda di http://localhost:8080
. Anda akan melihat pesan “Hello, World!”.
Contoh Lain: API Python dengan Alpine Linux dan uWSGI
Mari kita lihat contoh lain, kali ini menggunakan Python, Alpine Linux, dan uWSGI.
Prasyarat
- Python (versi 3.6 atau lebih baru)
- Docker
Langkah 1: Membuat API Python Sederhana dengan Flask
Kita akan membuat API Python sederhana menggunakan Flask.
Buat direktori untuk proyek Anda:
mkdir python-api
cd python-api
Buat file app.py
:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "Hello, World!
"
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8080)
Buat file requirements.txt
:
Flask
Langkah 2: Membuat Dockerfile
Buat file bernama Dockerfile
di direktori proyek Anda:
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "app.py"]
Mari kita uraikan Dockerfile
ini:
-
Base Image: Menggunakan
python:3.9-alpine
sebagai base image. -
Direktori Kerja: Menetapkan direktori kerja menjadi
/app
. -
Instalasi Dependensi: Menyalin
requirements.txt
dan menginstal dependensi menggunakanpip
. Opsi--no-cache-dir
membantu mengurangi ukuran image. - Menyalin Kode: Menyalin semua file sumber.
- Mengekspos Port: Mengekspos port 8080.
-
Perintah: Menjalankan aplikasi Python menggunakan
python app.py
.
Langkah 3: Membangun Docker Image
Bangun image Docker menggunakan perintah berikut:
docker build -t python-api .
Langkah 4: Memeriksa Ukuran Image
Periksa ukuran image:
docker images python-api
Ukuran image ini mungkin lebih besar dari contoh Go karena Python dan Flask memiliki lebih banyak dependensi. Namun, dengan optimasi lebih lanjut (seperti menggunakan uWSGI atau Gunicorn sebagai server aplikasi dan mengoptimalkan dependensi), Anda dapat mengurangi ukurannya secara signifikan.
Optimasi Lanjutan
Selain teknik dasar yang telah kita bahas, ada beberapa optimasi lanjutan yang dapat Anda terapkan:
- Menggunakan Distroless Images: Distroless images adalah image yang hanya berisi aplikasi Anda dan dependensi runtime-nya. Mereka tidak menyertakan manajer paket, shell, atau program lain yang tidak diperlukan. Ini secara signifikan mengurangi ukuran image dan meningkatkan keamanan.
- Static Linking: Untuk bahasa seperti Go, Anda dapat menggunakan static linking untuk menyertakan semua dependensi dalam executable Anda. Ini menghilangkan kebutuhan akan dependensi eksternal pada sistem runtime.
- Menggunakan UPX: UPX adalah executable packer yang dapat mengkompresi executable dan mengurangi ukurannya. Ini dapat berguna untuk mengurangi ukuran image secara keseluruhan.
- Menggunakan BuildKit: BuildKit adalah mesin build yang lebih canggih untuk Docker yang menawarkan fitur seperti parallel build, layer caching yang lebih baik, dan kemampuan untuk mengekspor artefak build ke registry yang berbeda.
- Mengoptimalkan Konfigurasi Aplikasi: Pastikan konfigurasi aplikasi Anda dioptimalkan untuk produksi. Nonaktifkan fitur debug, minimalkan logging, dan gunakan kompresi untuk aset statis.
Praktik Terbaik untuk Dockerfile
Berikut adalah beberapa praktik terbaik untuk menulis Dockerfile
yang efisien:
-
Urutkan Perintah: Urutkan perintah dalam
Dockerfile
Anda agar perintah yang jarang berubah berada di atas. Ini memungkinkan Docker untuk memanfaatkan layer caching dengan lebih efektif. -
Gunakan Multi-Line Statements: Gunakan multi-line statements untuk membuat
Dockerfile
Anda lebih mudah dibaca. -
Beri Komentar pada Dockerfile: Tambahkan komentar untuk menjelaskan apa yang dilakukan setiap perintah. Ini membuat
Dockerfile
Anda lebih mudah dipahami dan dipelihara. - Hindari Menjalankan Aplikasi sebagai Root: Hindari menjalankan aplikasi Anda sebagai root. Buat pengguna khusus untuk menjalankan aplikasi Anda untuk meningkatkan keamanan.
-
Gunakan
COPY
daripadaADD
: Gunakan perintahCOPY
untuk menyalin file ke image Anda. PerintahADD
memiliki beberapa fitur tambahan yang dapat menyebabkan masalah tak terduga.
Kesimpulan
Membangun API dalam image Docker yang berukuran kurang dari 20MB adalah tantangan yang layak dilakukan. Dengan menggunakan teknik yang tepat, seperti memilih base image minimal, menggunakan multi-stage builds, dan mengoptimalkan dependensi, Anda dapat secara signifikan mengurangi ukuran image Anda dan mendapatkan manfaat dari waktu deploy yang lebih cepat, penggunaan sumber daya yang lebih efisien, dan keamanan yang ditingkatkan. Ingatlah untuk selalu mengoptimalkan Dockerfile
Anda dan menerapkan praktik terbaik untuk memastikan image Anda sekecil dan seefisien mungkin.
Semoga panduan ini bermanfaat! Selamat mencoba dan semoga berhasil dalam upaya containerization Anda!
“`