取り組みの背景 — Claude Code × Docker が最強のコンビである理由
コンテナ技術は現代のソフトウェア開発に欠かせない存在です。しかし「Dockerfileをどう書けばいいか」「DevContainerの設定が複雑すぎる」「本番環境への移行でトラブルが続く」といった悩みを抱える開発者は少なくありません。
Claude Codeは、こうしたDockerにまつわる課題を劇的に解決するツールです。自然言語でDockerfileの最適化を依頼したり、エラーメッセージをそのまま貼り付けて原因究明を任せたり、複雑なKubernetes YAMLの生成を自動化したりできます。
ここで扱うのはClaude CodeとDockerを組み合わせた本番級の開発・デプロイワークフロー を、実際のコード例とともに段階的に解説します。DevContainerの初期設定から始まり、マルチステージビルド、Docker Compose によるローカル開発環境、GitHub Actions を使ったCI/CD、そして Kubernetes または Fly.io への本番デプロイまで、一連の流れを網羅します。
対象読者は、Docker の基礎知識を持ちながらも本番運用に踏み込めていない中〜上級エンジニアです。Claude Code を使うことで、これまで数日かかっていたインフラ設計・実装を数時間で完成させる体験をお届けします。
DevContainer × Claude Code — 再現性の高い開発環境を5分で構築する
DevContainer とは何か
DevContainerは、VS CodeまたはGitHub Codespacesで使用できる「開発環境をコードとして定義する」仕組みです。チームメンバー全員が同一の環境で開発でき、「自分のマシンでは動くのに」問題を根絶できます。
Claude Codeでは、.devcontainer/devcontainer.json の生成・最適化を自然言語で依頼できます。
Claude Codeを使ったDevContainer生成
プロジェクトのルートで以下のように依頼します:
# Claude Codeに依頼する例
claude "Node.js 22 + TypeScript + PostgreSQL 16を使うプロジェクト用のdevcontainer.jsonを作成してください。
postCreateCommandでnpm installも実行されるようにしてください。"
生成される .devcontainer/devcontainer.json の例:
{
"name" : "Node.js + TypeScript + PostgreSQL" ,
"dockerComposeFile" : "docker-compose.yml" ,
"service" : "app" ,
"workspaceFolder" : "/workspace" ,
"features" : {
"ghcr.io/devcontainers/features/node:1" : {
"version" : "22"
},
"ghcr.io/devcontainers/features/git:1" : {},
"ghcr.io/devcontainers/features/github-cli:1" : {}
},
"customizations" : {
"vscode" : {
"extensions" : [
"dbaeumer.vscode-eslint" ,
"esbenp.prettier-vscode" ,
"ms-vscode.vscode-typescript-next" ,
"bradlc.vscode-tailwindcss"
],
"settings" : {
"editor.formatOnSave" : true ,
"editor.defaultFormatter" : "esbenp.prettier-vscode"
}
}
},
"postCreateCommand" : "npm install" ,
"remoteUser" : "node" ,
"forwardPorts" : [ 3000 , 5432 ],
"portsAttributes" : {
"3000" : { "label" : "App Server" , "onAutoForward" : "notify" },
"5432" : { "label" : "PostgreSQL" , "onAutoForward" : "silent" }
}
}
DevContainerのよくある問題をClaude Codeで解決する
DevContainerが起動しない場合、エラーメッセージをそのままClaude Codeに渡します:
claude "以下のエラーでDevContainerが起動できません。原因と修正方法を教えてください:
[error] failed to solve: failed to read dockerfile: open .devcontainer/Dockerfile: no such file or directory"
Claude Codeは問題を即座に特定し、不足しているDockerfileの生成や devcontainer.json の修正を提案します。
マルチステージビルド — 本番イメージを最小化する技術
なぜマルチステージビルドが必要か
開発用のNode.jsアプリをそのままDockerイメージにすると、node_modules も含めて数GBになることがあります。本番環境では、ビルド済みの成果物のみを含む軽量イメージが必要です。
マルチステージビルドは、ビルド環境と実行環境を分離し、本番イメージを100MB以下に抑える 技術です。
Claude Codeによるマルチステージ Dockerfile 生成
claude "Next.js 15アプリ用のマルチステージDockerfileを作成してください。
要件:
- ビルドステージ: node:22-alpine ベース
- 本番ステージ: node:22-alpine (distrolessでも可)
- セキュリティのため非rootユーザーで実行
- .next/standalone を活用した最小構成
- ARGでNODE_ENVを受け取れる構造"
生成された Dockerfile の例:
# ──────────────────────────────────
# Stage 1: 依存関係インストール
# ──────────────────────────────────
FROM node:22-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
# package.jsonとlockfileのみを先にコピー(キャッシュ活用)
COPY package.json package-lock.json* ./
RUN npm ci --only=production --ignore-scripts
# ──────────────────────────────────
# Stage 2: ビルド
# ──────────────────────────────────
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Standalone出力を有効化(next.config.tsで output: 'standalone' 設定済み前提)
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# ──────────────────────────────────
# Stage 3: 本番ランナー(最小サイズ)
# ──────────────────────────────────
FROM node:22-alpine AS runner
WORKDIR /app
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
# セキュリティ: 非rootユーザーを作成
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# standaloneビルドに必要なファイルのみコピー
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
CMD [ "node" , "server.js" ]
このDockerfileを使うと、最終イメージサイズは約80〜120MB に抑えられます(node_modules込みで数GBになる開発イメージと比較して約90%削減)。
イメージサイズの検証
# ビルドと確認
docker build -t myapp:prod .
docker images myapp
# 期待する出力例:
# REPOSITORY TAG IMAGE ID CREATED SIZE
# myapp prod a1b2c3d4e5f6 2 minutes ago 118MB
Docker Compose — ローカルマルチサービス開発環境の構築
実践的な docker-compose.yml の設計
フロントエンド、バックエンドAPI、データベース、Redisを含むフルスタック開発環境をClaude Codeに依頼します:
claude "Next.js フロントエンド + Hono.js API + PostgreSQL + Redis を含む
docker-compose.yml を作成してください。
- ホットリロードが効くボリューム設定
- 各サービスのヘルスチェック
- .env.local からの環境変数読み込み
- 開発用とCI用でプロファイルを分ける"
生成される docker-compose.yml:
version : "3.9"
services :
# ──── フロントエンド ────
web :
build :
context : ./web
dockerfile : Dockerfile.dev
target : development
ports :
- "3000:3000"
volumes :
- ./web:/app
- /app/node_modules # node_modulesはコンテナ内のものを使用
environment :
- NODE_ENV=development
- NEXT_PUBLIC_API_URL=http://localhost:8080
env_file :
- ./web/.env.local
depends_on :
api :
condition : service_healthy
healthcheck :
test : [ "CMD" , "wget" , "--spider" , "-q" , "http://localhost:3000" ]
interval : 30s
timeout : 10s
retries : 3
# ──── バックエンドAPI ────
api :
build :
context : ./api
dockerfile : Dockerfile.dev
ports :
- "8080:8080"
volumes :
- ./api:/app
- /app/node_modules
environment :
- NODE_ENV=development
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
depends_on :
db :
condition : service_healthy
cache :
condition : service_healthy
healthcheck :
test : [ "CMD" , "wget" , "--spider" , "-q" , "http://localhost:8080/health" ]
interval : 10s
timeout : 5s
retries : 5
start_period : 10s
# ──── PostgreSQL ────
db :
image : postgres:16-alpine
ports :
- "5432:5432"
environment :
POSTGRES_USER : postgres
POSTGRES_PASSWORD : password
POSTGRES_DB : myapp
volumes :
- postgres_data:/var/lib/postgresql/data
- ./db/init:/docker-entrypoint-initdb.d # 初期化SQL
healthcheck :
test : [ "CMD-SHELL" , "pg_isready -U postgres -d myapp" ]
interval : 5s
timeout : 3s
retries : 10
# ──── Redis ────
cache :
image : redis:7-alpine
ports :
- "6379:6379"
volumes :
- redis_data:/data
command : redis-server --appendonly yes
healthcheck :
test : [ "CMD" , "redis-cli" , "ping" ]
interval : 5s
timeout : 3s
retries : 5
# ──── DBマイグレーション(CI用プロファイル)────
migrate :
build :
context : ./api
command : npm run db:migrate
environment :
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
depends_on :
db :
condition : service_healthy
profiles :
- ci
volumes :
postgres_data :
redis_data :
Docker Composeを使った開発フロー
# 全サービス起動(ホットリロード有効)
docker compose up -d
# ログ確認(全サービス)
docker compose logs -f
# 特定サービスのログ
docker compose logs -f api
# DBマイグレーション実行
docker compose run --rm migrate
# コンテナ内でコマンド実行
docker compose exec api npm run db:seed
# 停止・クリーンアップ
docker compose down -v # ボリュームも削除
Claude Codeによるコンテナデバッグ — 問題解決を10倍速にする
エラーパターン別の対処法
コンテナ起動時のエラーはClaude Codeにそのまま投げることで、即座に解決策を得られます:
# エラーが発生した場合の対処法
docker compose logs api 2>&1 | claude "このエラーを解析して修正方法を提示してください"
よくある問題と Claude Code での解決アプローチ:
問題1: ポートバインディングエラー
Error response from daemon: driver failed programming external connectivity:
Bind for 0.0.0.0:5432 failed: port is already allocated
Claude Codeに渡すと、既存プロセスの特定方法(lsof -i :5432)とdocker-compose.ymlのポート変更を即座に提案します。
問題2: ヘルスチェック失敗による依存サービス待機
# ヘルスチェック状態を確認
docker compose ps
# 問題のあるコンテナのヘルスチェック詳細
docker inspect --format= '{{json .State.Health}}' myapp-db-1 | python3 -m json.tool
問題3: node_modulesのパーミッション問題
Claude Codeに依頼:
claude "DockerでNode.jsアプリのnode_modulesが
EACCES: permission denied エラーになります。
非rootユーザー設定時の正しいDockerfile修正方法を教えてください"
コンテナリソース最適化
# メモリ使用量の確認
docker stats --no-stream
# CPU・メモリ制限付きでサービス起動
docker compose up -d --scale api= 3
Claude Codeに docker stats の出力を渡して「最適なメモリ制限値の算出」を依頼することで、本番環境のリソース設計を効率化できます。
GitHub Actions × Docker — CI/CDパイプラインの完全自動化
Claude Codeが生成するCI/CDワークフロー
claude "以下の要件でGitHub ActionsのCI/CDワークフローを作成してください:
- mainブランチへのpushでDockerイメージをビルド・テスト
- タグプッシュ時にGHCRへpushしてCloud Runへデプロイ
- キャッシュを活用してビルド時間を短縮
- セキュリティスキャン(Trivy)を組み込む"
生成される .github/workflows/deploy.yml:
name : Build and Deploy
on :
push :
branches : [ main ]
tags : [ "v*" ]
pull_request :
branches : [ main ]
env :
REGISTRY : ghcr.io
IMAGE_NAME : ${{ github.repository }}
jobs :
# ──── テスト ────
test :
runs-on : ubuntu-latest
services :
postgres :
image : postgres:16-alpine
env :
POSTGRES_PASSWORD : test
POSTGRES_DB : testdb
options : >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports :
- 5432:5432
steps :
- uses : actions/checkout@v4
- name : Setup Node.js
uses : actions/setup-node@v4
with :
node-version : "22"
cache : "npm"
- name : Install dependencies
run : npm ci
- name : Run unit tests
run : npm test
- name : Run integration tests
run : npm run test:integration
env :
DATABASE_URL : postgresql://postgres:test@localhost:5432/testdb
# ──── ビルド & プッシュ ────
build-and-push :
needs : test
runs-on : ubuntu-latest
if : github.event_name != 'pull_request'
permissions :
contents : read
packages : write
outputs :
image-digest : ${{ steps.build.outputs.digest }}
image-tag : ${{ steps.meta.outputs.tags }}
steps :
- uses : actions/checkout@v4
- name : Set up QEMU(マルチアーキテクチャビルド用)
uses : docker/setup-qemu-action@v3
- name : Set up Docker Buildx
uses : docker/setup-buildx-action@v3
- name : Log in to GHCR
uses : docker/login-action@v3
with :
registry : ${{ env.REGISTRY }}
username : ${{ github.actor }}
password : ${{ secrets.GITHUB_TOKEN }}
- name : Extract Docker metadata
id : meta
uses : docker/metadata-action@v5
with :
images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags : |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
- name : Build and push
id : build
uses : docker/build-push-action@v5
with :
context : .
platforms : linux/amd64,linux/arm64
push : true
tags : ${{ steps.meta.outputs.tags }}
labels : ${{ steps.meta.outputs.labels }}
cache-from : type=gha
cache-to : type=gha,mode=max
# ──── セキュリティスキャン ────
security-scan :
needs : build-and-push
runs-on : ubuntu-latest
steps :
- name : Run Trivy vulnerability scanner
uses : aquasecurity/trivy-action@master
with :
image-ref : ${{ needs.build-and-push.outputs.image-tag }}
format : "sarif"
output : "trivy-results.sarif"
severity : "CRITICAL,HIGH"
- name : Upload Trivy scan results
uses : github/codeql-action/upload-sarif@v3
with :
sarif_file : "trivy-results.sarif"
# ──── Cloud Run へのデプロイ(タグ時のみ)────
deploy :
needs : [ build-and-push , security-scan ]
runs-on : ubuntu-latest
if : startsWith(github.ref, 'refs/tags/v')
environment : production
steps :
- name : Authenticate to Google Cloud
uses : google-github-actions/auth@v2
with :
credentials_json : ${{ secrets.GCP_SA_KEY }}
- name : Deploy to Cloud Run
uses : google-github-actions/deploy-cloudrun@v2
with :
service : myapp
image : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-and-push.outputs.image-digest }}
region : asia-northeast1
flags : |
--min-instances=1
--max-instances=10
--memory=512Mi
--cpu=1
このワークフローでは、GHA キャッシュを使えばビルド時間を初回5分 → 2回目以降1分以内 に短縮できます。
セキュリティハードニング — 本番コンテナを守る実践的手法
Claude Codeによるセキュリティ強化
claude "現在のDockerfileのセキュリティ問題を洗い出して、
CISベンチマークに準拠した修正版を作成してください。
特に: 非rootユーザー、不要パッケージの排除、read-onlyファイルシステムを重視してください"
セキュリティ強化の主要ポイント:
1. 非rootユーザーの徹底
# 専用ユーザーの作成
RUN addgroup --gid 1001 appgroup && \
adduser --uid 1001 --gid 1001 --disabled-password appuser
# ファイル所有権の設定
COPY --chown=appuser:appgroup . .
USER appuser
2. 不要なツールの排除
# 本番イメージにシェルや開発ツールを含めない
FROM gcr.io/distroless/nodejs22-debian12:nonroot AS runner
# ← distrolessはシェルすら含まない最小イメージ
3. read-onlyファイルシステムの設定
# docker-compose.yml での設定
services :
app :
read_only : true
tmpfs :
- /tmp
- /app/logs
security_opt :
- no-new-privileges:true
cap_drop :
- ALL
4. シークレット管理
# Dockerビルド時のシークレットを安全に扱う
docker build \
--secret id=api_key,env=API_KEY \
-t myapp:prod .
# Dockerfileでのシークレット参照
RUN --mount=type=secret,id=api_key \
API_KEY=$(cat /run/secrets/api_key) npm run build:with-key
# ← ビルドキャッシュやイメージ履歴にシークレットが残らない
脆弱性スキャンの自動化
# Trivyによるスキャン(Claude Codeで解釈を依頼)
trivy image myapp:prod --format json | \
claude "このTrivy脆弱性レポートを分析し、
緊急対応が必要な問題と修正方法を優先度順に教えてください"
Kubernetes 本番デプロイ — Claude Codeと学ぶ実践的なマニフェスト設計
K8s マニフェストの生成
Kubernetesのマニフェスト作成はClaude Codeが最も得意とする作業の一つです:
claude "以下の要件でKubernetesマニフェストを作成してください:
- Deployment: 3レプリカ、ローリングアップデート
- Service: ClusterIP(Ingressからのみアクセス)
- HPA: CPU 70%でスケールアウト(最大10レプリカ)
- PodDisruptionBudget: 最低2レプリカを常に維持
- リソースリクエスト・リミット設定済み"
生成される deployment.yaml:
apiVersion : apps/v1
kind : Deployment
metadata :
name : myapp
namespace : production
labels :
app : myapp
version : "1.0.0"
spec :
replicas : 3
selector :
matchLabels :
app : myapp
strategy :
type : RollingUpdate
rollingUpdate :
maxUnavailable : 1
maxSurge : 1
template :
metadata :
labels :
app : myapp
spec :
# セキュリティコンテキスト
securityContext :
runAsNonRoot : true
runAsUser : 1001
fsGroup : 1001
# グレースフルシャットダウン
terminationGracePeriodSeconds : 60
containers :
- name : app
image : ghcr.io/myorg/myapp:v1.0.0
ports :
- containerPort : 3000
# リソース設定(実測値ベースで調整)
resources :
requests :
cpu : "100m"
memory : "128Mi"
limits :
cpu : "500m"
memory : "512Mi"
# ヘルスチェック
livenessProbe :
httpGet :
path : /api/health
port : 3000
initialDelaySeconds : 10
periodSeconds : 10
failureThreshold : 3
readinessProbe :
httpGet :
path : /api/ready
port : 3000
initialDelaySeconds : 5
periodSeconds : 5
successThreshold : 1
# セキュリティ
securityContext :
allowPrivilegeEscalation : false
readOnlyRootFilesystem : true
capabilities :
drop :
- ALL
# 一時ファイル用ボリューム
volumeMounts :
- name : tmp-volume
mountPath : /tmp
volumes :
- name : tmp-volume
emptyDir : {}
---
apiVersion : autoscaling/v2
kind : HorizontalPodAutoscaler
metadata :
name : myapp-hpa
namespace : production
spec :
scaleTargetRef :
apiVersion : apps/v1
kind : Deployment
name : myapp
minReplicas : 3
maxReplicas : 10
metrics :
- type : Resource
resource :
name : cpu
target :
type : Utilization
averageUtilization : 70
- type : Resource
resource :
name : memory
target :
type : Utilization
averageUtilization : 80
---
apiVersion : policy/v1
kind : PodDisruptionBudget
metadata :
name : myapp-pdb
namespace : production
spec :
minAvailable : 2
selector :
matchLabels :
app : myapp
Fly.io への代替デプロイ(Kubernetesなしのシンプル本番環境)
Kubernetesが大げさな場合、Fly.ioはDockerコンテナをそのまま本番デプロイできる優れた代替手段です:
# Claude Codeにfly.toml生成を依頼
claude "Next.js アプリをFly.ioにデプロイするためのfly.tomlを作成してください。
東京リージョン、512MBメモリ、自動スケールなし(固定2インスタンス)"
# fly.toml
app = "myapp"
primary_region = "nrt" # 東京
kill_signal = "SIGINT"
kill_timeout = "5s"
[ build ]
dockerfile = "Dockerfile"
[ env ]
PORT = "8080"
NODE_ENV = "production"
[ http_service ]
internal_port = 8080
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 2
[[ http_service . checks ]]
grace_period = "10s"
interval = "30s"
method = "GET"
path = "/api/health"
timeout = "5s"
[[ vm ]]
memory = "512mb"
cpu_kind = "shared"
cpus = 1
デプロイは fly deploy の一コマンドで完了します。
よくあるエラーと対処法
エラー1: ENOSPC: no space left on device
# 不要なイメージ・コンテナの一括削除
docker system prune -af --volumes
# Claude Codeで根本原因を分析
df -h | claude "このディスク使用状況を分析して、
Docker関連ファイルの削減方法を教えてください"
エラー2: ビルドキャッシュが効かない
# キャッシュの効率を確認
docker build --progress=plain . 2>&1 | grep -E "CACHED|DONE"
# 典型的な原因: COPYの順序が最適化されていない
# Claude Codeに修正を依頼:
claude "このDockerfileのキャッシュ効率を改善してください。
COPY命令の順序を最適化して、コード変更時の再ビルドを最小化してください"
エラー3: 本番コンテナでのメモリOOM(Out of Memory)
# OOMの確認
docker events --filter event=oom
# メモリ使用量の詳細確認
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
# Claude Codeで最適化を依頼
claude "Node.jsアプリのDockerコンテナが512MBでOOMします。
--max-old-space-sizeの設定とK8sのresource limitsを
どう調整すべきか教えてください"
まとめ
Claude Code × Docker の組み合わせは、現代的なコンテナ開発ワークフローを劇的に効率化します。本記事で解説した主要なポイントを振り返ります:
DevContainer : チーム全体で再現性のある開発環境を実現。Claude Codeが設定ファイルを自動生成
マルチステージビルド : 本番イメージを100MB以下に最小化。Claude Codeがアーキテクチャに最適なDockerfileを提案
Docker Compose : ローカルマルチサービス環境を宣言的に管理。エラーのデバッグもClaude Codeに任せられる
GitHub Actions CI/CD : ビルド・テスト・セキュリティスキャン・デプロイを完全自動化
セキュリティ : 非rootユーザー・read-onlyファイルシステム・シークレット管理でCISベンチマーク準拠
Kubernetes / Fly.io : スケーラブルな本番デプロイメントをClaude Codeが生成するマニフェストで実現
Claude Codeを使えば、これまでDockerインフラの設計・実装に数日かかっていた作業を数時間で完成させられます。特に「どのベースイメージを使えばいいか」「マルチステージビルドはどう分けるか」「K8sのリソース設定はいくつが適切か」といった判断をClaude Codeに任せることで、インフラよりもアプリケーションのロジックに集中できるようになります。
CI/CDをさらに高度化したい方は、Claude CodeのHTTP HooksとGitHub Actionsを組み合わせたClaude Code HTTP Hooks × GitHub Actions 完全統合ガイド もあわせてご覧ください。また、Next.jsアプリをDockerコンテナで運用する場合は、Claude Code × Next.js 15 App Router 本番開発マスターガイド で詳細なアプリケーション側の設計を確認できます。
まずはDevContainerの設定から始めて、Claude Codeと対話しながら本番環境へのパスを一歩ずつ歩んでいきましょう。