docker
アプリケーションと依存関係をまとめて隔離されたポータブルなコンテナにパッケージングするDockerコンテナ化スキルです。開発・テスト・本番環境を問わず一貫した動作を保証し、環境差異によるトラブルを防ぎます。
description の原文を見る
Docker containerization for packaging applications with dependencies into isolated, portable units ensuring consistency across development, testing, and production environments.
SKILL.md 本文
Docker コンテナ化スキル
サマリー
Docker はアプリケーションとその依存関係を独立したポータブルなユニットにパッケージ化するためのコンテナ化を提供します。コンテナは開発、テスト、本番環境全体で一貫性を確保し、「自分のマシンでは動作する」という問題を排除します。
使用すべき時期
- ローカル開発: チームメンバー間で一貫した開発環境
- CI/CDパイプライン: 再現可能なビルドおよびテスト環境
- マイクロサービス: 独立したスケーリングを持つ隔離されたサービス
- 本番デプロイメント: クラウドプロバイダー全体でのポータブルアプリケーション
- データベース/サービステスト: 統合テスト用の一時的なデータベース
- レガシーアプリケーション分離: 互換性のない依存関係を並行実行
クイックスタート
1. Dockerfile の作成
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
2. イメージのビルド
docker build -t myapp:1.0 .
3. コンテナの実行
docker run -p 3000:3000 myapp:1.0
コア概念
イメージ vs コンテナ
- イメージ: アプリケーションコード、ランタイム、依存関係を含む読み取り専用テンプレート
- コンテナ: 書き込み可能なレイヤーを持つイメージの実行インスタンス
- レジストリ: イメージの保存場所(Docker Hub、GitHub Container Registry)
レイヤーとキャッシング
各 Dockerfile の命令はレイヤーを作成します。Docker は変更されていないレイヤーをキャッシュしてビルドを高速化します。
# 良い例: 依存関係はコードより変更頻度が低い
FROM python:3.11-slim
COPY requirements.txt .
RUN pip install -r requirements.txt # requirements.txt が変更されない限りキャッシュ
COPY . . # コード変更時のみ再ビルド
# 悪い例: コード変更のたびにキャッシュが無効化される
FROM python:3.11-slim
COPY . . # 頻繁に変更
RUN pip install -r requirements.txt # ビルドのたびに再インストール
ボリューム
コンテナ再起動後も存続する永続データストレージ。
# 名前付きボリューム (Docker で管理)
docker run -v mydata:/app/data myapp
# バインドマウント (ホストディレクトリ)
docker run -v $(pwd)/data:/app/data myapp
# 匿名ボリューム (一時的)
docker run -v /app/data myapp
ネットワーク
コンテナは Docker ネットワークを通じて通信します。
# ネットワークの作成
docker network create mynetwork
# ネットワーク上でコンテナを実行
docker run --network mynetwork --name db postgres
docker run --network mynetwork --name app myapp
# アプリはホスト名 "db" を使用して db に接続可能
Dockerfile 基礎
重要な命令
# ベースイメージ
FROM node:18-alpine
# メタデータ
LABEL maintainer="dev@example.com"
LABEL version="1.0"
# ワーキングディレクトリの設定
WORKDIR /app
# ファイルのコピー
COPY package*.json ./
COPY src/ ./src/
# コマンドの実行 (レイヤーを作成)
RUN npm ci --only=production
# 環境変数の設定
ENV NODE_ENV=production
ENV PORT=3000
# ポートの公開 (ドキュメンテーションのみ)
EXPOSE 3000
# デフォルトコマンド
CMD ["node", "src/server.js"]
# 代替手段: ENTRYPOINT (docker run の引数で上書きされない)
ENTRYPOINT ["node"]
CMD ["src/server.js"] # ENTRYPOINT のデフォルト引数
キャッシュ効率のための命令順序
# 1. ベースイメージ (ほぼ変更なし)
FROM python:3.11-slim
# 2. システム依存関係 (ほぼ変更なし)
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 3. アプリケーション依存関係 (たまに変更)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 4. アプリケーションコード (頻繁に変更)
COPY . .
# 5. ランタイム設定
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
.dockerignore
ビルドコンテキストからファイルを除外 (ビルド高速化、イメージサイズ削減)。
# .dockerignore
node_modules/
npm-debug.log
.git/
.gitignore
*.md
.env
.vscode/
__pycache__/
*.pyc
.pytest_cache/
coverage/
dist/
build/
マルチステージビルド
ビルドステージとランタイムステージを分離してイメージサイズを最適化します。
Node.js TypeScript の例
# ビルドステージ
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 本番ステージ
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
メリット:
- ビルド依存関係 (TypeScript、webpack) は最終イメージから除外
- 最終イメージ: ビルドツール付きで約500MB ではなく約50MB
- デプロイメント高速化と攻撃面縮小
Python の例
# ビルドステージ
FROM python:3.11 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# ランタイムステージ
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Go の例 (最小イメージ)
# ビルドステージ
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server
# ランタイムステージ (scratch = 空のベースイメージ)
FROM scratch
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
結果: コンパイル済みバイナリのみを含む約10MB の最終イメージ。
Docker Compose
YAML で マルチコンテナアプリケーションを定義します。
基本構造
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/myapp
depends_on:
- db
volumes:
- ./src:/app/src # 開発時ホットリロード
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
db_data:
コマンド
# すべてのサービスを起動
docker-compose up
# バックグラウンドで起動
docker-compose up -d
# イメージを再ビルド
docker-compose up --build
# サービスを停止
docker-compose down
# サービスを停止してボリュームを削除
docker-compose down -v
# ログを表示
docker-compose logs -f app
# ワンタイムコマンドを実行
docker-compose run app npm test
フルスタック例
version: '3.8'
services:
# フロントエンド
web:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./frontend/src:/app/src
environment:
- REACT_APP_API_URL=http://localhost:8000
# バックエンド API
api:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./backend:/app
command: uvicorn main:app --host 0.0.0.0 --reload
# データベース
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
# キャッシュ
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
# ワーカー (バックグラウンドジョブ)
worker:
build: ./backend
command: celery -A tasks worker --loglevel=info
environment:
- REDIS_URL=redis://redis:6379
depends_on:
- redis
- db
volumes:
db_data:
redis_data:
networks:
default:
name: myapp_network
開発ワークフロー
ボリュームを使用したホットリロード
Node.js
services:
app:
build: .
volumes:
- ./src:/app/src # ソースコード同期
- /app/node_modules # コンテナの node_modules 上書き防止
command: npm run dev
# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install # 開発依存関係を含める
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
Python (Django/FastAPI)
services:
web:
build: .
volumes:
- .:/app
command: python manage.py runserver 0.0.0.0:8000
# または FastAPI の場合:
# command: uvicorn main:app --host 0.0.0.0 --reload
VS Code Dev Containers
.devcontainer/devcontainer.json:
{
"name": "Python Dev Container",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/app",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
],
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python"
}
}
},
"postCreateCommand": "pip install -r requirements-dev.txt",
"remoteUser": "vscode"
}
ローカルデータベースコンテナ
# PostgreSQL
docker run -d \
--name dev-postgres \
-e POSTGRES_PASSWORD=localdev \
-e POSTGRES_DB=myapp_dev \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:15-alpine
# MySQL
docker run -d \
--name dev-mysql \
-e MYSQL_ROOT_PASSWORD=localdev \
-e MYSQL_DATABASE=myapp_dev \
-p 3306:3306 \
-v mysqldata:/var/lib/mysql \
mysql:8
# MongoDB
docker run -d \
--name dev-mongo \
-p 27017:27017 \
-v mongodata:/data/db \
mongo:7
# Redis
docker run -d \
--name dev-redis \
-p 6379:6379 \
redis:7-alpine
本番パターン
ヘルスチェック
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# ヘルスチェックエンドポイント
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD node healthcheck.js
EXPOSE 3000
CMD ["node", "server.js"]
// healthcheck.js
const http = require('http');
const options = {
host: 'localhost',
port: 3000,
path: '/health',
timeout: 2000
};
const request = http.request(options, (res) => {
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on('error', () => process.exit(1));
request.end();
セキュリティベストプラクティス
FROM python:3.11-slim
# 1. 非root ユーザーを使用
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 2. 依存関係を root として インストール
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 3. アプリケーションファイルをコピー
COPY --chown=appuser:appuser . .
# 4. 非root ユーザーに切り替え
USER appuser
# 5. 不要な権限を削除
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
追加のセキュリティ対策:
- 最小限のベースイメージ (alpine、distroless) を使用
- イメージの脆弱性をスキャン:
docker scan myapp:latest - イメージにシークレットを含めない (環境変数またはシークレット管理ツールを使用)
- ベースイメージを更新に保つ
- 可能な限りルートファイルシステムを読み取り専用に
シークレット管理
# Docker Swarm シークレット (本番)
echo "db_password_here" | docker secret create db_password -
version: '3.8'
services:
app:
image: myapp
secrets:
- db_password
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
external: true
代替案: 環境ファイル
# docker-compose.yml
services:
app:
env_file:
- .env.production # このファイルはコミットしない
# .env.production (gitignore)
DATABASE_URL=postgresql://user:pass@db:5432/prod
SECRET_KEY=your-secret-key
リソースリミット
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# コマンドラインリソースリミット
docker run -d \
--memory="512m" \
--cpus="1.0" \
--restart=unless-stopped \
myapp
フレームワーク固有の例
Python: Django
FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
WORKDIR /app
# システム依存関係のインストール
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Python 依存関係のインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションをコピー
COPY . .
# 静的ファイルを収集
RUN python manage.py collectstatic --noinput
# 非root ユーザーを作成
RUN useradd -m -u 1000 django && chown -R django:django /app
USER django
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "myproject.wsgi:application"]
docker-compose.yml:
version: '3.8'
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DEBUG=1
- DATABASE_URL=postgres://postgres:postgres@db:5432/django_dev
depends_on:
- db
db:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: django_dev
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Python: FastAPI
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
Node.js: Next.js
# Next.js 用のマルチステージビルド
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
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
CMD ["node", "server.js"]
next.config.js (スタンドアロン出力に必須):
module.exports = {
output: 'standalone',
}
Node.js: Express
FROM node:18-alpine
WORKDIR /app
# 依存関係をインストール
COPY package*.json ./
RUN npm ci --only=production
# アプリケーションをコピー
COPY . .
# 非root ユーザーを作成
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
TypeScript ビルド
# ビルドステージ
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm ci
COPY src/ ./src/
RUN npm run build
# 本番ステージ
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]
コンテナオーケストレーション基礎
Docker Swarm (組み込み)
# Swarm を初期化
docker swarm init
# スタックをデプロイ
docker stack deploy -c docker-compose.yml myapp
# サービスをスケール
docker service scale myapp_web=5
# サービスを更新 (ダウンタイムなし)
docker service update --image myapp:2.0 myapp_web
# スタックを削除
docker stack rm myapp
Kubernetes との比較
| 機能 | Docker Compose | Docker Swarm | Kubernetes |
|---|---|---|---|
| 複雑さ | 低 | 中 | 高 |
| ユースケース | ローカル開発 | 小規模クラスタ | 本番規模 |
| セットアップ | 単一ファイル | 組み込み | 別途インストール |
| スケーリング | 手動 | 自動 | 自動 + 高度 |
| HA | なし | あり | あり |
| エコシステム | 限定的 | Docker | 膨大 |
それぞれの使い分け:
- Docker Compose: ローカル開発、シンプルなデプロイ
- Docker Swarm: 小規模本番クラスタ、K8s より単純
- Kubernetes: 大規模本番、マルチクラウド、高度なオーケストレーション
CI/CD 統合
GitHub Actions
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run tests
run: |
docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} npm test
GitLab CI
# .gitlab-ci.yml
stages:
- build
- test
- deploy
variables:
DOCKER_DRIVER: overlay2
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
test:
stage: test
script:
- docker run --rm $IMAGE_TAG npm test
deploy:
stage: deploy
script:
- docker pull $IMAGE_TAG
- docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
コンテナのデバッグ
ログを表示
# ログをストリーム表示
docker logs -f container_name
# 最後の 100 行
docker logs --tail 100 container_name
# タイムスタンプ以降のログ
docker logs --since 2024-01-01T10:00:00 container_name
# タイムスタンプ付きで表示
docker logs -t container_name
# Docker Compose のログ
docker-compose logs -f service_name
実行中のコンテナでコマンドを実行
# インタラクティブシェル
docker exec -it container_name /bin/sh
# または
docker exec -it container_name /bin/bash
# 単一コマンドを実行
docker exec container_name ls -la /app
# 別のユーザーとして実行
docker exec -u root container_name apt-get update
コンテナを検査
# コンテナの完全な詳細
docker inspect container_name
# 特定フィールド (IP アドレス)
docker inspect -f '{{.NetworkSettings.IPAddress}}' container_name
# 環境変数
docker inspect -f '{{.Config.Env}}' container_name
# マウントされたボリューム
docker inspect -f '{{.Mounts}}' container_name
リソース使用状況
# リアルタイム統計
docker stats
# 単一コンテナ
docker stats container_name
# ストリーミングなし (1 回のスナップショット)
docker stats --no-stream
ネットワークのデバッグ
# ネットワークをリスト表示
docker network ls
# ネットワークを検査
docker network inspect bridge
# コンテナ間の接続テスト
docker exec container1 ping container2
# DNS 解決をチェック
docker exec container_name nslookup other_container
ビルド問題のデバッグ
# キャッシュなしでビルド
docker build --no-cache -t myapp .
# ビルド進行状況を表示
docker build --progress=plain -t myapp .
# 特定ステージをビルド
docker build --target builder -t myapp-builder .
# 中間レイヤーを検査
docker history myapp:latest
ローカル Docker パターン (mcp-browser、mcp-memory)
mcp-browser 開発 compose
docker-compose.ymlはポート範囲8875-8895でmcp-serverを実行し、オプションのchromeプロファイルに対応- コードマウントは読み取り専用 (
./src:/app/src:ro) で永続ログと一時ボリュームあり - 環境デフォルト:
MCP_DEBUG=true、MCP_LOG_LEVEL=DEBUG、MCP_HOST=0.0.0.0、MCP_PORT=8875 - オプションプロファイル:
chrome(ブラウザ) とtools(開発ツールコンテナ)
mcp-browser Dockerfile.dev
ARG PYTHON_VERSION=3.11、watchdog+ Playwright Chromium をインストール- パッケージをエディタブルモードでインストールし、
python -m src.dev_runnerを実行 - 非root ユーザーと
/healthヘルスチェック
mcp-memory 本番 Dockerfile
/opt/venvに venv を持つマルチステージビルドとpython:3.11-slim- ランタイムはヘルスチェック用に
curlをインストール、PYTHONPATH=/appを設定 - 非root ユーザーと
CMD ["python", "run_api_server.py"]、/healthチェック
トラブルシューティング
よくある問題
「ポートが既に使用されている」
# ポートを使用中のプロセスを見つける
lsof -i :3000
# または
netstat -tulpn | grep 3000
# プロセスを強制終了
kill -9 <PID>
# または別のホストポートを使用
docker run -p 3001:3000 myapp
「Docker デーモンに接続できない」
# Docker が実行中か確認
docker info
# Docker Desktop を再起動 (Mac/Windows)
# または
sudo systemctl restart docker # Linux
# 権限を確認 (Linux)
sudo usermod -aG docker $USER
# ログアウトして再度ログイン
「デバイスに空きがない」
# 未使用のコンテナ、イメージ、ボリュームを削除
docker system prune -a --volumes
# ダングリングイメージのみ削除
docker image prune
# 停止中のコンテナを削除
docker container prune
# 未使用のボリュームを削除
docker volume prune
# ディスク使用状況をチェック
docker system df
「ビルドコンテキストが大きすぎる」
# .dockerignore を作成
cat > .dockerignore << EOF
node_modules/
.git/
*.log
dist/
coverage/
EOF
# 特定のコンテキストでビルド
docker build -f Dockerfile -t myapp ./src
コンテナが直ちに終了
# ログをチェック
docker logs container_name
# インタラクティブシェルで実行してデバッグ
docker run -it myapp /bin/sh
# entrypoint をオーバーライド
docker run -it --entrypoint /bin/sh myapp
# 終了コードをチェック
docker inspect -f '{{.State.ExitCode}}' container_name
コンテナ内で権限が拒否
# root として実行してデバッグ
docker exec -u root -it container_name /bin/sh
# 所有権を修正
docker exec -u root container_name chown -R appuser:appuser /app
# または Dockerfile で正しい権限でリビルド
パフォーマンス問題
ビルドが遅い
# BuildKit を使用 (高速化、キャッシング改善)
DOCKER_BUILDKIT=1 docker build -t myapp .
# マルチステージビルドでレイヤー削減
# 命令を変更頻度順に並べる
# 不要なファイルを .dockerignore で除外
メモリ使用率が高い
# メモリリミットを設定
docker run -m 512m myapp
# メモリをモニタリング
docker stats container_name
# アプリケーションのメモリリーク確認
ボリュームマウントが遅い (Mac/Windows)
# delegated 一貫性を使用 (Mac)
volumes:
- ./src:/app/src:delegated
# または バインドマウントの代わりに名前付きボリュームを使用
volumes:
- node_modules:/app/node_modules
ベストプラクティス
レイヤー最適化
- 変更頻度順に並べる: 最も頻度の低いものを最初に
- RUN コマンドを結合: レイヤー数を削減
- 同じレイヤーでクリーンアップ: 一時ファイルをすぐに削除
# 良い例
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*
# 悪い例 (3 つのレイヤーを作成、apt キャッシュがレイヤー 2 に残る)
RUN apt-get update
RUN apt-get install -y package1 package2
RUN rm -rf /var/lib/apt/lists/*
イメージサイズの削減
- Alpine イメージを使用: フル Linux の 5MB vs 100MB 以上
- マルチステージビルド: ビルドツールを最終イメージから除外
- 不要なファイルを削除: ドキュメント、例、テスト
- .dockerignore を使用: 開発ファイルを除外
# 前: 800MB
FROM node:18
COPY . .
RUN npm install
CMD ["node", "server.js"]
# 後: 120MB
FROM node:18-alpine
COPY package*.json ./
RUN npm ci --only=production
COPY server.js .
CMD ["node", "server.js"]
セキュリティチェックリスト
- 信頼されたソースの公式ベースイメージを使用
- イメージバージョンを正確に指定 (
latestではなく) - 非root ユーザーとして実行
- イメージの脆弱性をスキャン
- ベースイメージを更新に保つ
- イメージにシークレットを埋め込まない
- 可能な限りルートファイルシステムを読み取り専用に
- 攻撃面を最小化 (alpine、distroless)
- Docker Content Trust を有効化 (イメージ署名)
開発 vs 本番
開発:
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install # 開発依存関係を含める
COPY . .
CMD ["npm", "run", "dev"]
本番:
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]
ログのベストプラクティス
# stdout/stderr にログを出力 (Docker が取得)
CMD ["node", "server.js"] # 良い例
# ファイルにログを出力しない (コンテナ停止時に失われる)
CMD ["node", "server.js", ">", "app.log"] # 悪い例
// アプリケーションログ
console.log('Info message'); // stdout
console.error('Error message'); // stderr
// 構造化ログを使用
console.log(JSON.stringify({
level: 'info',
timestamp: new Date().toISOString(),
message: 'Request processed',
requestId: '123'
}));
環境設定
# ビルド時変数に ARG を使用
ARG NODE_ENV=production
ENV NODE_ENV=$NODE_ENV
# ランタイム変数に ENV を使用
ENV PORT=3000
ENV LOG_LEVEL=info
# ランタイムでオーバーライド
# docker run -e PORT=8080 -e LOG_LEVEL=debug myapp
ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# docker-compose.yml
services:
app:
image: myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40s
グレースフルシャットダウン
// Node.js 例
process.on('SIGTERM', () => {
console.log('SIGTERM received, closing server...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
# exec フォーム使用でシグナル処理
CMD ["node", "server.js"] # 良い例
CMD node server.js # 悪い例 (/bin/sh でラップ、シグナル転送なし)
クイックリファレンス
必須コマンド
# イメージ
docker build -t name:tag .
docker pull image:tag
docker push image:tag
docker images
docker rmi image:tag
# コンテナ
docker run -d --name container image
docker ps # 実行中のコンテナ
docker ps -a # すべてのコンテナ
docker stop container
docker start container
docker restart container
docker rm container
docker logs -f container
docker exec -it container /bin/sh
# クリーンアップ
docker system prune -a # 未使用リソースをすべて削除
docker container prune # 停止中のコンテナを削除
docker image prune # ダングリングイメージを削除
docker volume prune # 未使用ボリュームを削除
# Compose
docker-compose up -d
docker-compose down
docker-compose logs -f
docker-compose exec service /bin/sh
docker-compose build
よく使うフラグ
# docker run フラグ
-d # デタッチ (バックグラウンド)
-it # インタラクティブで TTY
-p 8080:80 # ポートマッピング (ホスト:コンテナ)
--name myapp # コンテナ名
-e VAR=value # 環境変数
-v /host:/container # ボリュームマウント
--network name # ネットワークに接続
--rm # 終了時にコンテナを削除
-m 512m # メモリリミット
--cpus 1.0 # CPU リミット
Dockerfile 命令
FROM image:tag # ベースイメージ
WORKDIR /path # ワーキングディレクトリを設定
COPY src dst # ファイルをコピー
ADD src dst # コピー (URL/tar サポート)
RUN command # コマンドを実行
ENV KEY=value # 環境変数
EXPOSE port # ポートをドキュメント化
CMD ["executable"] # デフォルトコマンド
ENTRYPOINT ["exec"] # コマンドプレフィックス
VOLUME /path # マウントポイントを作成
USER username # ユーザーを設定
ARG name=default # ビルド引数
LABEL key=value # メタデータ
HEALTHCHECK CMD command # ヘルスチェック
まとめ
Docker コンテナ化は以下を提供します:
- 一貫性: 開発から本番までの同一環境
- 分離: アプリケーション間で依存関係が競合しない
- ポータビリティ: Docker が実行できるあらゆる場所で動作 (クラウド、ローカル、CI)
- 効率: VM 比で軽量、高速起動
- スケーラビリティ: オーケストレーションでの簡単な水平スケーリング
主要ワークフロー:
- 開発: ホットリロードボリュームを使用した docker-compose
- CI/CD: イメージビルド、テスト、レジストリへのプッシュ
- 本番: イメージをプル、リソースリミットとヘルスチェック付きで実行
次のステップ:
- イメージサイズ最適化のためのマルチステージビルドをマスター
- ヘルスチェックとグレースフルシャットダウンを実装
- ローカル開発用に docker-compose を設定
- CI/CD パイプラインに Docker を統合
- 本番規模用のオーケストレーション (Swarm または Kubernetes) を検討
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- bobmatnyc
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/bobmatnyc/claude-mpm-skills / ライセンス: MIT
関連スキル
superpowers-streamer-cli
SuperPowers デスクトップストリーマーの npm パッケージをインストール、ログイン、実行、トラブルシューティングできます。ユーザーが npm から `superpowers-ai` をセットアップしたい場合、メールまたは電話でサインインもしくはアカウント作成を行いたい場合、ストリーマーを起動したい場合、表示されたコントロールリンクを開きたい場合、後で停止したい場合、またはソースコードへのアクセスなしに npm やランタイムの一般的な問題から復旧したい場合に使用します。
catc-client-ops
Catalyst Centerのクライアント操作・監視機能 - 有線・無線クライアントのリスト表示・フィルタリング、MACアドレスによる詳細なクライアント検索、クライアント数分析、時間軸での分析、SSIDおよび周波数帯によるフィルタリング、無線トラブルシューティング機能を提供します。MACアドレスやIPアドレスでのクライアント検索、サイト別やSSID別のクライアント数集計、無線周波数帯の分布分析、Wi-Fi信号の問題調査が必要な場合に活用できます。
ci-cd-and-automation
CI/CDパイプラインの設定を自動化します。ビルドおよびデプロイメントパイプラインの構築または変更時に使用できます。品質ゲートの自動化、CI内のテストランナー設定、またはデプロイメント戦略の確立が必要な場合に活用します。
shipping-and-launch
本番環境へのリリース準備を行います。本番環境へのデプロイ準備が必要な場合、リリース前チェックリストが必要な場合、監視機能の設定を行う場合、段階的なロールアウトを計画する場合、またはロールバック戦略が必要な場合に使用します。
linear-release-setup
Linear Releaseに向けたCI/CD設定を生成します。リリース追跡の設定、LinearのCIパイプライン構築、またはLinearリリースとのデプロイメント連携を実施する際に利用できます。GitHub Actions、GitLab CI、CircleCIなど複数のプラットフォームに対応しています。
tracking-application-response-times
API エンドポイント、データベースクエリ、サービスコール全体にわたるアプリケーションのレスポンスタイムを追跡・最適化できます。パフォーマンス監視やボトルネック特定の際に活用してください。「レスポンスタイムを追跡する」「API パフォーマンスを監視する」「遅延を分析する」といった表現で呼び出せます。