Docker — Python language guide
Konsep Docker yang perlu kamu pahami: image, layer, container, volume, network, dan compose.
Intisari
- Image = cetakan (statis). Container = instance yang berjalan.
- Tiap instruksi Dockerfile membuat layer; layer di-cache dan digunakan ulang selama input-nya tidak berubah.
- Data di dalam container hilang saat container dihapus. Yang harus bertahan disimpan di volume.
- Compose menjalankan beberapa layanan sekaligus; layanan saling memanggil lewat namanya.
- Kesalahan paling umum: bind ke
127.0.0.1, danPYTHONUNBUFFEREDyang belum diatur.
Kosakata
| Istilah | Artinya |
|---|---|
| Image | Paket read-only berisi kode + dependency + OS minimal |
| Container | Image yang sedang berjalan sebagai proses terisolasi |
| Layer | Satu instruksi Dockerfile = satu layer; di-cache dan dipakai bersama antar image |
| Volume | Penyimpanan yang bertahan setelah container dihapus |
| Network | Jaringan virtual tempat container saling menemukan lewat nama |
| Registry | Tempat menyimpan dan berbagi image (Docker Hub, ECR, GHCR) |
Layer dan cache
FROM python:3.13-slim ← layer 1
WORKDIR /app ← layer 2
COPY pyproject.toml ./ ← layer 3
RUN uv sync --frozen ← layer 4 (mahal)
COPY src/ ./src/ ← layer 5
CMD ["uvicorn", "..."] ← layer 6
Aturannya: begitu satu layer berubah, semua layer sesudahnya dibangun ulang. Karena itu urutkan dari yang paling jarang berubah ke yang paling sering. Kode aplikasi selalu di bawah; dependency selalu di atas.
Instruksi Dockerfile
| Instruksi | Fungsinya |
|---|---|
FROM | Image dasar |
WORKDIR | Direktori kerja (dibuat kalau belum ada) |
COPY | Salin dari konteks build ke image |
RUN | Jalankan perintah saat build |
ENV | Environment variable (build dan runtime) |
ARG | Variabel hanya saat build |
EXPOSE | Dokumentasi port (tidak benar-benar membuka) |
USER | Ganti user |
HEALTHCHECK | Cara Docker menentukan container sehat |
CMD | Perintah default (bisa ditimpa) |
ENTRYPOINT | Perintah yang selalu jalan |
Memilih image dasar
| Tag | Ukuran | Catatan |
|---|---|---|
python:3.13 | ~1 GB | Lengkap; terlalu besar untuk production |
python:3.13-slim | ~150 MB | Pilihan default yang tepat |
python:3.13-alpine | ~50 MB | musl libc — banyak wheel tidak jalan, harus compile |
Hindari Alpine untuk aplikasi Python. Ukurannya memang menggoda, tapi Alpine memakai musl libc alih-alih glibc — sehingga wheel biner (numpy, pandas, cryptography) tidak cocok dan harus dikompilasi dari sumber. Build-nya jadi berkali-kali lipat lebih lama, dan kadang hasilnya justru lebih besar.
Perintah sehari-hari
docker build -t myapp:latest .
docker run --rm -p 8000:8000 --env-file .env myapp:latest
docker run --rm -it myapp:latest bash # masuk ke shell untuk debug
docker ps # container yang jalan
docker logs -f <id> # ikuti log
docker exec -it <id> bash # masuk ke container yang jalan
docker stop <id>
docker images
docker system prune -a # bersihkan yang tidak terpakai
Volume
# Named volume — dikelola Docker, untuk data persisten
docker run -v chroma-data:/chroma/chroma chromadb/chroma
# Bind mount — folder host, untuk development
docker run -v $(pwd)/src:/app/src myapp
Tanpa volume, semua data hilang saat container dihapus. Vector store, database, dan file yang diunggah harus disimpan di named volume. Bind mount cocok untuk development (kode di host langsung terlihat di container), tapi jangan dipakai di production.
Compose
services:
api:
build: .
ports:
- "8000:8000"
env_file: [.env]
depends_on:
chroma:
condition: service_healthy
restart: unless-stopped
chroma:
image: chromadb/chroma:latest
volumes:
- chroma-data:/chroma/chroma
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/v2/heartbeat"]
interval: 10s
retries: 5
volumes:
chroma-data:
docker compose up -d
docker compose logs -f api
docker compose down # hentikan
docker compose down -v # hentikan DAN hapus volume (hati-hati)
Layanan saling memanggil lewat nama
CHROMA_URL = "http://chroma:8000" # 'chroma' = nama layanan di compose
Docker menyediakan DNS internal. Dari dalam container api, hostname
chroma otomatis menunjuk ke container Chroma. Jangan pakai
localhost — di dalam container, itu menunjuk ke container itu sendiri.
Kesalahan yang paling sering
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Tidak bisa diakses dari host | Bind ke 127.0.0.1 | --host 0.0.0.0 |
| Log tidak muncul | Output di-buffer | ENV PYTHONUNBUFFERED=1 |
| Image sangat besar | .venv ikut tersalin, atau tidak multi-stage | .dockerignore + multi-stage |
| Build selalu lambat | COPY . . sebelum install | Salin lockfile dulu |
| Data hilang setelah restart | Tidak ada volume | Tambahkan named volume |
Connection refused antar layanan | Pakai localhost | Pakai nama layanan |
| Layanan start sebelum dependensinya siap | Hanya depends_on | Tambahkan condition: service_healthy |
Debugging
docker run --rm -it myapp bash # jelajahi image
docker exec -it <id> bash # masuk ke container hidup
docker inspect <id> # konfigurasi lengkap
docker stats # pemakaian CPU/memori
docker compose logs --tail=100 -f api
# Kalau container langsung mati
docker run --rm myapp # lihat pesan errornya
docker logs <id>
Checkpoint Fase 6
Target: siapa pun bisa menjalankan proyekmu dengan satu perintah.
git clone https://github.com/kamu/proyek
cd proyek
cp .env.example .env # isi ANTHROPIC_API_KEY
docker compose up
Kalau itu berhasil di mesin orang lain tanpa penjelasan tambahan, checkpoint-nya tercapai.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.