Claude Code Devcontainer: lingkungan development yang reproducible
Bangun devcontainer Claude Code reproducible dengan Dockerfile, izin, secret, volume, dan port-forward.
Claude Code paling berguna saat lingkungan development tidak berubah-ubah. Kalau satu developer memakai Node.js 22, yang lain masih Node.js 20, PostgreSQL terpasang berbeda di setiap laptop, dan Redis hanya ada di sebagian mesin, agent akan menghabiskan waktu untuk menebak masalah environment sebelum memperbaiki kode.
Dev Container membuat environment itu menjadi konfigurasi di repository. Editor masuk ke container Docker, lalu terminal, language server, test runner, tool database, dan Claude Code berjalan di tempat yang sama. Artikel ini memakai contoh Next.js + TypeScript dengan PostgreSQL dan Redis, lalu menyiapkan .devcontainer/devcontainer.json, Dockerfile, docker-compose.yml, postCreateCommand, izin, secret, volume, dan port-forward.
Per 2 Juni 2026, dokumentasi resmi Claude Code memiliki halaman Development containers yang membahas Dev Container Feature, penyimpanan credential, batasan jaringan, dan risiko melewati permission prompt. Untuk dasar Dev Container, cek juga VS Code Dev Containers dan Dev Container Specification.
Mengapa devcontainer cocok untuk Claude Code
Claude Code bisa membaca file, mengubah kode, menjalankan command, dan menafsirkan hasil test. Karena itu, environment tempat ia berjalan harus jelas. Jika agent berjalan langsung di host, ia bisa melihat package global lama, credential pribadi, variable dari project lain, atau database lokal yang tidak sama dengan milik tim.
Dengan devcontainer, permukaan kerja menjadi reviewable. Versi Node.js, package sistem, versi Claude Code CLI, extension VS Code, lifecycle command, volume, dan port-forward semuanya ada di repository. Saat Claude Code mengatakan sudah menjalankan npm test, reviewer tahu command itu dijalankan di environment yang sama.
flowchart LR
Host["Mesin host"] --> Editor["VS Code / Cursor"]
Editor --> Container["Dev Container"]
Container --> Claude["Claude Code CLI"]
Container --> Tools["Node.js / npm / psql / redis-cli"]
Container --> Services["PostgreSQL / Redis"]
Container --> Repo["Repository yang di-mount"]
Claude --> Repo
Claude --> Tools
Ada tiga use case utama. Pertama, onboarding: anggota baru cukup rebuild container dan mendapatkan toolchain yang sama. Kedua, remote development: local machine dan Codespaces memakai konfigurasi yang sama. Ketiga, debugging dengan AI: hasil lint, typecheck, dan test tidak lagi bergantung pada satu laptop tertentu.
File yang akan dibuat
Setup ini memisahkan aplikasi, service pendukung, dan state Claude Code. Jangan langsung mount seluruh home directory host hanya demi praktis.
| File | Fungsi | Fokus review |
|---|---|---|
.devcontainer/devcontainer.json | Entry point untuk editor | remoteUser, port, mount, lifecycle command |
.devcontainer/Dockerfile | Menginstall tool dan Claude Code | versi CLI, user non-root, package sistem |
.devcontainer/docker-compose.yml | Menjalankan app, PostgreSQL, Redis | volume, healthcheck, port yang dipublish |
.devcontainer/post-create.sh | Setup setelah container dibuat | lockfile, Prisma, error handling |
.claude/settings.json | Aturan izin Claude Code | .env, secret, git push, command Docker berbahaya |
devcontainer.json
Buat .devcontainer/devcontainer.json. Ini JSON valid, jadi jangan menaruh komentar di dalam file.
{
"name": "claude-code-next-dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/app",
"remoteUser": "node",
"shutdownAction": "stopCompose",
"waitFor": "postCreateCommand",
"postCreateCommand": "bash .devcontainer/post-create.sh",
"postStartCommand": "git config --global --add safe.directory /workspaces/app || true",
"forwardPorts": [3000, 5432, 6379],
"portsAttributes": {
"3000": { "label": "Next.js", "onAutoForward": "notify" },
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" },
"6379": { "label": "Redis", "onAutoForward": "silent" }
},
"mounts": [
"source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
],
"containerEnv": {
"NODE_ENV": "development",
"DISABLE_AUTOUPDATER": "1",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
},
"customizations": {
"vscode": {
"extensions": [
"anthropic.claude-code",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-azuretools.vscode-docker"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"typescript.tsdk": "node_modules/typescript/lib",
"terminal.integrated.defaultProfile.linux": "bash"
}
}
}
}
Gunakan remoteUser non-root. Container memang membatasi risiko, tetapi workspace tetap bind mount dari host. Kalau Claude Code menghapus file di /workspaces/app, repository lokal juga berubah. Volume untuk /home/node/.claude menyimpan konfigurasi Claude Code per project tanpa membuka seluruh home host.
Compose, Dockerfile, dan postCreateCommand
.devcontainer/docker-compose.yml menjalankan app, PostgreSQL, dan Redis. Mulai dari forwardPorts; publish port database dengan Compose ports hanya jika tool luar benar-benar membutuhkannya.
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
command: sleep infinity
volumes:
- ..:/workspaces/app:cached
- node_modules:/workspaces/app/node_modules
- claude_code_config:/home/node/.claude
environment:
DATABASE_URL: postgresql://app:app_password@db:5432/app
REDIS_URL: redis://redis:6379
NEXT_TELEMETRY_DISABLED: "1"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app_password
POSTGRES_DB: app
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 5s
retries: 20
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 20
volumes:
node_modules:
claude_code_config:
postgres_data:
redis_data:
Di Dockerfile, pin versi Claude Code. Pada 2 Juni 2026, npm view @anthropic-ai/claude-code version mengembalikan 2.1.160.
FROM mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm
ARG CLAUDE_CODE_VERSION=2.1.160
ENV DISABLE_AUTOUPDATER=1
ENV NEXT_TELEMETRY_DISABLED=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
jq \
postgresql-client \
redis-tools \
ripgrep \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
&& npm cache clean --force
USER node
WORKDIR /workspaces/app
RUN mkdir -p /home/node/.claude
Setup awal ada di .devcontainer/post-create.sh.
#!/usr/bin/env bash
set -euo pipefail
cd /workspaces/app
corepack enable
if [ -f pnpm-lock.yaml ]; then
pnpm install --frozen-lockfile
elif [ -f yarn.lock ]; then
yarn install --immutable
elif [ -f package-lock.json ]; then
npm ci
elif [ -f package.json ]; then
npm install
fi
if [ -f prisma/schema.prisma ]; then
npx prisma generate
fi
node --version
npm --version
claude --version || true
Script ini mengikuti lockfile yang ada. Jangan menjalankan npm run dev di postCreateCommand, karena proses panjang membuat pembuatan container sulit dibaca. Jalankan server dari terminal, task, atau service terpisah.
Izin, secret, volume, dan port-forward
Jangan mount .env production, ~/.ssh, ~/.aws, atau ~/.config/gcloud secara default. Secret paling aman adalah secret yang tidak pernah masuk container. Untuk development, gunakan URL internal Compose; untuk API key nyata, gunakan managed secrets atau token sementara.
Aturan project bisa ditulis di .claude/settings.json.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Bash(npm run typecheck)",
"Bash(claude --version)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(printenv *)",
"Bash(git push *)",
"Bash(docker system prune *)"
]
}
}
Volume mempercepat kerja, tetapi juga menyimpan state lama. node_modules sebaiknya berada di volume container agar tidak bercampur dengan modul native dari Windows atau macOS. Volume PostgreSQL harus punya aturan reset, terutama setelah banyak percobaan migration.
Kesalahan umum dan verifikasi
Kesalahan umum: menjalankan Claude Code sebagai root, tidak mem-pin versi CLI, memasukkan secret production, menjalankan server panjang di postCreateCommand, dan mempublish port 5432 atau 6379 tanpa kebutuhan. Setelah rebuild, cek node --version, npm --version, claude --version, satu command lint atau test, dan http://localhost:3000.
Untuk service yang lebih lengkap, baca panduan Docker Compose Claude Code. Untuk menghubungkan ini ke deployment, lanjutkan ke panduan CI/CD Claude Code. Jika tim ingin menstandarkan devcontainer, CLAUDE.md, izin, dan checklist review, mulai dari training / consultation.
Hasil setelah dicoba
Pada repository Next.js kecil, bagian yang paling membantu adalah memisahkan postCreateCommand ke script, menaruh node_modules di volume container, dan menyimpan /home/node/.claude di volume per project. Setelah rebuild, versi Claude Code, install dependency, generate Prisma, dan port 3000 bisa dicek dengan urutan yang sama. Perhatian utama ada pada volume database: setelah banyak eksperimen migration, state lama bisa menyesatkan diagnosis.
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
Permission safety ladder Claude Code: perluas akses tanpa kehilangan kontrol
Naik dari read-only ke edit terbatas, command bukti, dan cek deploy dengan kontrol yang jelas.
Claude Code Small PR Proof Pack: perubahan kecil yang mudah direview
Paket bukti untuk PR Claude Code: diff, check, URL publik, jalur CTA, dan rollback.
Review gate Claude Code sebelum commit: diff, test, URL publik, dan CTA
Cara memakai Claude Code sebelum commit: diff scope, build, URL publik, link Gumroad, CTA konsultasi, missing test, dan file tidak terkait.