Docker入門
コンテナ技術でアプリの実行環境を統一しよう
Dockerとは?
Dockerは、アプリケーションとその実行環境をまとめてコンテナという軽量な仮想環境にパッケージ化するツールです。 「自分のPCでは動くのに、サーバーでは動かない」という問題を解決します。
コンテナにはOS、ランタイム、ライブラリ、アプリケーションコードがすべて含まれているため、 どの環境でも全く同じように動作します。開発・テスト・本番で一貫した環境が保証されます。
環境の統一
開発・テスト・本番で同一環境を保証
軽量・高速
VMと違いOS全体を仮想化しないため起動が速い
移植性
どのマシンでも同じコンテナが動作する
コンテナと仮想マシンの違い
コンテナと仮想マシン(VM)はどちらもアプリケーションを隔離して実行しますが、 その仕組みは大きく異なります。
仮想マシン(VM) コンテナ(Docker)
┌─────────────────┐ ┌─────────────────┐
│ アプリA │ アプリB │ │ アプリA │ アプリB │
│─────────│────────│ │─────────│────────│
│ ゲストOS│ ゲストOS│ │ ランタイム│ランタイム│
│─────────│────────│ │─────────────────│
│ ハイパーバイザ │ │ Dockerエンジン │
│─────────────────│ │─────────────────│
│ ホストOS │ │ ホストOS │
└─────────────────┘ └─────────────────┘
VM: 各アプリにOS全体が必要(数GB、起動に分単位)
コンテナ: ホストOSのカーネルを共有(数MB〜、起動は秒単位)| 比較項目 | 仮想マシン | コンテナ |
|---|---|---|
| 起動時間 | 数分 | 数秒 |
| サイズ | 数GB〜 | 数MB〜数百MB |
| リソース効率 | 低い | 高い |
| 分離レベル | 完全(OS単位) | プロセス単位 |
Dockerfile
Dockerfileは、Dockerイメージの設計図です。 ベースイメージの選択、ファイルのコピー、依存関係のインストール、起動コマンドなどを記述します。
# Next.jsアプリのDockerfile例
# ステージ1: 依存関係のインストール
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ステージ2: ビルド
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# ステージ3: 本番イメージ
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# セキュリティ:non-rootユーザーで実行
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
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
ENV PORT=3000
CMD ["node", "server.js"]マルチステージビルドを使うことで、ビルドに必要なツールを最終イメージに含めず、 軽量な本番イメージを作成できます。上の例では最終イメージにはビルド成果物だけが含まれます。
docker build と docker run
Dockerfileからイメージを作成し、そのイメージからコンテナを起動する基本的なコマンドを学びましょう。
# イメージをビルド(-t でタグ名を指定)
docker build -t my-nextjs-app .
# イメージ一覧を確認
docker images
# コンテナを起動
# -d: バックグラウンド実行
# -p: ポートマッピング(ホスト:コンテナ)
docker run -d -p 3000:3000 --name my-app my-nextjs-app
# 実行中のコンテナを確認
docker ps
# コンテナのログを表示
docker logs my-app
docker logs -f my-app # リアルタイムで追跡
# コンテナに入る(デバッグ用)
docker exec -it my-app sh
# コンテナを停止・削除
docker stop my-app
docker rm my-app
# イメージを削除
docker rmi my-nextjs-app.dockerignoreファイルを作成して、 不要なファイル(node_modules、.git など)がイメージに含まれないようにしましょう。
# .dockerignore
node_modules
.next
.git
.gitignore
*.md
.env.localDocker Compose
Docker Composeは、複数のコンテナをまとめて管理するツールです。 Webアプリ + データベース + キャッシュなど、複数のサービスを一括で起動・停止できます。
# docker-compose.yml
version: "3.8"
services:
# Next.jsアプリ
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
depends_on:
- db
volumes:
- .:/app
- /app/node_modules
# 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
# Redis(キャッシュ)
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:# Docker Compose コマンド
docker compose up # 全サービスを起動
docker compose up -d # バックグラウンドで起動
docker compose down # 全サービスを停止・削除
docker compose logs # ログを表示
docker compose ps # 稼働中のサービスを確認
docker compose exec app sh # appコンテナに入るボリュームとネットワーク
ボリュームはコンテナのデータを永続化する仕組みです。 コンテナを削除してもデータベースのデータは保持されます。ネットワークはコンテナ間の通信を管理します。
# ボリュームの種類
# 1. 名前付きボリューム(Dockerが管理、データの永続化に使う)
volumes:
postgres_data:
# 2. バインドマウント(ホストのディレクトリをコンテナに接続)
volumes:
- ./src:/app/src # 開発時のホットリロード用
# ボリューム管理コマンド
docker volume ls # ボリューム一覧
docker volume inspect db_data # 詳細確認
docker volume rm db_data # 削除# ネットワーク
# Docker Composeは自動的にネットワークを作成し、
# サービス名で他のコンテナにアクセスできる
# 例: appコンテナからdbコンテナに接続
DATABASE_URL=postgresql://postgres:password@db:5432/myapp
# ^^
# サービス名がホスト名になる
# カスタムネットワークの定義
networks:
frontend:
backend:
services:
app:
networks:
- frontend
- backend
db:
networks:
- backend # dbはbackendネットワークのみまとめ
- Dockerはアプリと実行環境をコンテナにパッケージ化し、どこでも同じ動作を保証する
- コンテナはVMより軽量で高速に起動でき、リソース効率が高い
- Dockerfileでイメージの設計図を定義し、マルチステージビルドで軽量化する
- docker build でイメージ作成、docker run でコンテナ起動
- Docker Composeで複数コンテナ(アプリ+DB+キャッシュ等)を一括管理する
- ボリュームでデータ永続化、ネットワークでコンテナ間通信を制御する