Saat ini Docker adalah salah satu tools yang populer di kalangan developer dan menjadi standar industri untuk mendeploy aplikasi ke production, tetapi tidak semua paham menggunakan Docker dengan baik. Contohnya adalah masih banyak developer yang masih membuat Dockerfile tanpa memperhatikan prinsip optimasi, keamanan, dan efisiensi.
Docker diciptakan untuk memudahkan proses packaging aplikasi sehingga dapat dijalankan secara konsisten di berbagai environment. Namun dalam praktiknya, Dockerfile yang dibuat tanpa standar akan menghasilkan image yang:
- berukuran sangat besar,
- sulit di-cache,
- tidak stabil akibat ketergantungan versi,
- lambat di-build,
- memiliki risiko keamanan tinggi,
- sulit dipelihara jangka panjang.
Mengapa Best Practice Docker Penting dalam Development Modern?
Tanpa menerapkan prinsip-prinsip optimasi, workflow DevOps bisa kacau: build pipeline menjadi lambat, image tidak reproducible, dan debugging menjadi sulit. Pada perusahaan besar, setiap detik waktu build berarti uang.
Sebaliknya, mengikuti best practice akan memberikan manfaat berikut:
Manfaat Teknis
- Build lebih cepat karena caching optimal
- Image lebih kecil → lebih cepat di-push/pull
- Deployment jadi lebih stabil
- Konsistensi environment terjaga
Manfaat Bisnis
- Menghemat biaya cloud (less storage & less bandwidth)
- Mengurangi risiko downtime produksi
- Mempercepat delivery cycle tim engineering
- Menjaga keamanan aplikasi
Berikut beberapa hal yang perlu diperhatikan saat menggunakan Docker, semuanya akan dibahas secara detail dan aplikatif.
1. Gunakan Base Image yang Tepat dan Terpercaya
Langkah pertama yang perlu dilakukan adalah memilih base image yang tepat untuk projek kita. Ketika memilih base image, pastikan untuk mengambil dari sumber yang terpercaya, misalnya maintainer resmi dari tools yang terkait atau yang sudah terverifikasi oleh Docker inc. Pastikan juga ukurannya sesuai agar tidak terlalu banyak built-in tools atau library yang tidak perlu.
# ❌ menggunakan image ubuntu dan install nodejs secara manual
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nodejs
# ✅ menggunakan image node yang dimaintain oleh nodejs dan sudah diterverikasi oleh Docker
FROM node:20-alpine
Memilih image generik seperti ubuntu:latest menyebabkan:
- image menjadi sangat besar,
- dependency sulit dikontrol,
- security footprint lebih besar,
- build time bertambah lama.
Mengapa Alpine sering direkomendasikan?
- ukurannya sangat kecil (±5MB),
- keamanannya lebih terkontrol,
- dependency minimal sehingga ringan dan cepat.
2. Gunakan Versi Image yang spesifik
# ❌ menggunakan image node yang tidak spesifik
FROM node:latest
# ✅ menggunakan image node yang spesifik
FROM node:20-alpine
Ketika kita memilih base image, pastikan kita menggunakan versi yang lebih spesifik. Mengapa harus begitu?
Sebagai contoh, jika kita mempunyai aplikasi Node Js yang berjalan dengan Node Js versi 20, tetapi kita menggunakan tag latest node:latest, ketika kita rebuild ulang image, tidak ada jaminan bahwa base image yang di-download berisi Node Js versi yang sama. Hal ini akan menjadi masalah jika kode atau library yang ada tidak kompatibel dengan versi node yang baru.
3. Manfaatkan Multi-Stage Build untuk Memperkecil Image
Beberapa aplikasi membutuhkan tools yang berbeda ketika proses build dan running. Sebagai contoh aplikasi client side, seperti React/Vue/Angular membutuhkan node dan npm untuk proses build saja. Untuk menjalankan aplikasi tersebut kita hanya perlu menggunakan nginx yang akan men-serve file static dari proses build. Dengan adanya multi stage build, size image akhir yang perlu dijalankan menjadi lebih kecil karena kita tidak perlu menyimpan node dan npm di dalam image.
# Build stage
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine
EXPOSE 80
COPY –from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
4. Mengoptimalkan Build Cache agar Proses Build Lebih Cepat
Docker menggunakan sistem layer dalam mem-build sebuah image, dimana setiap instruksi dalam Dockerfile akan membentuk layer baru. Jika tidak ada perubahan pada sebuah layer dan layer sebelumnya, docker akan menggunakan cache agar mempercepat proses build.
Oleh karena itu, penting untuk menempatkan instruksi yang jarang berubah di bagian atas Dockerfile, dan instruksi yang sering berubah di bagian bawah. Sebagai contoh, dalam aplikasi Node Js, proses instalasi library dengan npm install hanya akan dijalankan ulang jika file package*.json berubah, selain itu setiap kali kita rebuild image, docker akan menggunakan cache.
FROM node:14
# Set working directory
WORKDIR /app
# Layer 1: Copy package files
COPY package*.json ./
# Layer 2: Install dependencies
RUN npm install
# Layer 3: Copy application code
COPY . .
# Layer 4: Build application
RUN npm run build
# Command to run the application
CMD [“npm”, “start”]
5. Gabungkan Multiple Instruksi Menjadi Satu untuk Mengurangi Layer
Dalam membuat Dockerfile, setiap instruksi RUN akan menciptakan layer baru pada image. Semakin banyak layer yang dibuat, semakin kompleks manajemen cache-nya. Oleh karena itu, sangat penting untuk menggabungkan perintah yang berkaitan menjadi satu instruksi.
# ❌ multiple instruksi
RUN npm install
RUN npm run build
# ✅ single instruksi
RUN npm install && npm run build
6. Menggunakan .dockerignore untuk Menghindari File yang Tidak Dibutuhkan
Ketika membuild sebuah image, seringkali masuk beberapa file yang sebenarnya tidak dibutuhkan lagi. Agar image menjadi lebih kecil, kita bisa membuat file .dockerignore untuk mengecualikan file yang tidak perlu dimasukan ke dalam image.
Beberapa contoh file/folder yang biasa di-exclude di dalam projek adalah:
# Dependencies
node_modules
npm-debug.log
yarn-debug.log
yarn-error.log
# Git History
.git
# Environment
.env
.env.local
.env.*.local
# Testing
coverage
tests
__tests__
*.test.js
# Development
.vscode
.idea
*.swp
*.swo
# Build Output
dist
build
7. Hindari Penggunaan Root User dalam Container
Menjalankan container sebagai root user bisa menambah resiko keamanan. Jika ada kerentanan pada aplikasi, peretas bisa saja mendapatkan akses root ke host system. Untuk itu sebaiknya kita membuat user non-root khusus untuk menjalankan aplikasi di dalam container.
“`dockerfile
FROM node:18-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
# Ubah ownership directory ke user ‘node’ yang sudah built in dari base image
RUN chown -R node:node /usr/src/app
EXPOSE 3000
# Ganti user dari root ke user ‘node’
USER node
CMD [ “node”, “server.js” ]
Kesimpulan
Dari beberapa penjelasan diatas, kita bisa melihat bahwa ada beberapa hal yang perlu diperhatikan saat menggunakan Docker. Best practice Docker ini penting untuk diterapkan oleh developer, DevOps engineer, maupun tim software engineering yang ingin menjalankan aplikasi dengan stabil di environment production. Mulai dari pemilihan base image, optimasi layer, build cache, multi-stage build, hingga praktik keamanan dari sisi base image, build efisiensi, dan keamanan.





