コンテナとは何か
コンテナは、アプリケーションとその依存関係(ライブラリ・設定・ランタイム)を1つのパッケージにまとめて、どこでも同じように動かす仕組みです。
仮想マシン(VM) コンテナ
┌────────────────┐ ┌────────────────┐
│ アプリ A │ │ アプリ A │
│ Python 3.11 │ │ Python 3.11 │
│ ライブラリ群 │ │ ライブラリ群 │
├────────────────┤ ├────────────────┤
│ ゲストOS │ │ Docker Engine│ ← OS共有
│ (Ubuntu等) │ ├────────────────┤
├────────────────┤ │ ホストOS │
│ ハイパーバイザー│ └────────────────┘
├────────────────┤
│ ホストOS │
└────────────────┘
VMはGByte、コンテナはMByte。起動はVMが分単位、コンテナは秒単位。
コンテナのメリット:
- 「手元では動くのに本番では動かない」問題を解消
- 開発・ステージング・本番で同じ環境を使える
- 複数の言語・バージョンをホスト環境に影響なく共存
Dockerの基本概念
| 概念 | 説明 | 例え |
|---|---|---|
| Image | コンテナの設計図(不変) | クラス |
| Container | Imageから作った実行インスタンス | インスタンス |
| Dockerfile | Imageを作るための手順書 | レシピ |
| Registry | Imageの保管場所 | Docker Hub, ECR |
| Volume | コンテナ外の永続ストレージ | 外付けHDD |
| Network | コンテナ間の仮想ネットワーク | LAN |
基本コマンド
# イメージの操作
docker pull nginx:latest # レジストリからイメージを取得
docker images # ローカルのイメージ一覧
docker rmi nginx:latest # イメージを削除
docker image prune # 未使用イメージを一括削除
# コンテナの起動
docker run nginx # フォアグラウンドで起動
docker run -d nginx # バックグラウンド(detached)
docker run -d -p 8080:80 nginx # ホスト8080→コンテナ80にポートマップ
docker run -d --name my-nginx nginx # コンテナに名前をつける
docker run -it ubuntu bash # 対話的シェル起動(-i: 入力, -t: 疑似端末)
# コンテナの操作
docker ps # 実行中のコンテナ一覧
docker ps -a # 全コンテナ(停止中も含む)
docker stop my-nginx # コンテナを停止(SIGTERM)
docker kill my-nginx # コンテナを強制停止(SIGKILL)
docker rm my-nginx # コンテナを削除
docker rm -f my-nginx # 実行中でも削除
# コンテナの中に入る
docker exec -it my-nginx bash # 実行中のコンテナでbashを起動
docker logs my-nginx # ログを表示
docker logs -f my-nginx # ログをリアルタイム追跡
# ボリューム
docker run -v /host/path:/container/path nginx # ホストのディレクトリをマウント
docker run -v my-volume:/data nginx # 名前付きボリューム
docker volume ls # ボリューム一覧
docker volume rm my-volume # ボリューム削除
Dockerfile の書き方
# Python FastAPIアプリの例
FROM python:3.11-slim # ベースイメージ(alpine/slimで軽量化)
WORKDIR /app # 作業ディレクトリを設定
# 依存関係ファイルだけを先にコピー(キャッシュ最適化)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリのソースをコピー
COPY . .
# ポートを公開(ドキュメント目的、実際の公開はrunの-p)
EXPOSE 8000
# 非rootユーザーで実行(セキュリティ)
RUN useradd -m appuser
USER appuser
# コンテナ起動時のコマンド
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
レイヤーキャッシュの最適化
# ❌ 悪い例: コードが変わるたびにpip installが走る
COPY . .
RUN pip install -r requirements.txt
# ✅ 良い例: requirements.txtが変わらなければキャッシュが使われる
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . . # ソース変更時もpip installはスキップ
# イメージのビルド
docker build -t my-app:1.0 . # タグ付きでビルド
docker build -t my-app:latest -f Dockerfile.prod . # Dockerfileを指定
docker build --no-cache -t my-app . # キャッシュなし
マルチステージビルド
# ビルドステージ(コンパイル等に使うツールを含む)
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 本番ステージ(軽量)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
ビルドツールを含まない軽量なイメージが生成されます。
docker-compose によるマルチコンテナ管理
複数のコンテナをまとめて管理します。Webアプリ+DB+キャッシュのような構成で活躍します。
# docker-compose.yml
version: "3.9"
services:
# Webアプリ
app:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgresql://user:pass@db:5432/mydb
REDIS_URL: redis://cache:6379
depends_on:
db:
condition: service_healthy # DBが起動してから起動
volumes:
- ./src:/app/src # ホットリロード用
# PostgreSQL
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data # データを永続化
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
timeout: 5s
retries: 5
# Redis
cache:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
# docker-compose の基本操作
docker compose up -d # バックグラウンドで全サービス起動
docker compose up --build # イメージを再ビルドして起動
docker compose down # 全コンテナを停止・削除
docker compose down -v # ボリュームも削除
docker compose logs -f app # appサービスのログを追跡
docker compose exec app bash # appコンテナに入る
docker compose ps # サービスの状態確認
docker compose restart app # appサービスを再起動
.dockerignore
不要なファイルをイメージに含めないためのファイルです。
# .dockerignore
node_modules/
.git/
.env
*.log
dist/
__pycache__/
*.pyc
.pytest_cache/
これがないと node_modules(数百MB)や .git が含まれてイメージが肥大化します。
よくあるパターン
環境変数の管理
# .env ファイルを使う(.gitignore に追加すること)
docker run --env-file .env my-app
docker compose --env-file .env up
ヘルスチェック
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
まとめ
| 用途 | コマンド |
|---|---|
| イメージ取得 | docker pull |
| コンテナ起動 | docker run -d -p 8080:80 |
| イメージビルド | docker build -t name . |
| コンテナ内に入る | docker exec -it name bash |
| ログ確認 | docker logs -f name |
| マルチコンテナ | docker compose up -d |
Docker は現代の開発・デプロイ基盤の中心です。まず docker run と docker compose up から始めて、徐々に Dockerfile の最適化を学んでいきましょう。