Pertama kali deploy aplikasi pakai Docker di VPS, saya langsung kena masalah klasik — jalan di lokal, error di server. Setelah pakai Docker, masalah itu hilang karena environment-nya dijamin sama. Di sini saya share cara deploy aplikasi web pakai Docker di VPS Ubuntu 24.04, dari instalasi sampai Nginx + SSL.
Kenapa sih banyak developer pakai Docker?
Yang perlu disiapkan:
SSH ke VPS kamu, lalu install Docker:
#
Update package index
sudo apt
update && sudo apt upgrade -y
# Instal dependencies yang dibutuhkan
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# Tambahkan Docker GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg
--dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Tambahkan Docker repository
echo "deb [arch=$(dpkg
--print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Instal Docker Engine dan Docker Compose
sudo apt
update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Cek apakah Docker berjalan dengan baik:
# Cek versi Docker
docker
--version
# Cek Docker Compose
docker compose version
# Jalankan test container
sudo docker run hello-world
Supaya nggak perlu sudo terus, tambahkan user ke grup docker:
sudo usermod -aG docker $USER
newgrp docker
Dockerfile adalah blueprint yang mendefinisikan bagaimana aplikasi kamu dikemas ke dalam container. Berikut contoh Dockerfile untuk aplikasi Node.js dengan Express:
# Gunakan base image Node.js LTS
FROM node:20-alpine
#
Set working directory
WORKDIR /app
# Copy package files terlebih dahulu (untuk optimasi cache)
COPY package*.json ./
# Instal dependencies
RUN npm ci
--only=production
# Copy source code
COPY . .
# Expose port aplikasi
EXPOSE 3000
# Non-root user untuk keamanan
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser
USER appuser
# Jalankan aplikasi
CMD ["node", "server.js"]
Untuk aplikasi PHP, Dockerfile-nya akan berbeda:
FROM php:8.3-fpm-alpine
# Instal extensions yang dibutuhkan
RUN docker-php-ext-install pdo pdo_mysql opcache
# Konfigurasi OPcache untuk performa
RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini
RUN echo "opcache.memory_consumption=128" >> /usr/local/etc/php/conf.d/opcache.ini
WORKDIR /var/www/html
COPY . .
#
Set permission yang benar
RUN chown -R www-data:www-data /var/www/html
EXPOSE 9000
CMD ["php-fpm"]
Docker Compose memungkinkan kamu mendefinisikan dan menjalankan multi-container application. Buat file docker-compose.yml:
version: '3.8'
services:
app:
build: .
container_name: webapp
restart: unless-stopped
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=3306
- DB_NAME=webapp_db
- DB_USER=webapp_user
- DB_PASS=SecurePassword123!
depends_on:
db:
condition: service_healthy
networks:
- app-network
volumes:
- app-data:/app/uploads
db:
image: mysql:8.0
container_name: webapp_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: RootPass123!
MYSQL_DATABASE: webapp_db
MYSQL_USER: webapp_user
MYSQL_PASSWORD: SecurePassword123!
volumes:
- db-data:/var/lib/mysql
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: webapp_redis
restart: unless-stopped
networks:
- app-network
volumes:
db-data:
app-data:
networks:
app-network:
driver: bridge
Konfigurasi di atas mendefinisikan tiga layanan: aplikasi web, database MySQL, dan Redis untuk caching. Semuanya terhubung melalui network internal yang terisolasi.
Sekarang saatnya membangun dan menjalankan semua container:
# Build dan start semua container
docker compose up -d
--build
# Lihat status container
docker compose ps
# Lihat log aplikasi
docker compose logs -f app
# Lihat log semua service
docker compose logs -f
Gunakan flag -d agar container berjalan di background. Flag --build memaksa rebuild image meskipun sudah ada cache sebelumnya.
Nginx akan bertindak sebagai reverse proxy yang menerima request dari internet dan meneruskannya ke container aplikasi. Instal Nginx di host:
sudo apt install -y nginx
Buat konfigurasi virtual host di /etc/nginx/sites-available/webapp:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 90;
}
# Cache static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2)$ {
proxy_pass http://127.0.0.1:3000;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Aktifkan konfigurasi dan restart Nginx:
sudo ln -s /etc/nginx/sites-available/webapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
SSL wajib untuk keamanan dan SEO. Gunakan Certbot untuk mendapatkan sertifikat gratis dari Let's Encrypt:
# Instal Certbot
sudo apt install -y certbot python3-certbot-nginx
# Dapatkan dan pasang sertifikat SSL
sudo certbot
--nginx -d yourdomain.com -d www.yourdomain.com
# Cek auto-renewal
sudo certbot renew
--dry-run
Certbot akan otomatis mengubah konfigurasi Nginx untuk mengarahkan HTTP ke HTTPS dan menambahkan konfigurasi SSL yang aman.
Setelah aplikasi berjalan, lakukan monitoring rutin untuk menjaga stabilitas:
# Cek resource usage container
docker stats
# Restart service yang bermasalah
docker compose restart app
#
Update image ke versi terbaru
docker compose pull
docker compose up -d
# Bersihkan image dan container yang tidak terpakai
docker system prune -a
--volumes
# Backup database
docker exec webapp_db mysqldump -u root -p'RootPass123!' webapp_db > backup_$(date +%Y%m%d).sql
Buat cron job untuk backup otomatis database setiap hari:
# Tambahkan di crontab (crontab -e)
0 2 * * * docker exec webapp_db mysqldump -u root -p'RootPass123!' webapp_db | gzip > /backups/db_$(date +\%Y\%m\%d).sql.gz
Beberapa langkah keamanan yang sering dilupakan tapi sangat penting:
trivy image yourapp:latest untuk menemukan CVE pada dependencies.Berikut beberapa pitfalls yang sering ditemui saat pertama kali deploy dengan Docker:
.env file dan pastikan masuk ke .gitignore.node_modules, .git, dan .env harus di-ignore agar image tidak bengkak.Deploy aplikasi web dengan Docker di VPS Ubuntu 24.04 bukanlah hal yang rumit jika kamu mengikuti langkah-langkah yang terstruktur. Docker memberikan konsistensi, kemudahan scaling, dan isolasi yang sulit dicapai dengan cara deployment tradisional. Dengan kombinasi Docker Compose untuk orchestration, Nginx sebagai reverse proxy, dan Let's Encrypt untuk SSL, kamu memiliki setup production yang solid dan profesional.
Mulailah dari project kecil, pahami konsep container, dan secara bertahap terapkan best practices yang sudah dibahas. Selamat mencoba dan happy deploying!