コンテナ
アプリケーションとその依存関係をパッケージ化し、環境に依存しない一貫した実行環境を提供する仮想化技術
コンテナとは
コンテナは、アプリケーションのコード、ランタイム、ライブラリ、設定ファイルを 1 つのパッケージにまとめ、どの環境でも同一の動作を保証する軽量な仮想化技術である。「自分のマシンでは動くのに本番では動かない」問題を根本的に解決する。
Linux の namespaces (プロセス、ネットワーク、ファイルシステムの分離) と cgroups (CPU、メモリの制限) がコンテナの基盤技術だ。Docker が 2013 年にコンテナを使いやすくパッケージ化し、爆発的に普及した。
VM との違い
| 観点 | コンテナ | 仮想マシン (VM) |
|---|---|---|
| 起動時間 | ミリ秒〜秒 | 分 |
| サイズ | MB 単位 (Alpine: 5MB) | GB 単位 |
| カーネル | ホスト OS と共有 | 独自のゲスト OS |
| 分離レベル | プロセスレベル | ハードウェアレベル |
| 密度 | 1 ホストに数十〜数百 | 1 ホストに数個〜数十 |
| 適するケース | マイクロサービス、CI/CD | 強い分離が必要な環境 |
コンテナはカーネルを共有するため VM より軽量だが、分離レベルは VM より弱い。マルチテナント環境で完全な分離が必要な場合は VM を使う。AWS の Fargate は Firecracker (軽量 VM) 上でコンテナを実行し、両方の利点を組み合わせている。
Dockerfile とイメージの最適化
実務ではイメージサイズの最適化が起動速度とセキュリティの両面で重要だ。
# マルチステージビルドで最終イメージを軽量化
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
CMD ["node", "dist/index.js"]
最適化のポイント:
- Alpine ベースイメージを使う (node:20 は 1GB 超、node:20-alpine は 180MB)
- マルチステージビルドで開発依存を最終イメージに含めない
USER nodeで非 root ユーザーで実行 (セキュリティ).dockerignoreで不要ファイルを除外
1 コンテナ 1 プロセスの原則
1 つのコンテナには 1 つのプロセスだけを実行する。Web サーバーとログ収集エージェントを同じコンテナに入れない。理由は以下のとおり。
- ヘルスチェックが明確になる (1 プロセスの生死 = コンテナの生死)
- スケーリングが独立する (Web サーバーだけスケールアウトできる)
- ログが分離される (stdout に出力すれば、コンテナランタイムが収集)
補助プロセス (ログ収集、プロキシ) はサイドカーパターンで別コンテナとして同一 Pod に配置する。
AWS でのコンテナ実行環境
| サービス | 特徴 | 適するケース |
|---|---|---|
| ECS on Fargate | サーバーレス、インフラ管理不要 | 小〜中規模、運用負荷を最小化 |
| ECS on EC2 | インスタンスを自前管理 | GPU、大容量メモリが必要 |
| EKS | Kubernetes マネージド | K8s エコシステムを活用 |
| Lambda (コンテナイメージ) | イベント駆動、最大 10GB | 既存コンテナを Lambda で実行 |
Lambda もコンテナイメージをサポートしている。既存の Docker イメージを Lambda で実行でき、最大 10GB のイメージサイズに対応する。
よくある失敗パターン
イメージに機密情報を含める
Dockerfile の ENV や COPY で API キーやパスワードをイメージに焼き込むと、イメージを取得した誰もが機密情報にアクセスできる。機密情報は環境変数や Secrets Manager で実行時に注入する。
latest タグの使用
FROM node:latest は再現性がない。ビルドのたびに異なるバージョンが使われる可能性がある。必ずバージョンを固定する (FROM node:20.11-alpine)。
# マルチステージビルド
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
COPY --from=build /app/dist ./dist
CMD ["node", "dist/index.js"]
詳しくは関連書籍を参照。