🐳 Dockerとは?
📖 定義
Dockerは、コンテナと呼ばれる隔離された環境でアプリケーションを実行するプラットフォームです。コンテナは、アプリケーションとすべての依存関係を1つにまとめ、どこでも同じように実行できるようにします。「私のマシンでは動く...」という問題を解決し、開発、テスト、デプロイを簡単で一貫性のあるものにします。
🎯 アナロジーで理解する
輸送コンテナ
Dockerを物流のコンテナに例えると:
従来の配送 (VM)
├─ 荷物ごとに異なる梱包
├─ サイズ/重量がバラバラ
├─ 輸送方法が異なる
└─ 非効率的、複雑
コンテナ配送 (Docker)
├─ 標準化されたコンテナ
├─ どんな荷物でも入れられる
├─ 船、トラック、列車どこでも同じ輸送
└─ 効率的、シンプル
Dockerコンテナ = 標準化されたソフトウェアパッケージ
アパート vs 一戸建て
仮想マシン (VM) = 一戸建て
├─ それぞれに完全なインフラが必要
├─ 土地、建物、電気、水道すべて別々
├─ コストが高い
└─ 起動が遅い
Dockerコンテナ = アパート
├─ 共通インフラを共有(土地、建物)
├─ 各戸は独立
├─ 効率的
└─ すぐに入居可能
⚙️ 動作原理
1. Dockerアーキテクチャ
┌─────────────────────────────────────┐
│ Docker Client (CLI) │
│ docker run, docker build, etc. │
└───────────────┬─────────────────────┘
│ API呼び出し
┌───────────────▼─────────────────────┐
│ Docker Daemon │
│ コンテナ/イメージ管理 │
└───────────────┬────────────────── ───┘
│
┌───────────────▼─────────────────────┐
│ コンテナ(実行中のアプリ) │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │App 1│ │App 2│ │App 3│ │
│ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────┘
│
┌───────────────▼─────────────────────┐
│ Host OS (Linux Kernel) │
└─────────────────────────────────────┘
2. イメージ vs コンテナ
イメージ = 設計図、クラス
├─ 読み取り専用
├─ レイヤー構造
├─ 再利用可能
└─ 例:ubuntu、node、nginx
コンテナ = 実行インスタンス、オブジェクト
├─ イメージから作成
├─ 実行可能
├─ 隔離された環境
└─ 複数作成可能
関係:
イメージ → コンテナ1
→ コンテナ2
→ コンテナ3
3. Dockerfile → イメージ → コンテナ
1. Dockerfileを書く(レシピ)
├─ FROM node:18
├─ COPY package.json .
├─ RUN npm install
└─ CMD ["npm", "start"]
2. イメージをビルド(調理)
docker build -t my-app .
3. コンテナを実行(提供)
docker run -p 3000:3000 my-app
💡 実践例
Dockerfileの作成
# Node.jsアプリケーションのDockerfile
# ベースイメージ
FROM node:18-alpine
# 作業ディレクトリを 設定
WORKDIR /app
# package.jsonをコピー
COPY package*.json ./
# 依存関係をインストール
RUN npm ci --only=production
# ソースコードをコピー
COPY . .
# ポートを公開
EXPOSE 3000
# 環境変数
ENV NODE_ENV=production
# コンテナ起動時に実行するコマンド
CMD ["node", "server.js"]
イメージのビルドと実行
# 1. イメージをビルド
docker build -t my-node-app:1.0 .
# -t: タグ(名前:バージョン)
# .: 現在のディレクトリのDockerfileを使用
# 2. イメージを確認
docker images
# REPOSITORY TAG IMAGE ID CREATED
# my-node-app 1.0 abc123 2分前
# 3. コンテナを実行
docker run -d \
--name my-app \
-p 3000:3000 \
-e NODE_ENV=production \
my-node-app:1.0
# -d: バックグラウンド実行
# --name: コンテナ名
# -p: ポートマッピング(ホスト:コンテナ)
# -e: 環境変数
# 4. 実行中のコンテナを確認
docker ps
# 5. ログを確認
docker logs my-app
# 6. コンテナ内部にアクセス
docker exec -it my-app sh
# 7. コンテナを停止
docker stop my-app
# 8. コンテナを削除
docker rm my-app
# 9. イメージを削除
docker rmi my-node-app:1.0
Docker Compose(複数コンテナの管理)
# docker-compose.yml
version: '3.8'
services:
# Webアプリケーション
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=database
depends_on:
- database
- redis
volumes:
- ./logs:/app/logs
# データベース
database:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=myapp
volumes:
- db-data:/var/lib/mysql
ports:
- "3306:3306"
# キャッシュ
redis:
image: redis:7-alpine
ports:
- "6379:6379"
# Nginx(リバースプロキシ)
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
volumes:
db-data:
# Docker Composeコマンド
# すべてのサービスを起動
docker-compose up -d
# ログを確認
docker-compose logs -f web
# 特定のサービスを再起動
docker-compose restart web
# サービスをスケーリング
docker-compose up -d --scale web=3
# すべてのサービスを停止して削除
docker-compose down
# ボリュームも削除
docker-compose down -v
実例:React + Node.js + MongoDB
# frontend/Dockerfile
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Nginxで静的ファイルを配信
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# backend/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 5000
CMD ["node", "server.js"]
# docker-compose.yml
version: '3.8'
services:
frontend:
build:
context: ./frontend
ports:
- "80:80"
depends_on:
- backend
backend:
build:
context: ./backend
ports:
- "5000:5000"
environment:
- MONGO_URL=mongodb://mongodb:27017/myapp
depends_on:
- mongodb
mongodb:
image: mongo:6
volumes:
- mongo-data:/data/db
ports:
- "27017:27017"
volumes:
mongo-data:
データボリュームの管理
# ボリュームを作成
docker volume create my-data
# ボリューム一覧
docker volume ls
# ボリュームをコンテナにマウント
docker run -v my-data:/app/data my-app
# ホストディレクトリをマウント(開発時に便利)
docker run -v $(pwd):/app my-app
# 読み取り専用でマウント
docker run -v $(pwd):/app:ro my-app
# ボリュームを削除
docker volume rm my-data
# 使用していないボリュームをすべて削除
docker volume prune
.dockerignoreファイル
# .dockerignore
# Git
.git
.gitignore
# Node
node_modules
npm-debug.log
# 環境設定
.env
.env.local
# ビルド出力
dist
build
# IDE
.vscode
.idea
# テスト
coverage
*.test.js
# ドキュメント
README.md
docs/
🤔 よくある質問
Q1. Docker vs 仮想マシン?
A:
仮想マシン (VM)
┌─────────────────┐ ┌─────────────────┐
│ App A │ │ App B │
│ Libs │ │ Libs │
│ Guest OS │ │ Guest OS │
│ (Linux) │ │ (Ubuntu) │
└─────────────────┘ └─────────────────┘
┌─────────────────────────────────────┐
│ Hypervisor (VMware等) │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Host OS │
└─────────────────────────────────────┘
Dockerコンテナ
┌───────┐ ┌───────┐ ┌───────┐
│ App A │ │ App B │ │ App C │
│ Libs │ │ Libs │ │ Libs │
└───────┘ └───────┘ └───────┘
┌─────────────────────────────┐
│ Docker Engine │
└─────────────────────────────┘
┌─────────────────────────────┐
│ Host OS (Linux Kernel) │
└─────────────────────────────┘
比較:
VM Docker
サイズ GB MB
起動 分 秒
隔離 完全 プロセスレベル
パフォーマンス オーバーヘッド大 ネイティブに近い
移植性 低い 高い
Q2. Dockerイメージレイヤーとは?
A:
FROM node:18 # レイヤー1: ベースイメージ
WORKDIR /app # レイヤー2: 作業ディレクトリ
COPY package.json . # レイヤー3: package.json
RUN npm install # レイヤー4: 依存関係のインストール
COPY . . # レイヤー5: ソースコード
CMD ["node", "app.js"]# レイヤー6: 起動コマンド
# レイヤーキャッシング
# - 変更されていないレイヤーは再利用
# - ビルド速度の向上
# ✅ 良い例: 頻繁に変更されるものを後に
COPY package.json .
RUN npm install # キャッシュされる(package.json変更なければ)
COPY . . # コード変更のみ
# ❌ 悪い例: 頻繁に変更されるものを先に
COPY . . # コード変更のたびに
RUN npm install # npm installが再実行!
Q3. コンテナオーケストレーションとは?
A:
単一サーバー
┌─────────────────────┐
│ ┌───┐ ┌───┐ ┌───┐ │
│ │C1 │ │C2 │ │C3 │ │
│ └───┘ └───┘ └───┘ │
└─────────────────────┘
オーケストレーション (Kubernetes)
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Server1 │ │ Server2 │ │ Server3 │
│ ┌───┐ │ │ ┌───┐ │ │ ┌───┐ │
│ │C1 │ │ │ │C2 │ │ │ │C3 │ │
│ └───┘ │ │ └───┘ │ │ └───┘ │
└─────────┘ └─────────┘ └─────────┘
機能:
- 自動デプロイ
- スケーリング(自動拡張/縮小)
- ロードバランシング
- 自動復旧(コンテナが死んだら再起動)
- ローリングアップデート
ツール:
- Kubernetes(最も人気)
- Docker Swarm
- Amazon ECS
Q4. 開発環境でのDocker活用は?
A:
# シナリオ: チームメンバーごとに異なる環境
# チームメンバーA: macOS、Node 16
# チームメンバーB: Windows、Node 18
# チームメンバーC: Linux、Node 14
# 問題: 「私のマシンでは動く...」
# 解決策: Dockerで環境を統一
# docker-compose.yml
version: '3.8'
services:
app:
image: node:18
volumes:
- .:/app
working_dir: /app
command: npm run dev
ports:
- "3000:3000"
# すべてのチームメンバーが同じ環境を使用
docker-compose up
# メリット:
# 1. Node.jsのインストール不要
# 2. バージョンの統一
# 3. 依存関係の分離
# 4. 環境設定の共有
Q5. Dockerのセキュリティは?
A:
# ✅ セキュリティのベストプラクティス
# 1. 最小権限のベースイメージ
FROM node:18-alpine # ✅ 小さく安全
FROM node:18 # ❌ 不要なツールが多い
# 2. rootユーザーでない実行
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs # ✅ 権限を最小化
# 3. 機密情報の除外
# .dockerignoreに追加
.env
*.key
secrets/
# 4. マルチステージビルド(不要なツールを削除)
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build
FROM node:18-alpine # 小さいイメージ
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]
# 5. イメージのスキャン
docker scan my-image
# 6. 読み取り専用のルートファイルシステム
docker run --read-only my-app
# 7. リソース制限
docker run --memory="512m" --cpus="1" my-app
🎓 次のステップ
Dockerを理解したら、次を学んでみましょう:
- Gitとは?(作成予定)- バージョン管理とデプロイ
- Node.jsとは?(作成予定)- DockerでNodeアプリをデプロイ
- TDDとは? - Dockerでテストを実行
試してみる
# 1. Dockerのインストールを確認
docker --version
# 2. Hello World
docker run hello-world
# 3. Nginxを実行
docker run -d -p 8080:80 nginx
# http://localhost:8080にアクセス
# 4. コンテナを確認
docker ps
# 5. 停止と削除
docker stop <container-id>
docker rm <container-id>
# 6. 自分のアプリをコンテナ化
# - Dockerfileを作成
# - docker build
# - docker run
便利なコマンド
# イメージ管理
docker pull nginx # イメージをダウンロード
docker images # イメージ一覧
docker rmi nginx # イメージを削除
# コンテナ管理
docker run # コンテナを実行
docker ps # 実行中のコンテナ
docker ps -a # すべてのコンテナ
docker stop <id> # コンテナを停止
docker start <id> # コンテナを起動
docker restart <id> # コンテナを再起動
docker rm <id> # コンテナを削除
# ログとデバッグ
docker logs <id> # ログを確認
docker logs -f <id> # リアルタイムログ
docker exec -it <id> sh # コンテナ内部にアクセス
docker inspect <id> # 詳細情報
# クリーンアップ
docker system prune # 未使用リソースを削除
docker system prune -a # すべての未使用リソース
docker volume prune # 未使用ボリュームを削除
🎬 まとめ
Dockerは現代の開発に不可欠なツールです:
- コンテナ: 隔離された実行環境
- イメージ: アプリケーションパッケージ
- 移植性: どこでも同じように実行
- 効率性: 軽量で高速
「私のマシンでは動く」問題をDockerで解決しましょう! 🐳✨