Claude Code dan Docker: Compose, Volume, Network, dan Build CI
Gunakan Claude Code untuk membuat Dockerfile, Compose, local setup, dan build CI yang aman.
Tentukan dulu bagian yang dikerjakan Claude Code
Kalau hanya meminta “Dockerize app ini”, Claude Code bisa membuat Dockerfile yang berjalan sekali tetapi sulit direview. Docker memaketkan runtime aplikasi: image adalah template, container adalah instance yang berjalan, volume menyimpan data di luar container, dan network membuat service saling memanggil memakai nama.
Dalam proyek nyata, Dockerfile bukan satu-satunya file. Review Dockerfile, docker-compose.yml, .dockerignore, environment variables, health checks, dan build CI sebagai satu paket. Pakai referensi resmi: Dockerfile reference, Compose file reference, Docker build best practices, Docker Build GitHub Actions, dan Claude Code overview.
Untuk pekerjaan terkait CI, baca juga Claude Code CI/CD setup. Untuk batas permission dan sandbox, lanjutkan ke approval and sandbox guide dan security best practices.
Use case praktis
Integrasi Docker berguna saat mengurangi tebakan environment. Tulis masalahnya sebelum meminta Claude Code mengubah file.
| Use case | Yang distandarkan Docker | Yang diminta ke Claude Code |
|---|---|---|
| Onboarding developer baru | Node.js, PostgreSQL, Redis, port, command awal | Membuat docker compose up menyalakan stack |
| Debug mendekati produksi | Env vars, service name, health check, urutan start | Membandingkan local dan production |
| Verifikasi PR | Dockerfile, lockfile, build cache, log CI | Menambah workflow yang hanya build image |
| Training dan handoff | Command, mode gagal, recovery | Menulis aturan di CLAUDE.md dan README |
Untuk SaaS atau situs yang dimonetisasi, ini langsung menyentuh revenue. Checkout, lead form, admin screen, dan product page tidak boleh bergantung pada satu laptop. Builder individual bisa mulai dari ClaudeCodeLab products. Tim yang ingin permission, CI, dan review rules sesuai repository nyata bisa memakai Claude Code training and consultation.
Prompt dengan guardrail
Prompt pertama perlu berisi context, file yang diminta, batasan, dan cara verifikasi. Ini mencegah konfigurasi yang terlihat benar tetapi berisiko.
Dockerize this Node.js + TypeScript API.
Context:
- pnpm is the package manager.
- The app listens on port 3000.
- GET /health returns 200.
- Local development needs PostgreSQL 16 and Redis 7.
Create:
- Production multi-stage Dockerfile
- docker-compose.yml for local development
- .dockerignore
- Docker-related package.json scripts
- GitHub Actions workflow that only verifies docker build
Constraints:
- Do not run the production container as root.
- Do not COPY .env files or secrets into the image.
- Explain the volume and network choices for the README.
- Include verification commands and how to inspect failures.
Multi-stage build memisahkan environment build dan runtime. Tool TypeScript tinggal di stage build, sementara image final hanya membawa production dependencies dan dist.
Dockerfile siap pakai
Contoh ini mengasumsikan API Node.js yang membangun src/index.ts menjadi dist/index.js. Stage dev untuk Compose lokal, dan runner untuk image produksi.
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
WORKDIR /app
RUN corepack enable
FROM base AS dev
ENV NODE_ENV=development
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
CMD ["pnpm", "dev"]
FROM base AS deps
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
FROM deps AS build
COPY tsconfig.json ./
COPY src ./src
RUN pnpm build
FROM base AS prod-deps
ENV NODE_ENV=production
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod && pnpm store prune
FROM base AS runner
ENV NODE_ENV=production
RUN groupadd --system --gid 1001 nodejs \
&& useradd --system --uid 1001 --gid nodejs appuser
COPY --from=prod-deps --chown=appuser:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=appuser:nodejs /app/dist ./dist
COPY --chown=appuser:nodejs package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD node -e "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "dist/index.js"]
Minta Claude Code mereview tiga hal: apakah secret bisa masuk ke image, apakah urutan COPY menjaga cache, dan apakah devDependencies tidak ikut ke runtime image.
Compose: volume dan network
Compose menjalankan beberapa container bersama. Di stack ini, API, PostgreSQL, dan Redis berbagi network; API dapat menghubungi postgres dan redis sebagai service name. Volume menyimpan state di luar container sementara. pgdata menyimpan database, dan api_node_modules mencegah node_modules host menimpa dependency Linux di container.
services:
api:
build:
context: .
target: dev
command: pnpm dev
ports:
- "3000:3000"
environment:
NODE_ENV: development
DATABASE_URL: postgres://app:app@postgres:5432/app
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- .:/app
- api_node_modules:/app/node_modules
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 10s
timeout: 3s
retries: 5
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: app
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 10
redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
volumes:
pgdata:
api_node_modules:
depends_on mengatur urutan start, tetapi tidak otomatis membuktikan database siap menerima koneksi. Kombinasikan dengan healthcheck dan condition: service_healthy.
Jauhkan secret dari build context
Mulai dari .dockerignore. File ini mengecilkan build context dan mencegah .env tersalin.
.git
node_modules
dist
coverage
.env
.env.*
!.env.example
npm-debug.log*
pnpm-debug.log*
Dockerfile*
docker-compose*.yml
Lalu tambahkan scripts bersama di package.json.
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js",
"docker:dev": "docker compose up --build",
"docker:check": "bash scripts/docker-check.sh"
},
"dependencies": {
"@fastify/redis": "latest",
"fastify": "latest",
"pg": "latest"
},
"devDependencies": {
"tsx": "latest",
"typescript": "latest"
}
}
Script verifikasi yang bisa diulang
Command manual mudah terlewat. Simpan alurnya di scripts/docker-check.sh.
#!/usr/bin/env bash
set -euo pipefail
docker compose build api
docker compose up -d postgres redis api
cleanup() {
docker compose down
}
trap cleanup EXIT
for attempt in {1..30}; do
if curl -fsS http://127.0.0.1:3000/health >/dev/null; then
echo "healthcheck ok"
exit 0
fi
echo "waiting for api... ${attempt}/30"
sleep 2
done
docker compose logs api
exit 1
Script ini membangun image, menjalankan stack, menunggu /health, dan mencetak log jika API tidak pernah sehat.
CI: build dulu, push nanti
Pada PR pertama, cukup verifikasi image build tanpa publish ke registry. Push, signing, vulnerability scan, dan SBOM bisa ditambahkan setelah dasar stabil.
name: docker-build
on:
pull_request:
push:
branches:
- main
jobs:
image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v7
with:
context: .
target: runner
push: false
tags: claude-code-docker-sample:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Claude Code harus bisa menjelaskan apakah workflow ini push image, apakah permission terlalu besar, dan apa yang terjadi saat cache kosong.
Kesalahan yang sering terjadi
Kesalahan paling mahal adalah menyalin .env ke image. Jika secret masuk registry, cleanup akan lama. Review .dockerignore, CI secrets, dan build log bersama-sama.
Kesalahan berikutnya adalah mount node_modules host ke container Linux. Paket native bisa berbeda di macOS, Windows, dan Linux. Named volume memisahkan dependency container dari host.
Masalah ketiga adalah startup race: API start sebelum PostgreSQL siap. Gunakan database health check dan retry di aplikasi.
Terakhir, jangan jalankan production container sebagai root. Demo tetap berjalan, tetapi risiko membesar. Minta Claude Code menunjukkan baris Dockerfile yang membuktikan user non-root.
Workflow yang aman
Urutan yang aman: inspeksi repository, daftar runtime dependencies, tulis .dockerignore, buat Compose lokal, buat Dockerfile produksi, tambah script verifikasi, lalu CI. Setelah setiap tahap, manusia membaca git diff dan Claude Code menulis empat hal: changed files, reason, verification command, remaining risk.
Pola ini cocok dengan session handoff template. Docker integration seharusnya menjadi kebiasaan tim yang bisa direview, bukan file sekali generate.
Hasil praktik
Dalam praktik, membagi pekerjaan membuat output Claude Code lebih baik. .dockerignore, lalu Compose, lalu health checks, lalu CI menghasilkan diff yang mudah direview. Volume api_node_modules dan gate service_healthy untuk database mengurangi dua masalah pemula: “hanya jalan di laptop saya” dan “API menyala tapi tidak bisa connect ke Postgres”.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.