目次

この記事の内容

コンテナ技術は、現代のアプリケーション開発・運用に欠かせないインフラとなりました。本記事では、コンテナの基本概念から Docker の実践的活用までを解説します。

コンテナ技術とは何か

従来の仮想化との比較

【従来型仮想化(ハイパーバイザー)】
┌─────────────────────────────────┐
│        仮想マシン 1             │
│  アプリ │ ライブラリ │ ゲスト OS │
├─────────────────────────────────┤
│        仮想マシン 2             │
│  アプリ │ ライブラリ │ ゲスト OS │
├─────────────────────────────────┤
│      ハイパーバイザー            │
├─────────────────────────────────┤
│        ホスト OS                │
├─────────────────────────────────┤
│        ハードウェア             │
└─────────────────────────────────┘

【コンテナ型仮想化】
┌─────────────────────────────────┐
│    コンテナ 1  │    コンテナ 2   │
│ アプリ│libs  │ アプリ│libs   │
├─────────────────────────────────┤
│      コンテナエンジン           │
├─────────────────────────────────┤
│        ホスト OS                │
├─────────────────────────────────┤
│        ハードウェア             │
└─────────────────────────────────┘

仮想マシン vs コンテナ

特徴仮想マシンコンテナ
起動時間数分数秒
サイズGB 単位MB 単位
オーバーヘッド大きい(フル OS)小さい(カーネル共有)
隔離性高い(完全分離)中程度(プロセスレベル)
移植性やや劣る高い(イメージ共通)
使用例完全なサーバー環境マイクロサービス、CI/CD

コンテナのメリット

  1. 軽量・高速: カーネルを共有するため、リソース効率がよい
  2. 環境の一貫性: 「開発では動いたが、本番で動かない」を解消
  3. スケーラビリティ: 数秒で数百インスタンス起動可能
  4. マイクロサービスとの相性: 1 サービス =1 コンテナで管理

コンテナのデメリット

  1. セキュリティ: カーネルを共有するため、完全隔離ではない
  2. Windows 対応: Linux カーネルベースのため、Windows では制限
  3. 永続ストレージ: コンテナ破棄時にデータが消失(ボリュームで対応)

Docker の基本アーキテクチャ

主要コンポーネント

┌─────────────────────────────────────────────┐
│              Docker Client                  │
│              (docker コマンド)               │
└─────────────────┬───────────────────────────┘
                  │ API
┌─────────────────▼───────────────────────────┐
│              Docker Daemon                  │
│              (dockerd)                      │
└─────────┬──────────────┬────────────────────┘
          │              │
┌─────────▼──────┐  ┌───▼────────────────────┐
│    Images      │  │   Containers           │
│  (設計図)     │  │   (実行インスタンス)  │
└────────────────┘  └────────────────────────┘

用語解説

用語説明例え
イメージコンテナの設計図(読み取り専用)クッキーの型
コンテナイメージの実行インスタンス焼き上がったクッキー
Dockerfileイメージ構築手順書レシピ
レジストリイメージ共有サービスアプリストア
Docker HubDocker 公式レジストリApp Store / Google Play

Docker のインストールとセットアップ

インストール(主要 OS)

# Ubuntu
sudo apt-get update
sudo apt-get install docker.io docker-compose

# macOS (Homebrew)
brew install --cask docker

# Windows
# Docker Desktop をダウンロード
# https://www.docker.com/products/docker-desktop

動作確認

# バージョン確認
docker --version
docker compose version

# _hello world_ コンテナを実行
docker run hello-world

Docker の基本コマンド

コンテナ操作

# コンテナ起動(バックグラウンド)
docker run -d -p 8080:80 --name my-app nginx

# 実行中コンテナ一覧
docker ps

# 全コンテナ一覧(停止含む)
docker ps -a

# コンテナ停止
docker stop my-app

# コンテナ起動(停止済み)
docker start my-app

# コンテナ削除
docker rm my-app

# 強制削除(実行中でも)
docker rm -f my-app

イメージ操作

# イメージ一覧
docker images

# イメージダウンロード
docker pull nginx:latest

# イメージ削除
docker rmi nginx:latest

# 使用されていないイメージをクリーンアップ
docker image prune -a

ログ・実行中操作

# ログ表示
docker logs my-app

# リアルタイムログ
docker logs -f my-app

# コンテナ内コマンド実行
docker exec -it my-app bash

# リソース使用状況
docker stats

Dockerfile の書き方

基本構文

# ベースイメージ
FROM ubuntu:22.04

# メンテナ情報
LABEL maintainer="taro@example.com"

# 環境変数
ENV APP_HOME=/app
ENV NODE_ENV=production

# 作業ディレクトリ
WORKDIR $APP_HOME

# 依存関係インストール
RUN apt-get update && apt-get install -y \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

# アプリケーションコピー
COPY package*.json ./
RUN npm ci --only=production

COPY . .

# ポート公開
EXPOSE 3000

# 起動コマンド
CMD ["node", "server.js"]

主要命令

命令説明実行時期
FROMベースイメージ指定-
RUNシェルコマンド実行ビルド時
COPYファイルコピービルド時
ADDファイルコピー+展開・URL 対応ビルド時
WORKDIR作業ディレクトリ設定-
ENV環境変数設定-
EXPOSE公開ポート宣言-
CMDデフォルトコマンド実行時
ENTRYPOINT実行コマンド(上書き不可)実行時

CMD vs ENTRYPOINT

# CMD: 引数で上書き可能
CMD ["node", "server.js"]
# 実行時: docker run my-app node other.js で上書き可能

# ENTRYPOINT: コマンド固定、引数追加のみ
ENTRYPOINT ["node"]
CMD ["server.js"]
# 実行時: docker run my-app other.js → node other.js

実践的 Dockerfile 例

Node.js アプリケーション

# 本番環境用
FROM node:18-alpine

WORKDIR /app

# 依存関係インストール(キャッシュ活用)
COPY package*.json ./
RUN npm ci --only=production

# アプリケーションコピー
COPY . .

# 非 root ユーザー作成(セキュリティ)
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

USER nodejs

EXPOSE 3000

CMD ["node", "dist/server.js"]

Python アプリケーション

FROM python:3.11-slim

WORKDIR /app

# 依存関係インストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# 非 root ユーザー
RUN useradd -m -u 1001 appuser && chown -R appuser /app
USER appuser

EXPOSE 8000

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Go アプリケーション(マルチステージビルド)

# ビルドステージ
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server

# 実行ステージ(最小イメージ)
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/
COPY --from=builder /app/server .

EXPOSE 8080
CMD ["./server"]

マルチステージビルド

概要

1 つの Dockerfile で複数のビルドステージを定義。ビルド環境と実行環境を分離し、最終イメージを小型化できます。

# ステージ 1: ビルド
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build

# ステージ 2: 本番
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80

メリット:

  • ビルドツールが含まれない(小型化)
  • セキュリティ向上(攻撃対象領域減少)
  • ビルド段階のキャッシュを分離可能

Docker Compose

概要

複数のコンテナを定義・管理するためのツールです。

docker-compose.yml 例

version: '3.8'

services:
  # Web アプリケーション
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:pass@db:5432/myapp
    depends_on:
      - db
    volumes:
      - ./app:/app
      - /app/node_modules
    restart: unless-stopped

  # データベース
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

  # 認証・認可(オプション)
  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  postgres_data:

主要コマンド

# 全サービス起動(バックグラウンド)
docker compose up -d

# 起動 + ビルド
docker compose up -d --build

# サービス停止
docker compose down

# ログ表示
docker compose logs -f

# 特定サービスのみ起動
docker compose up -d web

# サービス再起動
docker compose restart web

# コンテナ内に入る
docker compose exec web bash

ボリュームとデータ永続化

ボリュームの種類

種類説明使用例
ボリュームDocker 管理の永続領域データベースデータ
バインドマウントホストディレクトリ直接マウント開発環境のコード
tmpfsメモリ上マウント(永続化なし)機密データ、キャッシュ

使用例

services:
  db:
    image: postgres:15
    volumes:
      # 名前付きボリューム(推奨)
      - db_data:/var/lib/postgresql/data

      # バインドマウント(開発用)
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

  web:
    build: .
    volumes:
      # 開発:ホストコードをマウント
      - ./src:/app/src
      # node_modules はコンテナ内を使用
      - /app/node_modules

volumes:
  db_data:

ネットワーク

ネットワークドライバー

ドライバー用途
bridgeデフォルト。同一ホスト内コンテナ間通信
hostホストネットワーク直接利用(性能重視)
overlay複数ホスト間通信(Swarm)
noneネットワーク無効

カスタムネットワーク

services:
  web:
    build: .
    networks:
      - frontend
      - backend

  api:
    build: ./api
    networks:
      - backend

  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
  backend:
    internal: true  # 外部からアクセス不可

Docker レジストリ

Docker Hub の利用

# ログイン
docker login

# イメージタグ付け
docker tag my-app:latest username/my-app:1.0.0

# プッシュ
docker push username/my-app:1.0.0

# プル
docker pull username/my-app:1.0.0

プライベートレジストリ(自前運用)

# docker-compose.yml
version: '3.8'
services:
  registry:
    image: registry:2
    ports:
      - "5000:5000"
    volumes:
      - registry_data:/var/lib/registry
    environment:
      - REGISTRY_STORAGE_DELETE_ENABLED=true

volumes:
  registry_data:

セキュリティベストプラクティス

1. 最小権限の原則

# ❌ root で実行
FROM node:18
USER root

# ✅ 非 root ユーザー
FROM node:18
RUN adduser -S appuser
USER appuser

2. 公式イメージの使用

# ❌ 不明なベース
FROM random-user/custom-image

# ✅ 公式イメージ
FROM node:18-alpine
FROM python:3.11-slim

3. 依存関係の固定

# ❌ 最新版(予測不能)
FROM node:latest

# ✅ バージョン固定
FROM node:18.17.0-alpine

4. 機密情報の排除

# ❌ Dockerfile に埋め込み
ENV API_KEY=secret123

# ✅ ビルド時引数(イメージに残らない)
ARG API_KEY
RUN echo $API_KEY > /tmp/config

# ✅ 実行時環境変数
# docker run -e API_KEY=secret123

5. 脆弱性スキャン

# Docker Scout(公式)
docker scout cve my-app:latest

# Trivy(サードパーティ)
trivy image my-app:latest

トラブルシューティング

よくあるエラー

1. ポートがバインドできない

Error: Bind for 0.0.0.0:80 failed: port is already allocated

解決:

# 使用ポート確認
lsof -i :80

# または別ポート使用
docker run -p 8080:80 nginx

2. 容量不足

Error: no space left on device

解決:

# 不要なコンテナ・イメージ削除
docker system prune -a

# ボリューム確認
docker system df

3. コンテナが即終了

# ログ確認
docker logs <container-id>

# インタラクティブにデバッグ
docker run -it --entrypoint bash my-app

本番環境での運用

ヘルスチェック

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

ログ収集

services:
  web:
    build: .
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

リスタートポリシー

services:
  web:
    build: .
    restart: unless-stopped  # 手動停止まで自動再起動
    # または
    # restart: on-failure:5  # 失敗時最大 5 回

まとめ

Docker の核心概念:

  1. コンテナ: 軽量・高速・移植性の高い仮想化技術
  2. イメージ: 読み取り専用の設計図
  3. Dockerfile: イメージ構築手順書
  4. Compose: 複数コンテナの管理ツール
  5. セキュリティ: 非 root ユーザー、公式イメージ、脆弱性スキャン

「コンテナは現代のデファクトスタンダード」

基礎を固め、実践で使い込むことが習得への近道です。


参考資料

免責事項 — 掲載情報は執筆時点のものです。料金・機能は変更される場合があります。最新情報は各公式サイトをご確認ください。