Docker はソフトウェアの構築、配布、実行の方法を変えました。「自分のマシンでは動く」の代わりに、Docker はアプリケーションがどこでも同じように動作することを保証します - あなたのノートパソコン、同僚のマシン、CI/CD、そして本番環境で。このガイドでは、ゼロから実際のアプリケーションのデプロイまでを解説します。
Docker とは?
Docker は、アプリケーションとそのすべての依存関係をコンテナと呼ばれる標準化されたユニットにパッケージングするプラットフォームです。コンテナは、ホスト OS のカーネルを共有しながらも、独自のファイルシステム、ネットワーク、プロセス空間を持つ、隔離された軽量なプロセスです。
コンテナ vs 仮想マシン
| 項目 | コンテナ | 仮想マシン |
|---|---|---|
| 起動 | 秒単位 | 分単位 |
| サイズ | MB 単位 | GB 単位 |
| OS | ホストカーネルを共有 | 完全なゲスト OS |
| 分離 | プロセスレベル | ハードウェアレベル |
| パフォーマンス | ほぼネイティブ | ハイパーバイザーのオーバーヘッド |
| 密度 | ホストあたり数百 | ホストあたり数十 |
Docker のインストール
# macOS brew install --cask docker # Ubuntu/Debian curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Verify installation docker --version docker run hello-world
コアコンセプト
イメージ
イメージは、コンテナを作成するための命令を含む読み取り専用のテンプレートです。アプリケーションとその環境のスナップショットと考えてください。
# Pull an image from Docker Hub docker pull node:20-alpine # List local images docker images # Remove an image docker rmi node:20-alpine
コンテナ
コンテナはイメージの実行中のインスタンスです。コンテナの作成、起動、停止、削除ができます。
# Run a container docker run -d --name my-app -p 3000:3000 node:20-alpine # List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-app # Remove a container docker rm my-app # View logs docker logs my-app # Execute a command inside a running container docker exec -it my-app sh
Dockerfile の書き方
Dockerfile は、イメージを構築するための命令が書かれたテキストファイルです。各命令がレイヤーを作成します。
Node.js アプリの基本的な Dockerfile
# Use an official Node.js runtime as base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (better caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Command to run the application CMD ["node", "server.js"]
ビルドと実行
# Build the image docker build -t my-node-app . # Run the container docker run -d -p 3000:3000 my-node-app # Visit http://localhost:3000
マルチステージビルド
マルチステージビルドは、ビルド環境をランタイムから分離することで、本番イメージを小さく保ちます。
# Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:20-alpine AS runner WORKDIR /app COPY /app/dist ./dist COPY /app/node_modules ./node_modules COPY /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/server.js"]
これにより、コンパイル済みの出力と本番依存関係のみを含むイメージが生成されます - ソースコード、開発依存関係、ビルドツールは含まれません。
Next.js のマルチステージ例
FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY /app/public ./public COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static EXPOSE 3000 CMD ["node", "server.js"]
ボリューム:永続データ
デフォルトでは、コンテナ内のデータはコンテナが削除されると失われます。ボリュームがこの問題を解決します。
# Create a named volume docker volume create my-data # Run with a volume docker run -d -v my-data:/app/data my-app # Bind mount (map host directory to container) docker run -d -v $(pwd)/data:/app/data my-app # List volumes docker volume ls
ネットワーキング
Docker は、コンテナが通信するための隔離されたネットワークを作成します。
# Create a custom network docker network create my-network # Run containers on the same network docker run -d --name api --network my-network my-api docker run -d --name db --network my-network postgres:16 # Containers can reach each other by name # From "api" container: postgres://db:5432
Docker Compose
Docker Compose を使えば、単一の YAML ファイルでマルチコンテナアプリケーションを定義して実行できます。
docker-compose.yml
services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" redis: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata:
コマンド
# Start all services docker compose up -d # View logs docker compose logs -f # Stop all services docker compose down # Rebuild and restart docker compose up -d --build # Scale a service docker compose up -d --scale api=3
.dockerignore
.gitignore と同様に、このファイルは不要なファイルがイメージにコピーされるのを防ぎます。
node_modules .git .env *.md .next dist coverage
本番環境のベストプラクティス
1. 小さなベースイメージを使う
# Bad: 1GB+ FROM node:20 # Good: ~180MB FROM node:20-alpine
2. Root で実行しない
FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /home/app COPY . .
3. 特定のイメージタグを使う
# Bad: can change unexpectedly FROM node:latest # Good: pinned version FROM node:20.11-alpine3.19
4. ビルドキャッシュを活用する
Dockerfile の命令を、変更頻度の低いものから高いものの順に並べましょう:
FROM node:20-alpine WORKDIR /app # These change rarely - cached COPY package.json package-lock.json ./ RUN npm ci --only=production # This changes often - not cached COPY . .
5. ヘルスチェック
HEALTHCHECK \ CMD wget -qO- http://localhost:3000/health || exit 1
6. 環境変数を使う
ENV NODE_ENV=production ENV PORT=3000
よく使う Docker コマンド早見表
# Images docker build -t name:tag . # Build image docker images # List images docker rmi image_name # Remove image docker image prune # Remove unused images # Containers docker run -d -p 3000:3000 image # Run detached docker ps # List running docker stop container_name # Stop docker rm container_name # Remove docker logs -f container_name # Follow logs docker exec -it container sh # Shell into container # Compose docker compose up -d # Start services docker compose down # Stop services docker compose logs -f # Follow all logs docker compose ps # List services # Cleanup docker system prune -a # Remove everything unused
Docker から Kubernetes へ
Docker は個々のコンテナを管理します。複数のサーバーにわたって数百のコンテナをオーケストレーションする必要がある場合、Kubernetes が必要です。Docker と Kubernetes は補完的な関係にあります:
- Docker:コンテナを構築して実行する
- Kubernetes:コンテナを大規模にオーケストレーションする(スケジューリング、スケーリング、自動修復)
次のステップに興味がある方は、Kubernetes 入門の記事をご覧ください。
まとめ
Docker は現代の開発者にとって基本的なスキルです。環境の不整合を解消し、デプロイを簡素化し、Kubernetes によるコンテナオーケストレーションの基盤となります。シンプルな Dockerfile から始めて、マルチサービスアプリには Docker Compose に移行し、成長に合わせてマルチステージビルドとセキュリティのベストプラクティスを導入しましょう。
Docker を学ぶ最良の方法は、すでに取り組んでいるプロジェクトをコンテナ化することです。今日から始めましょう。