Beranda Blog Store
Linux

Docker Compose untuk Pemula: Menjalankan Aplikasi Web, Database, dan Reverse Proxy dalam Satu Berkas

23 Agu 2026 Hartono 5 menit baca 4 Dilihat

Kalau Anda sudah nyaman dengan satu kontainer tetapi bingung saat aplikasinya butuh database dan proxy, Rekan ArtonLabs, tulisan ini untuk Anda.

Docker sering diperkenalkan dengan satu kontainer, dan kesannya selesai di situ. Padahal aplikasi nyata hampir selalu lebih dari satu bagian: aplikasi web, database, mungkin cache, dan sesuatu di depan yang mengurus HTTPS. Docker Compose menuliskan semuanya dalam satu berkas YAML, dan satu perintah menghidupkan seluruhnya. Tulisan ini membangun susunan yang paling umum: aplikasi web, PostgreSQL, dan reverse proxy, dengan kebiasaan-kebiasaan yang membuatnya aman dipakai di server sungguhan.

Daftar Isi

Memasang Docker dan Compose

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
newgrp docker
docker compose version

Compose kini adalah sub-perintah docker compose (dengan spasi), bukan lagi docker-compose. Menambahkan pengguna ke grup docker praktis, tetapi ingat bahwa anggota grup itu secara efektif setara root di mesin tersebut; jangan berikan ke pengguna yang tidak Anda percayai sepenuhnya.

Berkas compose.yaml Pertama

services:
  web:
    build: .
    restart: unless-stopped
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
    expose:
      - "8000"

  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: aplikasi
      POSTGRES_USER: aplikasi
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U aplikasi"]
      interval: 10s
      retries: 5

volumes:
  dbdata:

Beberapa hal yang disengaja. Tidak ada kunci version:, karena Compose modern tidak membutuhkannya. expose dipakai untuk web, bukan ports, sehingga aplikasi hanya bisa dijangkau oleh kontainer lain, bukan dari internet. depends_on dengan condition: service_healthy membuat aplikasi menunggu sampai database benar-benar siap menerima koneksi, bukan sekadar sudah dimulai. Di dalam jaringan Compose, aplikasi menghubungi database dengan nama layanannya: postgres://aplikasi:...@db:5432/aplikasi.

Volume: Data yang Bertahan

Kontainer bersifat sekali pakai; apa pun yang ditulis di dalamnya hilang saat kontainer dibuat ulang. Volume bernama seperti dbdata hidup di luar kontainer dan bertahan. Aturan kami: semua yang tidak boleh hilang ada di volume bernama atau bind mount ke folder host, dan volume itu masuk jadwal backup. docker volume ls menunjukkan apa yang ada; docker compose down -v menghapusnya, jadi jangan pernah menjalankan itu di produksi tanpa berpikir dua kali.

Variabel Lingkungan dan Rahasia

Sandi database di atas dibaca dari berkas .env di folder yang sama, yang tidak masuk Git. Untuk aplikasi, env_file: .env memuat seluruh berkas. Jangan menulis rahasia langsung di compose.yaml yang di-commit. Untuk kebutuhan yang lebih ketat, Compose mendukung secrets yang dipasang sebagai berkas di dalam kontainer.

Reverse Proxy dan HTTPS

Ada dua pilihan. Kalau host sudah menjalankan Nginx (misalnya dikelola VinzaPanel), cukup buka port aplikasi ke localhost dengan ports: ["127.0.0.1:8000:8000"] dan biarkan Nginx host yang meneruskan dan mengurus sertifikat; plugin Docker Manager VinzaPanel persis melakukan pemetaan ini ke domain dengan SSL. Kalau seluruhnya di dalam Compose, tambahkan layanan proxy seperti Caddy, yang mengurus Let's Encrypt otomatis:

  proxy:
    image: caddy:2
    restart: unless-stopped
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddydata:/data

dengan Caddyfile berisi contoh.com { reverse_proxy web:8000 }. Dua baris itu memberi HTTPS yang diperbarui otomatis.

Perintah Sehari-hari

docker compose up -d           # hidupkan semua di latar
docker compose ps              # status
docker compose logs -f web     # ikuti log satu layanan
docker compose exec web sh     # masuk ke kontainer
docker compose pull && docker compose up -d   # perbarui image
docker compose down            # hentikan (volume tetap)

Memperbarui dan Kembali ke Versi Sebelumnya

Karena versi image disematkan, memperbarui berarti mengubah satu angka di compose.yaml lalu docker compose up -d; Compose hanya membuat ulang layanan yang berubah. Kalau versi baru bermasalah, kembalikan angkanya dan jalankan perintah yang sama; image lama masih ada di cache lokal sampai Anda menghapusnya. Untuk aplikasi sendiri, beri tag image dengan hash commit atau tanggal, bukan latest, supaya "kembali ke versi kemarin" benar-benar berarti sesuatu. Jalankan docker compose config sebelum up untuk melihat konfigurasi akhir setelah semua variabel diisi; banyak kesalahan ketik tertangkap di situ.

Kebiasaan yang Menyelamatkan

Sematkan versi image (postgres:16, bukan postgres:latest) supaya pembaruan tidak datang tanpa diundang; ini pelajaran yang sama dengan lock file Python. Pakai restart: unless-stopped agar layanan hidup lagi setelah reboot. Jalankan docker system prune secara berkala karena image lama memakan disk dengan cepat. Dan backup volume dengan menghentikan layanan sejenak atau memakai pg_dump dari dalam kontainer, bukan menyalin folder database yang sedang ditulis.

Membangun Image Aplikasi: Dockerfile Minimal

FROM python:3.12-slim
WORKDIR /app
RUN useradd -m app
COPY requirements.lock .
RUN pip install --no-cache-dir -r requirements.lock
COPY . .
USER app
EXPOSE 8000
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "2"]

Tiga kebiasaan di sini: image dasar slim agar kecil, dependensi disalin dan dipasang sebelum kode agar lapisan cache Docker tidak dibangun ulang setiap kali kode berubah, dan USER app agar proses di dalam kontainer tidak berjalan sebagai root. Tambahkan .dockerignore berisi .git, .venv, dan .env supaya tidak ikut masuk image.

Jaringan, Healthcheck, dan Log

Compose membuat satu jaringan privat per proyek; layanan saling menjangkau dengan nama, dan tidak ada yang terlihat dari luar kecuali yang Anda buka lewat ports. Tambahkan healthcheck pada aplikasi juga (misalnya curl -f http://localhost:8000/health) supaya docker compose ps menunjukkan status yang sebenarnya, bukan sekadar "running". Log kontainer dibaca dengan docker compose logs; batasi ukurannya di daemon Docker (/etc/docker/daemon.json dengan log-driver json-file dan max-size), karena log kontainer yang tidak dibatasi adalah penyebab disk penuh yang paling sering kami temui di server Docker.

dengan cara yang sama di laptop dan di server. Itulah nilai Compose. Mulailah dari dua layanan, tambahkan proxy saat butuh HTTPS, dan jaga kebiasaan menyematkan versi serta menaruh data di volume; sisanya akan terasa alami.

Selamat mencoba. Satu berkas Compose yang rapi adalah dokumentasi terbaik untuk tim Anda sendiri; semoga tulisan ini membantu membuatnya.