Docker dari Nol hingga Profesional: 100 Contoh dengan Dockerfile, Compose, dan CI/CD

Docker dari Nol hingga Profesional: 100 Contoh dengan Dockerfile, Compose, dan CI/CD

Docker mengemas aplikasi beserta semua yang dibutuhkannya ke dalam kontainer, sehingga perangkat lunak yang sama berjalan dengan cara yang sama di laptop, server, dan cloud. Artikel ini membawa Anda dari kontainer pertama hingga pengaturan yang siap produksi dalam 100 contoh. Anda akan mempelajari CLI Docker, image dan registry, menulis Dockerfile dengan build multi-tahap, volume dan jaringan, Docker Compose untuk aplikasi multi-kontainer, konfigurasi dan secret, batas sumber daya dan pemeriksaan kesehatan, keamanan kontainer, debugging, pipeline CI/CD, serta pengenalan awal Kubernetes dan Swarm. Catatan jujur: Docker tidak terpasang di komputer yang dipakai menyiapkan artikel ini, jadi 100 contoh tersebut tidak dijalankan di sini. Setiap perintah dan berkas ditulis mengikuti sintaks resmi Docker dan diperiksa dengan membaca. Jalankan sendiri setiap contoh sebelum Anda mengandalkannya.

Yang Anda butuhkan

Docker Desktop di Windows atau macOS, atau Docker Engine di Linux, dengan plugin Docker Compose (perintah docker compose version harus berjalan). Editor seperti Visual Studio Code dengan ekstensi Docker akan membantu. Pengetahuan dasar baris perintah sudah cukup untuk memulai. Beberapa contoh memakai proyek Python atau Node.js contoh, dan beberapa memakai registry privat, jadi gunakan placeholder seperti registry.example.com dan jangan pernah menempelkan kata sandi asli ke dalam perintah.

Cara memakai contoh

Contoh bash memakai Docker CLI dan Docker Compose. Contoh Dockerfile disimpan sebagai berkas bernama Dockerfile di folder proyek. Contoh YAML disimpan sebagai compose.yaml atau berkas Kubernetes yang disebut dalam teks.

Topik 1: Memulai dengan Docker

Kontainer adalah proses terisolasi dengan sistem berkas dan jaringannya sendiri, dibangun dari image. Pelajari gagasan intinya, periksa instalasi, dan jalankan kontainer pertama Anda.

Image, kontainer, dan registry

Image adalah templat hanya-baca yang terdiri atas lapisan. Kontainer adalah instans image yang sedang berjalan. Registry seperti Docker Hub atau Azure Container Registry menyimpan image agar mesin lain dapat mengunduhnya.

Mengapa kontainer membantu

Kontainer mengemas aplikasi bersama pustakanya, sehingga perilakunya sama di setiap mesin. Kontainer berjalan dalam hitungan detik dan berbagi kernel host, sehingga memakai memori jauh lebih sedikit daripada mesin virtual penuh.

Memeriksa instalasi

Jalankan docker version untuk melihat klien dan server. Jika baris server tidak muncul, Docker Desktop atau layanan Docker belum berjalan, jadi nyalakan dulu sebelum menjalankan perintah kontainer apa pun.

Ilustrasi

Cara Docker memindahkan aplikasi dari Dockerfile ke kontainer yang berjalan: Dockerfile dibangun menjadi image, image didorong ke registry, dan host menariknya lalu menjalankannya sebagai kontainer
Cara Docker memindahkan aplikasi dari Dockerfile ke kontainer yang berjalan: Dockerfile dibangun menjadi image, image didorong ke registry, dan host menariknya lalu menjalankannya sebagai kontainer

Contoh 1: Periksa Docker sudah terpasang

Pastikan klien dapat terhubung ke engine Docker.

docker --version
docker info --format "server: {{.ServerVersion}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 2: Jalankan hello-world

Kontainer pertama Anda, diunduh dan dijalankan dengan satu perintah.

docker run hello-world

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 3: Unduh image

Ambil image tanpa menjalankan kontainer.

docker pull nginx:1.27

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 4: Daftar image lokal

Lihat image yang tersimpan di komputer ini.

docker images
docker image ls --filter "reference=nginx"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 5: Periksa image

Baca arsitektur dan sistem operasi sebuah image.

docker image inspect nginx:1.27 --format "arch={{.Architecture}} os={{.Os}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 6: Periksa pemakaian disk

Lihat ruang yang dipakai image, kontainer, dan volume.

docker system df

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 2: Menjalankan dan Mengelola Kontainer

Perintah docker run membuat kontainer dari image. Anda akan mempublikasikan port, membaca log, menjalankan perintah di dalam kontainer, dan membersihkan kontainer yang tidak lagi dibutuhkan.

Mode terlepas dan interaktif

-d menjalankan kontainer di latar belakang dan -it melampirkan terminal. --rm menghapus kontainer saat berhenti, cocok untuk percobaan singkat.

Port dan nama

-p host:kontainer mempublikasikan port, jadi 8080:80 mengirim port 8080 di host ke port 80 di kontainer. --name memberi kontainer nama yang mudah dibaca untuk dipakai pada perintah berikutnya.

Siklus hidup dan pembersihan

Kontainer yang berhenti tetap menyimpan datanya sampai Anda menghapusnya. Gunakan docker ps -a untuk melihatnya dan docker rm untuk menghapusnya, serta bersihkan secara rutin di mesin yang sering membangun image.

Contoh 7: Jalankan kontainer di latar belakang

Mulai kontainer terlepas (detached) dan tampilkan daftarnya.

docker run -d --name web nginx:1.27
docker ps

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 8: Publikasikan port

Akses server web di dalam kontainer dari host.

docker run -d --name web-8080 -p 8080:80 nginx:1.27
curl http://localhost:8080

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 9: Mulai shell sementara

Gunakan --rm agar kontainer dihapus saat Anda keluar.

docker run -it --rm alpine:3.20 sh

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 10: Daftar kontainer

Tampilkan kontainer yang berjalan dan yang sudah berhenti.

docker ps
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 11: Baca log kontainer

Tampilkan beberapa baris terakhir atau ikuti keluarannya secara langsung.

docker logs --tail 50 web
docker logs -f web

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 12: Jalankan perintah di dalam kontainer

Buka shell atau jalankan satu perintah di kontainer yang berjalan.

docker exec -it web sh
docker exec web cat /etc/nginx/nginx.conf

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 13: Hentikan, mulai, dan restart

Kendalikan siklus hidup kontainer.

docker stop web
docker start web
docker restart web

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 14: Hapus kontainer

Hapus kontainer yang tidak lagi dibutuhkan.

docker rm -f web web-8080
docker container prune -f

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 3: Image dan Registry

Image memiliki nama, tag, dan digest. Tag bisa berubah, digest tidak, jadi Anda memerlukan keduanya untuk memberi tag, membagikan, dan mereproduksi perangkat lunak secara tepat.

Tag dan digest

latest hanyalah tag yang berpindah setiap kali penerbitnya memperbarui image. Digest seperti sha256 diikuti hash panjang mengidentifikasi satu image yang pasti, dan itulah cara membuat penerapan dapat direproduksi.

Mendorong ke registry

Masuk, beri tag pada image dengan alamat registry lengkap, lalu dorong. Mesin lain kemudian dapat menarik image yang sama dengan nama. Jangan pernah mendorong image yang berisi secret.

Membaca riwayat image

docker history menampilkan setiap lapisan, instruksi yang membuatnya, dan ukurannya. Ini membantu menemukan lapisan yang terlalu besar dan memastikan kata sandi tidak pernah tertulis ke dalam image.

Contoh 15: Beri tag pada image

Beri image nama dan versi milik Anda sendiri.

docker tag nginx:1.27 mycompany/nginx:1.0.0
docker images mycompany/nginx

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 16: Unggah image ke registry

Unggah image agar mesin lain dapat mengunduhnya.

docker login registry.example.com
docker tag mycompany/nginx:1.0.0 registry.example.com/team/nginx:1.0.0
docker push registry.example.com/team/nginx:1.0.0

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 17: Unggah ke Azure Container Registry

Masuk dengan Azure CLI lalu unggah ke registry Anda.

az acr login --name <registry-name>
docker tag mycompany/nginx:1.0.0 <registry-name>.azurecr.io/nginx:1.0.0
docker push <registry-name>.azurecr.io/nginx:1.0.0

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 18: Jalankan registry lokal

Mulai registry pribadi di komputer Anda untuk pengujian.

docker run -d -p 5000:5000 --restart unless-stopped --name registry registry:2
docker tag nginx:1.27 localhost:5000/nginx:1.27
docker push localhost:5000/nginx:1.27

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 19: Kunci image dengan digest

Digest adalah sidik jari yang tidak berubah, tidak seperti tag.

docker pull nginx:1.27
docker image inspect nginx:1.27 --format "{{index .RepoDigests 0}}"
docker run -d nginx@sha256:<digest-from-the-line-above>

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 20: Baca layer image

Lihat instruksi yang membuat setiap layer dan ukurannya.

docker history nginx:1.27
docker history --no-trunc --format "{{.Size}}\t{{.CreatedBy}}" nginx:1.27

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 4: Menulis Dockerfile

Dockerfile adalah resep berbentuk teks. Setiap instruksi membuat satu lapisan, sehingga urutan dan isi instruksi menentukan ukuran, kecepatan pembangunan ulang, dan apa yang berjalan saat kontainer dimulai.

Instruksi inti

FROM memilih image dasar. COPY dan RUN menambahkan berkas dan perintah. WORKDIR menetapkan folder untuk instruksi berikutnya. CMD dan ENTRYPOINT menentukan apa yang dijalankan kontainer.

ARG versus ENV

ARG hanya ada selama image dibangun. ENV tetap ada di dalam image dan terlihat oleh kontainer yang berjalan. Gunakan ARG untuk pilihan saat membangun dan ENV untuk pengaturan yang dibaca program.

Membangun dan memberi tag

docker build -t nama:tag . mengirim folder ke builder. Hanya berkas yang disalin Dockerfile yang digunakan, jadi jaga konteks build tetap kecil dengan berkas .dockerignore.

Contoh 21: Dockerfile minimal

Resep paling kecil yang berguna: image dasar dan satu perintah.

FROM alpine:3.20
CMD ["echo", "Hello from a container"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 22: Bangun dan jalankan image

Ubah Dockerfile menjadi image lalu jalankan.

docker build -t hello-image:1.0 .
docker run --rm hello-image:1.0

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 23: Dockerfile untuk aplikasi Python

Pasang dependensi dan salin kode ke image yang ringan.

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 24: Dockerfile untuk aplikasi Node.js

Pasang paket produksi dan buka port.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 25: ARG dan ENV

Atur nilai saat build dan variabel lingkungan saat dijalankan.

FROM alpine:3.20
ARG APP_VERSION=dev
ENV APP_VERSION=$APP_VERSION
ENV APP_PORT=8080
CMD ["sh", "-c", "echo version=$APP_VERSION port=$APP_PORT"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 26: Kirim argumen build

Ubah versi saat build tanpa mengedit berkas.

docker build --build-arg APP_VERSION=1.4.2 -t vars-image:1.4.2 .
docker run --rm -e APP_PORT=9000 vars-image:1.4.2

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 27: WORKDIR dan COPY

Atur folder kerja dan salin berkas ke dalam image.

FROM alpine:3.20
WORKDIR /srv/site
COPY ./site/ ./
# ADD can unpack archives, but COPY is clearer for plain files
RUN ls -la /srv/site

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 28: ENTRYPOINT dan CMD

Pilih program tetap beserta argumen bawaannya.

FROM alpine:3.20
RUN apk add --no-cache curl
ENTRYPOINT ["curl", "-s"]
CMD ["https://example.com"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 5: Praktik Terbaik untuk Image

Image yang baik kecil, dapat direproduksi, cepat dibangun, dan aman dijalankan. Build multi-tahap, urutan lapisan, versi yang dikunci, pengguna non-root, dan pemeriksaan kesehatan mencakup sebagian besar praktik tersebut.

Build multi-tahap

Tahap build menyimpan kompilator dan alat, lalu tahap akhir hanya menyalin hasilnya. Image akhir tetap kecil dan tidak berisi kode sumber atau alat build yang bisa dimanfaatkan penyerang.

Caching lapisan

Docker memakai ulang lapisan selama instruksi dan masukannya tidak berubah, lalu membangun ulang semua yang sesudah perubahan pertama. Salin berkas dependensi dan pasang sebelum menyalin kode sumber.

Pengguna, versi, dan pemeriksaan

Jalankan sebagai pengguna numerik non-root, kunci versi image dasar, tambahkan label pemilik dan versi, serta gunakan HEALTHCHECK agar Docker dapat melaporkan apakah aplikasi benar-benar berfungsi.

Contoh 29: Kecualikan berkas dengan .dockerignore

Jaga agar rahasia, data Git, dan dependensi tidak ikut dibangun.

cat > .dockerignore <<'EOF'
.git
node_modules
*.log
.env
EOF
docker build -t app:1.0 .

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 30: Build multi-tahap untuk Go

Kompilasi di image besar, lalu kirim hanya programnya.

FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod ./
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app .

FROM gcr.io/distroless/static-debian12
COPY --from=build /out/app /app
ENTRYPOINT ["/app"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 31: Build multi-tahap untuk front-end

Bangun aset, lalu sajikan dengan Nginx.

FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 32: Jalankan sebagai pengguna non-root

Batasi kerusakan jika aplikasi diserang.

FROM python:3.12-slim
RUN useradd --create-home --uid 10001 appuser
WORKDIR /home/appuser/app
COPY --chown=appuser:appuser . .
USER appuser
CMD ["python", "app.py"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 33: Kunci versi image dasar

Hindari kejutan dari tag latest yang terus berubah.

# Avoid "latest": it changes without warning
FROM python:3.12.5-slim-bookworm
# Pin system packages when the build must be reproducible
RUN apt-get update && apt-get install -y --no-install-recommends curl=8.* \
 && rm -rf /var/lib/apt/lists/*

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 34: Atur urutan layer agar cache terpakai

Salin berkas dependensi lebih dulu agar build tetap cepat.

FROM node:20-alpine
WORKDIR /app
# Dependencies change less often than source code, so copy them first
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["npm", "start"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 35: Tambahkan label image

Catat judul, versi, dan pemilik di dalam image.

FROM alpine:3.20
LABEL org.opencontainers.image.title="sample-api" \
      org.opencontainers.image.version="1.4.2" \
      org.opencontainers.image.maintainer="[email protected]"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 36: HEALTHCHECK

Beri tahu Docker apakah aplikasi masih berfungsi.

FROM nginx:1.27-alpine
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost/ || exit 1

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 6: Volume dan Data yang Tetap Ada

Kontainer bersifat sekali pakai, tetapi basis data dan unggahan tidak. Volume dan bind mount menyimpan data di luar lapisan kontainer yang dapat ditulis, sehingga data bertahan melewati restart dan peningkatan versi.

Named volume

Named volume dikelola oleh Docker dan disimpan di luar kontainer. Gunakan untuk basis data, karena datanya tetap ada saat kontainer dihapus dan Anda dapat mencadangkannya dengan kontainer pembantu.

Bind mount

Bind mount memetakan folder dari komputer Anda ke dalam kontainer. Ini praktis saat pengembangan karena perubahan kode langsung terlihat, tetapi kontainer mendapat akses langsung ke berkas host, jadi gunakan :ro jika hanya perlu membaca.

Pencadangan dan data sementara

Cadangkan volume dengan menjalankan kontainer kecil yang memasang volume dan menulis berkas tar. Gunakan tmpfs untuk berkas sementara yang sebaiknya berada di memori dan hilang saat kontainer berhenti.

Contoh 37: Buat named volume

Simpan data yang harus tetap ada walau kontainer dihapus.

docker volume create app-data
docker volume ls
docker volume inspect app-data

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 38: Named volume untuk database

Simpan data PostgreSQL dengan aman saat kontainer di-restart.

docker run -d --name db -e POSTGRES_PASSWORD=<strong-password> \
  -v app-data:/var/lib/postgresql/data postgres:16
docker exec db psql -U postgres -c "select 1"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 39: Bind mount folder host

Bagikan folder dari komputer Anda saat pengembangan.

docker run --rm -it -v "$(pwd)/site:/usr/share/nginx/html:ro" -p 8081:80 nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 40: Mount hanya-baca

Biarkan kontainer membaca konfigurasi tetapi tidak mengubahnya.

docker run --rm -v /srv/config:/etc/app:ro alpine:3.20 ls -l /etc/app

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 41: Cadangkan volume

Arsipkan data volume ke berkas tar dengan kontainer pembantu.

docker run --rm -v app-data:/data -v "$(pwd):/backup" alpine:3.20 \
  tar czf /backup/app-data-backup.tgz -C /data .

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 42: Pulihkan volume

Kembalikan data yang diarsipkan ke volume baru.

docker volume create app-data-restored
docker run --rm -v app-data-restored:/data -v "$(pwd):/backup" alpine:3.20 \
  tar xzf /backup/app-data-backup.tgz -C /data

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 43: tmpfs untuk data sementara

Simpan berkas sementara di memori dan hapus saat berhenti.

docker run --rm --tmpfs /tmp:rw,size=64m alpine:3.20 sh -c "echo scratch > /tmp/x && cat /tmp/x"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 7: Jaringan Kontainer

Docker memberi kontainer jaringannya sendiri. Jaringan buatan pengguna memungkinkan kontainer saling menemukan lewat nama, dan publikasi port menentukan layanan mana yang dapat dijangkau dari luar.

Jaringan bridge dan buatan pengguna

Jaringan bridge bawaan hanya memberi kontainer alamat IP. Jaringan bridge buatan pengguna juga menyediakan DNS, sehingga satu kontainer dapat menjangkau yang lain lewat namanya, misalnya http://api atau redis://cache.

Mempublikasikan port dengan aman

Secara bawaan port dipublikasikan ke semua antarmuka. Ikat ke 127.0.0.1 agar basis data hanya dapat diakses dari komputer Anda. EXPOSE hanya mendokumentasikan port dan tidak membukanya.

Beberapa jaringan

Satu kontainer dapat bergabung ke beberapa jaringan. Tempatkan basis data di jaringan back dan proksi web di jaringan front, sehingga hanya layanan yang memerlukan basis data yang dapat mengaksesnya.

Contoh 44: Daftar dan periksa jaringan

Lihat jaringan yang dibuat Docker dan rentang alamatnya.

docker network ls
docker network inspect bridge --format "{{range .IPAM.Config}}{{.Subnet}}{{end}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 45: Buat jaringan kustom

Beri kontainer terkait jaringan pribadinya sendiri.

docker network create app-net
docker run -d --name api --network app-net nginx:1.27
docker run --rm --network app-net alpine:3.20 wget -qO- http://api

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 46: Temukan kontainer dengan nama

Gunakan nama kontainer sebagai nama host di jaringan.

docker run -d --name cache --network app-net redis:7-alpine
docker run --rm --network app-net redis:7-alpine redis-cli -h cache ping

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 47: Hubungkan kontainer ke jaringan kedua

Biarkan satu layanan menjangkau dua jaringan terpisah.

docker network create back-net
docker network connect back-net api
docker inspect api --format "{{json .NetworkSettings.Networks}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 48: Publikasikan hanya di satu antarmuka

Buat database hanya dapat diakses dari komputer ini.

docker run -d -p 127.0.0.1:5432:5432 --name pg -e POSTGRES_PASSWORD=<strong-password> postgres:16

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 49: EXPOSE versus publish

EXPOSE hanya dokumentasi; -p membuat port dapat diakses dari host.

FROM node:20-alpine
# EXPOSE only documents the port; it does not open it to the host
EXPOSE 3000
CMD ["node", "server.js"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 50: Gunakan jaringan host

Pakai jaringan host Linux bersama untuk kasus khusus.

docker run --rm --network host alpine:3.20 sh -c "ip addr show eth0 | head -3"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 8: Dasar-Dasar Docker Compose

Compose mendeskripsikan aplikasi multi-kontainer dalam satu berkas YAML. Satu perintah menyalakan, menghentikan, dan memeriksa setiap layanan, jaringan, dan volume dalam proyek.

Berkas compose

Kunci services mendaftar setiap kontainer. Setiap layanan memiliki bagian image atau build, serta ports, environment, volumes, dan networks. Compose otomatis membuat jaringan bersama untuk proyek.

Perintah

docker compose up -d menjalankan proyek, docker compose ps menampilkan statusnya, docker compose logs -f mengikuti keluaran, dan docker compose down menghentikan serta menghapus kontainer dan jaringan bawaan.

Override

compose.yaml menyimpan pengaturan bersama dan compose.override.yaml digabungkan secara otomatis. Simpan perubahan lokal di berkas override agar berkas utama tetap sama di setiap lingkungan.

Contoh 51: Berkas Compose minimal

Jelaskan layanan web dalam satu berkas YAML.

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 52: Mulai dan hentikan proyek Compose

Nyalakan atau matikan seluruh aplikasi multi-kontainer.

docker compose up -d
docker compose ps
docker compose down

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 53: Bangun image di dalam Compose

Biarkan Compose membangun image dari Dockerfile.

services:
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - "3000:3000"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 54: Variabel lingkungan di Compose

Atur pengaturan tiap layanan di dalam berkas.

services:
  api:
    build: ./api
    environment:
      APP_ENV: development
      LOG_LEVEL: info

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 55: Tunggu layanan lain

Gunakan depends_on untuk mengatur urutan start.

services:
  api:
    build: ./api
    depends_on:
      - db
  db:
    image: postgres:16

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 56: Named volume di Compose

Simpan berkas database meski proyek di-restart.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: <strong-password>
    volumes:
      - db-data:/var/lib/postgresql/data
volumes:
  db-data:

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 57: Log, exec, dan perintah sekali jalan

Jalankan tes atau alat di dalam proyek.

docker compose logs -f api
docker compose exec db psql -U postgres
docker compose run --rm api npm test

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 58: Berkas override untuk pengembangan

Pisahkan pengaturan produksi dari perubahan lokal.

# compose.yaml holds the shared settings
services:
  api:
    build: ./api
# compose.override.yaml is merged automatically on "docker compose up"
services:
  api:
    volumes:
      - ./api:/app
    environment:
      DEBUG: "1"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 9: Compose untuk Aplikasi Nyata

Aplikasi nyata memiliki lapisan web, basis data, cache, dan proksi. Compose menghubungkan semuanya, menunggu hingga siap, dan memungkinkan Anda menskalakan bagian yang memerlukan kapasitas lebih besar.

Web, basis data, dan cache

Berikan satu tugas untuk setiap layanan, simpan berkas basis data di named volume, dan jangkau setiap layanan dengan namanya. Teruskan string koneksi melalui variabel lingkungan, bukan menuliskan nama host secara tetap.

Urutan start dan kesehatan

depends_on hanya menunggu kontainer mulai. Tambahkan healthcheck ke basis data dan gunakan condition: service_healthy agar aplikasi baru mulai setelah basis data menerima koneksi.

Penskalaan dan isolasi

docker compose up --scale mengubah jumlah salinan layanan tanpa status. Pisahkan jaringan agar proksi publik dapat menjangkau API tetapi tidak dapat menjangkau basis data secara langsung.

Contoh 59: Profil untuk layanan opsional

Jalankan alat administrasi hanya saat diminta.

services:
  api:
    build: ./api
  pgadmin:
    image: dpage/pgadmin4
    profiles: ["tools"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 60: Mulai sebuah profil

Aktifkan layanan opsional dari baris perintah.

docker compose up -d
docker compose --profile tools up -d

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 61: Aplikasi web dengan PostgreSQL

Aplikasi lengkap dengan basis data dan data yang tetap ada.

services:
  web:
    build: ./web
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: shop
      POSTGRES_USER: shop
      POSTGRES_PASSWORD: <strong-password>
    volumes:
      - pg-data:/var/lib/postgresql/data
volumes:
  pg-data:

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 62: Tambahkan Redis sebagai cache

Hubungkan penyimpanan kunci-nilai cepat memakai nama layanan.

services:
  web:
    build: ./web
    environment:
      REDIS_URL: redis://cache:6379
  cache:
    image: redis:7-alpine
    command: ["redis-server", "--save", "", "--appendonly", "no"]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 63: Nginx sebagai reverse proxy

Kirim lalu lintas web ke aplikasi lewat satu pintu masuk.

services:
  proxy:
    image: nginx:1.27-alpine
    ports:
      - "80:80"
    volumes:
      - ./proxy/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - app
  app:
    build: ./app

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 64: Tunggu sampai basis data sehat

Jalankan aplikasi setelah basis data menerima kueri.

services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: <strong-password>
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 10

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 10: Konfigurasi dan Secret

Konfigurasi berubah antarlingkungan, dan secret tidak boleh berakhir di dalam image atau di Git. Gunakan variabel lingkungan, berkas env, dan berkas secret, lalu baca dengan aman di dalam program Anda.

Variabel lingkungan dan berkas .env

Compose membaca berkas .env untuk substitusi variabel dalam berkas compose. Tambahkan .env ke .gitignore, dan commit berkas .env.example dengan nilai placeholder agar pengembang lain tahu apa yang harus diatur.

Secret sebagai berkas

Secret berbasis berkas dipasang di bawah /run/secrets di dalam kontainer. Membaca dari berkas menjaga nilainya tetap keluar dari keluaran docker inspect dan daftar proses, tempat variabel lingkungan dapat bocor.

Jangan pernah menanamkan secret ke image

Nilai yang disalin ke sebuah lapisan tetap ada di riwayat image meski langkah berikutnya menghapusnya. Berikan secret saat dijalankan, periksa riwayat dengan docker history, dan ganti secret apa pun yang pernah didorong.

Contoh 65: Skala sebuah layanan

Jalankan beberapa salinan worker.

docker compose up -d --scale worker=3
docker compose ps worker

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 66: Jaringan front-end dan back-end

Jauhkan basis data dari jaringan publik.

services:
  proxy:
    image: nginx:1.27-alpine
    networks: [front]
    ports: ["80:80"]
  api:
    build: ./api
    networks: [front, back]
  db:
    image: postgres:16
    networks: [back]
networks:
  front:
  back:

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 67: Muat variabel dari .env

Simpan nilai lokal di luar berkas Compose.

cat > .env <<'EOF'
POSTGRES_PASSWORD=<strong-password>
APP_PORT=8000
EOF
docker compose config

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 68: Gunakan env_file

Muat sekelompok pengaturan dari sebuah berkas.

services:
  api:
    build: ./api
    env_file:
      - ./config/api.env

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 69: Berkas secret di Compose

Berikan kata sandi ke layanan tanpa memasukkannya ke image.

services:
  api:
    build: ./api
    secrets:
      - db_password
secrets:
  db_password:
    file: ./secrets/db_password.txt

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 70: Baca konfigurasi di Python

Gunakan nilai bawaan dan ubah teks lingkungan menjadi angka.

import os

db_host = os.environ.get("DB_HOST", "localhost")
db_port = int(os.environ.get("DB_PORT", "5432"))
print(f"connect to {db_host}:{db_port}")

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 71: Baca berkas secret di Python

Muat kata sandi dari jalur secret di dalam kontainer.

from pathlib import Path

secret_file = Path("/run/secrets/db_password")
password = secret_file.read_text(encoding="utf-8").strip()
print("password length:", len(password))

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 72: Pengaturan saat dijalankan

Timpa nilai untuk satu kali jalan dan periksa riwayat image.

docker run --rm -e LOG_LEVEL=debug -e DB_HOST=db.internal app:1.0
docker history --no-trunc app:1.0 | grep -i password || echo "no password in the layers"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 11: Sumber Daya, Kesehatan, dan Log

Sebuah kontainer dapat memakai seluruh memori dan CPU host jika dibiarkan. Batas, kebijakan restart, pemeriksaan kesehatan, dan rotasi log menjaga layanan tetap stabil dan disk tidak penuh.

Batas memori dan CPU

--memory menghentikan kontainer yang memakai RAM terlalu banyak, dan --cpus membatasi porsi waktu prosesornya. Tetapkan batas berdasarkan pemakaian yang diukur dengan docker stats, bukan menebak.

Kebijakan restart

unless-stopped me-restart kontainer setelah crash atau reboot host, tetapi tidak setelah Anda menghentikannya sendiri. Gunakan untuk layanan yang berjalan lama, dan perbaiki penyebab crash yang berulang alih-alih mengandalkan restart.

Log dan kesehatan

Docker menyimpan keluaran kontainer di log driver. Batasi ukuran json-file dengan max-size dan max-file. Status kesehatan menampilkan starting, healthy, atau unhealthy, yang dapat dipakai load balancer dan orkestrator.

Contoh 73: Batas memori

Cegah proses liar memakai seluruh RAM.

docker run -d --name api-mem --memory 256m --memory-swap 256m nginx:1.27-alpine
docker stats --no-stream api-mem

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 74: Batas CPU

Berikan setengah inti CPU kepada kontainer.

docker run -d --name api-cpu --cpus 0.5 nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 75: Kebijakan restart

Jalankan kembali layanan setelah crash atau reboot.

docker run -d --name worker --restart unless-stopped app:1.0
docker inspect worker --format "{{.HostConfig.RestartPolicy.Name}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 76: Batasi ukuran log

Cegah berkas log memenuhi disk.

docker run -d --name api-logs \
  --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 77: Baca status kesehatan

Periksa apakah kontainer sehat, sedang mulai, atau tidak sehat.

docker ps --format "table {{.Names}}\t{{.Status}}"
docker inspect --format "{{.State.Health.Status}}" api

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 78: Bersihkan objek yang tidak dipakai

Hapus kontainer berhenti dan image yatim dengan aman.

docker container prune -f
docker image prune -f
docker volume ls -qf dangling=true

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 12: Keamanan Kontainer

Kontainer berbagi kernel host, sehingga konfigurasi yang ceroboh dapat memberi penyerang akses lebih dari yang diinginkan. Hak akses minimum, sistem berkas hanya-baca, pemindaian, dan image dasar yang mutakhir mengurangi risikonya.

Hak akses minimum

Jalankan sebagai pengguna non-root, buang capability Linux yang tidak diperlukan dengan --cap-drop ALL, dan tambahkan kembali hanya yang spesifik dibutuhkan. Gunakan no-new-privileges untuk mencegah proses memperoleh hak tambahan.

Sistem berkas hanya-baca

--read-only mencegah kontainer mengubah berkasnya sendiri. Sediakan pemasangan tmpfs untuk beberapa direktori yang harus dapat ditulis, seperti /tmp.

Pemindaian dan pembaruan

Pindai image dengan Docker Scout atau pemindai lain, bangun ulang secara berkala untuk mendapatkan image dasar yang sudah ditambal, dan gagalkan build saat ditemukan kerentanan kritis. Jangan jalankan kontainer dengan --privileged kecuali ada alasan khusus.

Contoh 79: Lepaskan capability Linux

Buang kewenangan yang tidak dibutuhkan aplikasi.

docker run -d --name locked --cap-drop ALL --cap-add NET_BIND_SERVICE -p 80:80 nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 80: Sistem berkas root hanya-baca

Cegah kontainer menulis ke berkas sistemnya sendiri.

docker run -d --name ro-app --read-only --tmpfs /tmp --tmpfs /var/run nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 81: Jalankan sebagai ID pengguna angka

Pilih ID pengguna, bukan bergantung pada nama.

docker run --rm --user 10001:10001 alpine:3.20 id

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 82: Blokir peningkatan hak akses

Cegah proses memperoleh hak tambahan.

docker run -d --name hardened --security-opt no-new-privileges:true nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 83: Pindai image untuk kerentanan

Temukan CVE yang sudah dikenal pada paket di dalam image.

docker scout cves nginx:1.27-alpine
docker scout quickview nginx:1.27-alpine

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 84: Pengaturan keamanan di Compose

Gabungkan opsi pengerasan dalam satu layanan.

services:
  api:
    build: ./api
    user: "10001:10001"
    read_only: true
    cap_drop: [ALL]
    security_opt: ["no-new-privileges:true"]
    tmpfs: [/tmp]

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 13: Debugging dan Pemecahan Masalah

Saat kontainer gagal, jawabannya ada di log, data inspect, event, dan proses. Rutinitas yang sistematis menemukan sebagian besar masalah dalam hitungan menit.

Log, event, dan inspect

Baca docker logs terlebih dahulu. docker events menampilkan apa yang dilakukan Docker dan kapan, sedangkan docker inspect menampilkan kode keluar, lingkungan, mount, dan jaringan, sehingga Anda dapat membandingkan kontainer yang berjalan dengan yang diharapkan.

Pemeriksaan sumber daya dan proses

docker stats menampilkan CPU dan memori per kontainer, dan docker top mendaftar proses. Kode keluar 137 sering berarti kernel mematikan proses karena memakai terlalu banyak memori, yang dapat Anda pastikan lewat OOMKilled.

Debugging jaringan

Jalankan image alat di namespace jaringan yang sama dengan --network container:nama, lalu gunakan curl, dig, dan ping dari dalam. Ini menguji pandangan jaringan yang sebenarnya dari kontainer tanpa mengubah apa pun.

Contoh 85: Ikuti event Docker

Pantau kontainer yang mulai, berhenti, dan gagal secara real time.

docker events --filter type=container --since 10m

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 86: Pantau pemakaian sumber daya

Lihat CPU dan memori tiap kontainer.

docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 87: Daftar proses di dalam kontainer

Lihat apa yang berjalan tanpa membuka shell.

docker top web

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 88: Baca satu field dari inspect

Ambil exit code dan tahu apakah kernel menghentikan proses.

docker inspect web --format "{{.State.ExitCode}} {{.State.OOMKilled}}"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 89: Salin berkas masuk dan keluar

Ambil berkas konfigurasi atau masukkan perbaikan ke kontainer.

docker cp web:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./nginx.conf web:/etc/nginx/nginx.conf

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 90: Debug dengan image alat jaringan

Bagikan jaringan kontainer lalu uji dengan curl dan dig.

docker run --rm -it --network container:web nicolaka/netshoot
# inside the tools shell: curl -v http://localhost:80

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 14: Pipeline CI/CD untuk Image

Pipeline membangun, menguji, memindai, dan mendorong image setiap kali kode berubah. Otomasi membuat setiap image dapat ditelusuri ke sebuah commit dan menjaga rilis tetap sama dari satu proses ke proses berikutnya.

Build dan push di CI

Pipeline masuk dengan kredensial berumur pendek, membangun image, menjalankan tes, lalu mendorongnya dengan tag yang menyertakan commit. Langkah yang sama berlaku di GitHub Actions dan Azure Pipelines.

Strategi penandaan

Beri setiap image tag commit Git untuk keterlacakan, dan pindahkan tag versi hanya saat rilis disetujui. Hindari bergantung pada latest di produksi, karena tag itu menyembunyikan kode mana yang sedang berjalan.

Kebersihan runner

Runner CI menumpuk lapisan dan volume. Bersihkan cache build sesuai jadwal dan tetapkan batas ukuran cache, agar mesin build tidak kehabisan disk lalu gagal secara tidak terduga.

Contoh 91: Bangun dan unggah di GitHub Actions

Otomatiskan pembangunan image untuk setiap dorongan ke main.

name: build-image
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/example/app:${{ github.sha }}

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 92: Bangun image di Azure Pipelines

Gunakan tugas Docker dengan service connection.

trigger:
  - main
pool:
  vmImage: ubuntu-latest
steps:
  - task: Docker@2
    inputs:
      command: buildAndPush
      containerRegistry: my-acr-connection
      repository: sample-api
      tags: |
        $(Build.BuildId)

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 93: Beri tag image dengan commit Git

Lacak tiap image sampai ke kode sumber yang tepat.

SHA=$(git rev-parse --short HEAD)
docker build -t app:$SHA .
docker tag app:$SHA app:latest
echo "built app:$SHA"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 94: Bersihkan cache build di runner CI

Cegah mesin build kehabisan disk.

docker builder prune --filter until=72h -f
docker image prune -a --filter until=168h -f

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Topik 15: Produksi dan Orkestrasi

Satu host cukup untuk layanan kecil. Ketika Anda memerlukan beberapa mesin, pemulihan mandiri, dan pembaruan bergulir, orkestrator seperti Kubernetes atau Docker Swarm menjalankan kontainer untuk Anda.

Daftar periksa produksi

Kunci versi image, tetapkan batas memori, tentukan kebijakan restart, tambahkan pemeriksaan kesehatan, ikat port ke antarmuka yang dituju, simpan secret di luar image, dan kirim log ke satu tempat terpusat.

Dasar Kubernetes

Deployment menjaga sejumlah replika tetap berjalan dan melakukan pembaruan bergulir. Service memberi replika-replika itu satu alamat tetap. Image kontainer yang sama berjalan tanpa perubahan di Compose maupun Kubernetes.

Swarm dan kapan memakainya

Docker Swarm memakai berkas bergaya Compose dalam sebuah stack dan menjalankan layanan di beberapa mesin. Kubernetes memiliki ekosistem yang lebih besar dan umum di layanan cloud terkelola, jadi pilih alat yang dapat dioperasikan tim Anda.

Contoh 95: Pengaturan Compose untuk produksi

Kunci versi, batasi memori, atur restart, dan periksa kesehatan.

services:
  api:
    image: registry.example.com/team/api:1.4.2
    restart: unless-stopped
    env_file: ./config/api.env
    ports:
      - "127.0.0.1:8000:8000"
    deploy:
      resources:
        limits:
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 3s
      retries: 3

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 96: Deployment Kubernetes

Jalankan tiga salinan image yang sama di klaster.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: registry.example.com/team/api:1.4.2
          ports:
            - containerPort: 8000
          resources:
            limits:
              memory: 512Mi
              cpu: "500m"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 97: Service Kubernetes

Beri semua salinan alamat tetap di dalam klaster.

apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 8000
  type: ClusterIP

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 98: Deploy stack Docker Swarm

Jalankan layanan yang sama di beberapa mesin.

docker swarm init
docker stack deploy -c stack.yml shop
docker service ls

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 99: Periksa kontainer dengan Docker SDK

Baca status kontainer dari kode Python.

import docker

client = docker.from_env()
for c in client.containers.list():
    state = c.attrs["State"].get("Health", {}).get("Status", "no healthcheck")
    print(c.name, state)

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Contoh 100: Skrip daftar periksa rilis

Hentikan rilis jika image berjalan sebagai root atau memiliki CVE kritis.

#!/usr/bin/env bash
set -euo pipefail
IMAGE="$1"
docker image inspect "$IMAGE" > /dev/null
USER_ID=$(docker run --rm --entrypoint id "$IMAGE" -u)
[ "$USER_ID" != "0" ] || { echo "image runs as root"; exit 1; }
docker scout cves --exit-code --only-severity critical "$IMAGE"
echo "release checks passed for $IMAGE"

*Contoh ini tidak dijalankan di sini karena Docker tidak terpasang di komputer yang menyiapkan artikel ini.*

Lab: Membangun, Menjalankan, dan Merilis Aplikasi Web Kecil

Satukan seluruh artikel dalam satu proyek: aplikasi web kecil, Dockerfile dengan build multi-tahap, berkas Compose dengan basis data dan volume, pemeriksaan kesehatan, dan pemeriksaan rilis.

1. Buat folder dengan aplikasi kecil dan berkas requirements.txt, lalu tulis Dockerfile yang menjalankannya sebagai pengguna non-root dengan HEALTHCHECK.

2. Tambahkan berkas .dockerignore dan bangun image dengan tag versi, misalnya docker build -t lab-web:1.0.0 .

3. Tulis compose.yaml dengan layanan web dan layanan PostgreSQL yang memakai named volume dan healthcheck, lalu jalankan dengan docker compose up -d.

4. Periksa status kesehatan dengan docker compose ps dan baca log dengan docker compose logs -f web.

5. Jalankan docker scout cves pada image, perbaiki yang bisa diperbaiki dengan memperbarui image dasar, lalu bangun ulang.

6. Jalankan daftar periksa rilis dari contoh 100 terhadap image Anda, dan hentikan rilis jika gagal.

7. Hentikan proyek dengan docker compose down, lalu hapus named volume hanya saat datanya tidak lagi dibutuhkan.

Langkah berikutnya

Setelah lab, baca dokumentasi resmi Docker untuk runtime pilihan Anda, berlatih di proyek terpisah, dan pelajari satu orkestrator secara mendalam saat layanan Anda membutuhkan lebih dari satu mesin. Simpan contoh dari artikel ini di repositori agar Anda dapat menjalankannya ulang setelah setiap pembaruan Docker.

Ringkasan

Docker mengubah aplikasi menjadi image yang berjalan sama di mana pun. Anda telah belajar menjalankan dan mengelola kontainer, mengunci image dengan tag dan digest, menulis Dockerfile yang efisien dengan build multi-tahap, menyimpan data di volume, menghubungkan layanan lewat jaringan, mendeskripsikan seluruh aplikasi dengan Compose, menangani konfigurasi dan secret dengan aman, membatasi sumber daya, memperkuat kontainer, melakukan debugging secara sistematis, mengotomasi build di CI/CD, serta bersiap untuk orkestrasi produksi.