<CodeLearn/>
デプロイ レッスン2

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.local

Docker 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+キャッシュ等)を一括管理する
  • ボリュームでデータ永続化、ネットワークでコンテナ間通信を制御する