Membangun Image dan menjalankannya di lokal hanyalah setengah perjalanan. Tujuan akhirnya adalah aplikasi berjalan di server production yang bisa diakses publik, stabil, dan mudah di-update. Di artikel ini kita bahas strategi deployment Docker ke VPS atau cloud server secara praktis.
Persiapan Server
Asumsikan kamu punya VPS Ubuntu 22.04. Langkah pertama adalah install Docker:
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# Verifikasi
docker --version
docker compose version
Struktur Project di Server
/var/www/blog-api/
├── docker-compose.yml
├── docker-compose.prod.yml
├── .env # environment variables (tidak di Git)
└── nginx/
└── default.conf
docker-compose.prod.yml
version: '3.8'
services:
api:
image: ghcr.io/username/blog-api:latest
restart: always
environment:
- NODE_ENV=production
- PORT=3000
- DATABASE_URL=${DATABASE_URL}
- JWT_SECRET=${JWT_SECRET}
depends_on:
db:
condition: service_healthy
networks:
- app_network
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app_network
nginx:
image: nginx:alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- certbot_certs:/etc/letsencrypt
- certbot_www:/var/www/certbot
depends_on:
- api
networks:
- app_network
volumes:
postgres_data:
certbot_certs:
certbot_www:
networks:
app_network:
Konfigurasi Nginx
nginx/default.conf:
server {
listen 80;
server_name api.namakamu.com;
# Untuk certbot verification
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name api.namakamu.com;
ssl_certificate /etc/letsencrypt/live/api.namakamu.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.namakamu.com/privkey.pem;
client_max_body_size 20M;
location / {
proxy_pass http://api:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
SSL dengan Certbot di Docker
# Jalankan dulu dengan HTTP saja untuk verifikasi domain
docker compose -f docker-compose.prod.yml up -d nginx
# Request sertifikat SSL
docker run --rm \
-v certbot_certs:/etc/letsencrypt \
-v certbot_www:/var/www/certbot \
certbot/certbot certonly --webroot \
--webroot-path=/var/www/certbot \
-d api.namakamu.com \
--email kamu@contoh.com \
--agree-tos --non-interactive
# Sekarang aktifkan konfigurasi HTTPS dan restart nginx
docker compose -f docker-compose.prod.yml restart nginx
Deployment Workflow
Pertama Kali Deploy
# Di server
cd /var/www/blog-api
# Clone atau copy file compose
git clone https://github.com/username/blog-api-deploy .
# atau scp docker-compose.prod.yml ke server
# Buat .env
cp .env.example .env
nano .env # isi dengan nilai production
# Login ke registry
docker login ghcr.io -u username -p $GITHUB_TOKEN
# Pull image terbaru dan jalankan
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
# Jalankan migrasi database
docker compose -f docker-compose.prod.yml exec api npx prisma migrate deploy
Update Deployment (Zero-Downtime)
# Pull image terbaru
docker compose -f docker-compose.prod.yml pull api
# Restart dengan image baru (ada jeda sebentar)
docker compose -f docker-compose.prod.yml up -d api
# Lihat apakah sudah jalan
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs api --tail 50
Monitoring dan Maintenance
# Lihat penggunaan resource semua container
docker stats
# Lihat log secara live
docker compose -f docker-compose.prod.yml logs -f
# Masuk ke container untuk debugging
docker compose -f docker-compose.prod.yml exec api sh
# Bersihkan resource yang tidak terpakai
docker system prune -f # hapus container/network tidak terpakai
docker system prune -af # + hapus image tidak terpakai
docker system df # lihat penggunaan disk Docker
Otomatis Deploy dengan GitHub Actions
.github/workflows/deploy.yml:
name: Deploy to Production
on:
push:
tags: ['v*']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: $
username: $
key: $
script: |
cd /var/www/blog-api
docker compose -f docker-compose.prod.yml pull api
docker compose -f docker-compose.prod.yml up -d api
docker compose -f docker-compose.prod.yml exec -T api npx prisma migrate deploy
docker system prune -f
Kesimpulan
Deployment Docker ke production jauh lebih reproducible dan terdokumentasi dibanding setup manual. Dengan docker-compose.prod.yml, Nginx, dan Certbot dalam container, seluruh stack bisa di-reproduce di server manapun hanya dari konfigurasi file.
Di artikel berikutnya, kita bahas Docker untuk development environment — cara membuat setup lokal yang konsisten untuk seluruh tim menggunakan Docker Compose.
Kiki/🎮🍉⌨️🍩💻