← プログラミングページの先頭へ

Docker および Docker Compose

Docker は、アプリケーションとその実行環境をコンテナーにカプセル化し、環境の分離と一貫した展開を実現するために使用されます。

Docker Compose は、複数のコンテナで構成されるアプリケーションを定義および管理するために使用されます。

1. 中心となる概念

Dockerfile
    ↓ docker build
Image(鏡)
    ↓ docker run
Container(コンテナ)
コンセプト機能
Dockerfileイメージがどのように構築されるかを説明する
Imageアプリケーションと依存関係を含む読み取り専用のイメージ テンプレート
Container独立した書き込み可能なレイヤーを持つイメージの実行中のインスタンス
Volume永続データ
Networkコンテナ間通信
Registry画像保管・配信サービス
Docker Composeマルチコンテナアプリケーションを管理する

1 つのイメージで複数のコンテナを作成できます。デフォルトでは、コンテナーは独自の書き込み可能なファイル レイヤーを共有しません。

コンテナーを停止してもデータが消えるわけではありません。ただし、コンテナーが削除されると、通常、その書き込み可能なレイヤーも一緒に削除されるため、データベースには永続的なストレージが必要です。

2. イメージを構築する

docker build -t sorivel-backend:1.0.0 .

パラメータ:

パラメータ機能
-tイメージ名とTagを指定します
.Build Context、現在のディレクトリ
-f Dockerfile.prodDockerfileを指定してください
--build-arg KEY=valueビルドパラメータを渡す
--no-cache既存のビルド キャッシュを使用しないでください
--pull新しいベースイメージをプルしてみてください
--platform linux/amd64ターゲット プラットフォームを指定する
--target prodマルチステージビルドターゲットの指定

たとえば:

docker build \
  -f Dockerfile.prod \
  -t sorivel-backend:1.2.0 \
  --build-arg APP_VERSION=1.2.0 \
  .

Build Context

docker build . は、現在のディレクトリをビルド コンテキストとして使用します。

Dockerfile の COPY は通常、ビルド コンテキストで無視されないファイルのみを読み取ることができます。

たとえば:

COPY ./src /app/src

./src は Build Context に対して相対的ですが、必ずしも Dockerfile が配置されているディレクトリに対して相対的であるとは限りません。

.dockerignore

非常に推奨される構成:

.git
node_modules
.venv
__pycache__
.env
.env.*
dist
*.log

機能:

  • ビルドコンテキストを減らします。
  • より速く構築します。
  • 不要なキャッシュの無効化を減らします。
  • 機密ファイルが誤って画像に入るリスクを軽減します。

.dockerignore は安全なキー管理ツールと同等ではありません。Secrets は依然として適切に管理する必要があります。

3. コンテナを作成して実行する

docker run -d \
  --name myapp \
  -p 8000:8000 \
  --env-file .env \
  myapp:1.0
パラメータ機能
--nameコンテナ名
-p 8000:8000ホストポートからコンテナポートへのマッピング
-dバックグラウンドで実行中
--rm終了後にコンテナを自動的に削除する
-e環境変数を設定する
--env-file環境変数ファイルの読み込み
-vVolumeまたはBind Mountをマウント
--networkコンテナネットワークの指定
--restart戦略を再始動する

ポートマッピング

-p 8000:8000

形式:

Host Port : Container Port

ホストへのローカル アクセスのみが許可されている場合:

-p 127.0.0.1:8000:8000

すべてのホスト ネットワーク インターフェイスを直接バインドするよりも、パブリック アクセスを必要としない開発サービスに適しています。

起動コマンドをオーバーライドする

docker run --rm myapp:1.0 python manage.py shell

ここのコマンドはイメージの CMD を上書きします。イメージが ENTRYPOINT で構成されている場合、パラメーターの組み合わせの動作を一緒に考慮する必要があります。

4.Dockerfile共通命令

指示機能
FROMベースイメージを指定する
WORKDIR作業ディレクトリを指定する
COPYファイルをコピーする
ADD部分的なアーカイブとリモート リソースを処理するためのレプリケーションの強化
RUNイメージビルド時にコマンドを実行
CMDコンテナのデフォルトのコマンドまたはパラメータ
ENTRYPOINTコンテナデフォルトエントリープログラム
ENV環境変数を設定する
ARGビルドパラメータ
EXPOSEコンテナのリスニングポートを宣言する
USER実行ユーザーの指定
VOLUMEマウントディレクトリを宣言する
LABEL画像メタデータ
HEALTHCHECKコンテナのヘルスチェック
SHELLShell フォーム命令で使用されるデフォルトの Shell を変更します。
STOPSIGNALコンテナ停止信号を設定する

Dockerfile の例

FROM python:3.12-slim

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD [
  "gunicorn",
  "config.asgi:application",
  "-k",
  "uvicorn_worker.UvicornWorker",
  "--bind",
  "0.0.0.0:8000"
]

Gunicorn、Uvicorn、および対応する Worker パッケージを依存関係にインストールする必要があります。

CMD および ENTRYPOINT

ENTRYPOINT ["python"]
CMD ["manage.py", "runserver"]

デフォルトのコマンドを組み合わせたもの:

python manage.py runserver
  • ENTRYPOINT: メインプログラムを定義します。
  • CMD: デフォルトのコマンドまたはパラメータを提供します。

どちらも実行パラメータによってオーバーライドできますが、方法は異なります。

プロセス信号を正しく処理するには、通常、JSON 配列形式 (Exec Form) を使用することをお勧めします。

ARG および ENV

ARG APP_VERSION=dev
ENV APP_ENV=production

違い:

  • ARG: ビルドフェーズ中に使用され、デフォルトではコンテナ環境変数として保持されません。
  • ENV: ビルドフェーズとコンテナー実行フェーズの両方で使用でき、イメージ構成に残ります。

ビルド キーの保存に ARG または ENV を使用しないでください。

5. Docker Image LayersとBuild Cache

Docker イメージは複数のレイヤーで構成されており、BuildKit はビルド ステップの結果をキャッシュできます。

たとえば:

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

Python ビジネス コードのみが変更され、依存関係ファイルが変更されない場合、Docker は通常、以前にインストールされた依存関係のビルド キャッシュを再利用できます。

そして:

COPY . .
RUN pip install -r requirements.txt

コードを変更すると、インストール手順に依存するキャッシュが無効化されやすくなる可能性があります。

キャッシュ最適化の原則

まず、変更頻度の低い依存関係記述ファイルをコピーし、次に依存関係をインストールし、最後にビジネス コードをコピーします。

BuildKit Cache Mount

ビルド キャッシュはパッケージ マネージャーに提供できます。

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

この方法では、Pip ダウンロード キャッシュを再利用できますが、これはキャッシュ ディレクトリを最終イメージに永続的に書き込むことを意味しません。

6.多段構造(Multi-stage Build)

マルチステージ ビルドは、ビルドの依存関係を最終的なランタイム環境から分離するために使用されます。

典型的な React + Vite:

FROM node:24-alpine AS builder

WORKDIR /app

RUN corepack enable

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

FROM nginx:alpine

COPY --from=builder /app/dist /usr/share/nginx/html
Node Builder
    ↓
pnpm build
    ↓
dist/
    ↓ COPY --from
Nginx Image

最終イメージには、Node.js プロジェクトのすべてのビルド依存関係が含まれている必要はありません。

COPY --chown

COPY --chown=appuser:appuser . /app

ファイルのコピー時に所有者を設定できるため、Root 以外のユーザーが実行するコンテナに適しています。

7. VolumeとBind Mount

Named Volume

Docker によって管理されるデータ ボリューム:

docker volume create postgres_data

マウント:

docker run \
  -v postgres_data:/var/lib/postgresql/data \
  postgres:17

ここのパスは PostgreSQL 17 公式イメージです。

Volume は、通常のコンテナの削除では自動的に削除されず、データベースの永続化に適しています。

Bind Mount

ホスト ディレクトリをコンテナにマウントします。

docker run \
  -v ./src:/app/src \
  myapp:1.0
Host ./src
    ↕
Container /app/src

ローカル開発および構成ファイルのマウントに適しています。

違い

種類マネージャー代表的な用途
Named VolumeDockerPostgreSQLデータ
Bind Mountホストファイルシステムソースコード、設定ファイル
tmpfs記憶一時的な機密データまたは高頻度データ

注: 運用環境では、ソース コード ディレクトリ全体を任意に Bind Mount から /app に変更しないでください。変更すると、イメージの構築中に書き込まれたファイルが上書きされる可能性があります。

8. Docker Network

コンテナは Docker ネットワーク経由で通信できます。

Docker Compose はデフォルトでプロジェクトのネットワークを作成し、同じネットワーク内のコンテナーはサービス名を通じて相互にアクセスできます。

たとえば:

backend
  ↓ db:5432
PostgreSQL

backend
  ↓ redis:6379
Redis

Django データベース構成では通常、次のものが使用されます。

DB_HOST=db
DB_PORT=5432

代わりに:

DB_HOST=localhost

コンテナーでは、localhost は通常、コンテナー自体を指すためです。

ports および expose

ports:
  - "8000:8000"

ホストマシンに公開します。

expose:
  - "8000"

コンテナーのポートを宣言しますが、ホストには公開しません。

同じ Compose ネットワーク上のサービス通信の場合、通常は expose を記述せずに、コンテナが実際にリッスンしているポートに直接アクセスできます。

9. Docker Compose

Compose は、1 つの YAML ファイルで複数のサービスを定義します。

たとえば:

services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: prod
      args:
        APP_VERSION: "1.2.0"
    image: sorivel-backend:1.2.0
    command: >
      gunicorn config.asgi:application
      -k uvicorn_worker.UvicornWorker
      --bind 0.0.0.0:8000
    env_file:
      - ./backend/.env
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - backend_network
      - frontend_network

  db:
    image: postgres:17
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Password required}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 20s
    networks:
      - backend_network

  redis:
    image: redis:7
    networks:
      - backend_network

volumes:
  postgres_data:

networks:
  backend_network:
  frontend_network:

以下に構造例を示します。実際のプロジェクトでは、必要に応じて Nginx、静的リソース、Redis 永続性、およびキー管理を構成する必要もあります。

重要な分野

フィールド機能
servicesサービスを定義する
imageイメージ名を指定してください
buildビルド方法を指定する
commandカバー Dockerfile CMD
entrypointカバー Dockerfile ENTRYPOINT
environmentコンテナ環境変数を挿入する
env_fileファイルからコンテナ環境変数を挿入する
portsホストポートの公開
volumesマウントの構成
depends_on依存関係の起動シーケンスと条件を定義する
healthcheckヘルスチェックを定義する
restartコンテナの再起動戦略
networksコンテナネットワークの指定

depends_on

depends_on:
  db:
    condition: service_healthy

Backend を開始する前に、DB の Health Check が通過するのを待っていることを示します。

ただし、アプリケーションのランタイム全体を通じてデータベースが利用できることが自動的に保証されるわけではありません。 Django は、データベース接続の失敗と再接続を適切に処理する必要があります。

10. Environment Variables

ここでは 2 つのメカニズムを区別する必要があります。

Compose 補間変数

environment:
  APP_PORT: ${APP_PORT:-8000}

Compose は、Shell、項目 .env などの変数を解析します。

その中には:

  • ${APP_PORT:-8000}: 未設定または空の場合は 8000 が使用されます。
  • ${VAR:?Required}: 設定されていないか、空の場合はエラーが報告されます。

env_file

env_file:
  - ./backend/.env

ファイルから Backend コンテナに変数を挿入します。

重要な違い

Compose .env
    ↓
Compose 設定変数の補間

services.backend.env_file
    ↓
Backend コンテナ環境変数

この 2 つは同じものではありません。

environment と env_file の両方に同じ名前の変数が指定されている場合、明示的な environment が優先されます。

以下を確認できます。

docker compose config

ただし、このコマンドは解析された機密情報を出力する可能性があるため、完全な結果をログに送信したり、公的に共有したりしないでください。

11. コンテナのライフサイクル

Created
   ↓
Running
   ↓
Stopped / Exited
   ↓
Removed

コンテナのメインプロセスが終了すると、通常はコンテナも終了します。

たとえば:

CMD ["gunicorn", "..."]

Gunicorn がメインプロセスです。それが終了すると、コンテナは終了します。

Restart Policy

restart: unless-stopped

コンテナーが終了した後、手動で停止されていない限り、Docker が対応するポリシーに従って再起動を試みることを示します。

Health Check 障害後にコンテナーが自動的に再起動するという保証はありません。

PID 1 と信号

コンテナが停止すると、通常、メイン プロセスに終了シグナルが送信され、一定時間待機します。

したがって、次のことが推奨されます。

  • Exec Formを使用してアプリケーションを起動します。
  • アプリが正常な終了をサポートしていることを確認してください。
  • 不要な Shell が終了信号をブロックしないようにしてください。
  • 必要に応じて、init: true を使用して子プロセスのリサイクルを処理します。

12. Docker Compose 共通コマンド

ステータスとログ

docker compose ps

docker compose logs

docker compose logs -f backend

docker stats

開始と停止

# 始める
docker compose up -d

# 停止しますがコンテナは保持します
docker compose stop

# サービスコンテナとネットワークを停止および削除する
docker compose down

# 同時削除 Compose 経営関連 Volume
docker compose down -v

本番データベースが存在する Named Volume は、任意に down -v を実行しないでください。

ビルドとアップデート

# ビルドのみ Backend 鏡
docker compose build backend

# ビルドキャッシュを使用しない
docker compose build --no-cache backend

# 構築して開始する
docker compose up -d --build

# アップデートのみ Backend サービス
docker compose up -d --build backend

# コンテナの再構築を強制する
docker compose up -d --force-recreate backend

Dockerfile またはイメージ内のソース コードを変更する場合は、開始する前に新しいイメージをビルドする必要があります。

env_file を通じて挿入された環境変数のみを変更する場合は、コンテナーを再作成できます。

docker compose up -d --force-recreate backend

Compose 構成を変更する場合:

docker compose up -d

通常、構成変更は識別され、必要に応じて対応するサービスが再作成されます。

コンテナに入る

docker compose exec backend sh

docker compose exec backend python manage.py shell

docker compose exec backend python manage.py migrate

すべてのコンテナー イメージ (特に Alpine またはシン イメージ) に Bash が含まれているわけではないため、通常は sh の方が汎用性が高くなります。

exec および run

docker compose exec backend python manage.py shell

既存の実行中のコンテナーでコマンドを実行します。

docker compose run --rm backend python manage.py shell

コマンドを実行するための新しい一時サービス コンテナを作成します。

後者は 1 回限りの管理タスクに適していますが、ネットワーク、ポート、ライフサイクルの動作は exec とまったく同じではありません。

13. 鏡倉庫(Registry)

一般的なミラー ウェアハウス:

  • Docker Hub。
  • GitHub Container Registry(GHCR)。
  • AWS ECR。

画像名の例:

ghcr.io/username/sorivel-backend:1.0.0

ビルドしてプッシュします。

docker build \
  -t ghcr.io/username/sorivel-backend:1.0.0 \
  .

docker push ghcr.io/username/sorivel-backend:1.0.0

プル:

docker pull ghcr.io/username/sorivel-backend:1.0.0

マルチアーキテクチャビルド

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t ghcr.io/username/sorivel-backend:1.0.0 \
  --push \
  .

複数の CPU アーキテクチャに対応するイメージをビルドしてプッシュできます。

ターゲット プラットフォームのビルドをサポートする Buildx Builder を使用し、必要に応じて QEMU などのメカニズムを通じてクロスアーキテクチャ ビルドを実行する必要があります。

14. Health Check

Dockerfile:

HEALTHCHECK --interval=30s --timeout=5s \
  CMD python -c \
  "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"

Compose で定義することもできます。

healthcheck:
  test:
    - CMD
    - python
    - -c
    - "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"
  interval: 30s
  timeout: 5s
  retries: 3

Health Check は、サービスが正常に応答できるかどうかを判断するために使用されます。

共通ステータス:

starting
healthy
unhealthy

注: コンテナーは Running ステータスですが、これはアプリケーションが Healthy でなければならないという意味ではありません。

15. Secrets とセキュリティ

パスワードを Dockerfile に直接書き込んだり、Git ウェアハウスに送信したりしないでください。

特に次のことは避けてください。

ARG DATABASE_PASSWORD=secret
ENV DATABASE_PASSWORD=secret

ビルドフェーズ中にプライベートリソースにアクセスする必要がある場合は、BuildKit Secret Mount を使用できます。

たとえば:

RUN --mount=type=secret,id=pip_token \
    ...

ランタイム キーの場合は、展開プラットフォームの Secret 管理機能を使用するか、適切なアクセス許可で保護された構成ファイルを介して注入できます。

その他の提案:

  • Root 以外のユーザーとしてアプリケーションを実行してみてください。
  • PostgreSQL や Redis などの内部サービス ポートはパブリック ネットワークに公開されません。
  • 無条件に latest に依存するのではなく、明示的なイメージ バージョンを使用してください。
  • 基本イメージを定期的に更新します。
  • PostgreSQL Volume の独立したバックアップ メカニズムを確立します。

16. データベースの操作とバックアップ

Migration を実行します。

docker compose exec backend python manage.py migrate

Volume を表示:

docker volume ls

PostgreSQL エクスポート

docker compose exec -T db \
  pg_dump -U app -d app > backup.sql

PostgreSQLインポート

docker compose exec -T db \
  psql -U app -d app < backup.sql

ここでは、Compose サービス名が db、データベースとユーザーが両方とも app であると仮定します。

インポートを実行する前に、対象のデータベースの状態とバックアップ形式を確認する必要があります。 SQL インポートは、安全で完全なデータベース移行プロセスとは異なります。

Volume は Backup と等しくありません

Volume は永続化を担当しますが、以下を防ぐことはできません。

  • 誤ってデータを削除してしまいました。
  • データベースのロジックが破損しています。
  • ディスク障害。
  • エラーMigration。
  • ホストマシンが失われてしまいました。

運用データベースは引き続き定期的にバックアップし、回復手順を検証する必要があります。

17. クリーンアップコマンド

# 画像を見る
docker images

# コンテナを表示する
docker ps -a

# 見る Volume
docker volume ls

# 指定した画像を削除
docker rmi image_name

# クリーン ビルド キャッシュは使用されなくなりました
docker builder prune

# 未使用のビルド キャッシュをすべて削除します
docker builder prune -a

開発環境を完全にリセットします。

docker compose down -v --rmi all --remove-orphans
docker compose up -d --build

この操作は破壊的であり、特に -v は、Compose が管理する関連する Volume を削除します。本番データを含む環境では直接実行しないでください。

概要

Docker の中心的な内容は、次の 5 つの部分に分けることができます。

分類知っておくべきこと
ベースモデルDockerfile、Image、Container
構築するBuild Context、Cache、Multi-stage、Buildx
動作環境ENV、ARG、CMD、ENTRYPOINT、Health Check
インフラストラクチャVolume、Bind Mount、Network、Ports
運用・保守Docker Compose、Logs、Exec、Backup、Registry

日常的な展開の一般的なプロセス:

Write Dockerfile
        ↓
docker compose build
        ↓
Docker Images
        ↓
docker compose up -d
        ↓
Running Containers
        ↓
Health Check / Logs
        ↓
Application

最も重要な実践的な原則:

  1. イメージはアプリケーションのパッケージ化を担当し、コンテナーはアプリケーションの実行を担当します。
  2. データベース データは永続化し、バックアップする必要があります。
  3. 運用環境のデプロイでは、ソース コード ディレクトリ全体を直接マウントしないようにしてください。
  4. Docker Network とサービス名を介したコンテナ間通信。
  5. 画像コンテンツを変更するには、コンテナーの再構築と更新が必要です。
  6. 機密情報をイメージやリポジトリに書き込まないでください。

参考資料