Docker: アプリケーションのコンテナか
最終更新:2026-08-26
フェーズ 2 のちしきをくみあわせ、ソースコードからほんばんむけイメージまで、Web アプリケーションをかんぜんにコンテナかします。
1. まなべること
- いくつかのフェーズにわけたハンズオンプロジェクト
- かんきょうせっていのかんりポリシー
- ログをえいぞくかするほうほう
- ヘルスチェックとじこしゅうふくのせってい
- イメージタグとバージョンかんり
2. レガシープロジェクトをひきついだはなし
(1) こまりごと: Docker でうごかないレガシープロジェクト
Alice がひきついだ Python プロジェクトは、Dockerfile が 1.2 GB のイメージをつくり、ビルドに 10 ぷんかかっていました。ヘルスチェックはなく、ログはコンテナないにかかれてさいきどうでうしなわれ、root でうごき、かんきょうへんすうもハードコードされていました。デプロイには 30 ぷんかかり、あんていしません。
(2) かんぜんなコンテナかによるかいけつ
Bob はいぞんかんけいをしらべ、マルチステージ Dockerfile、ログえいぞくか、ヘルスチェック、root ではないユーザーでのじっこうをせっていしました。そのけっか、ビルドとデプロイは 3 ぷんみまんになりました。
DOCKERFILE
# ほんばんむけマルチステージ Dockerfile
FROM python:3.12-slim AS builder
# ... さいてきかした venv をビルド
FROM python:3.12-slim
# ... venv をコピーし、root ではないユーザーとヘルスチェックをせってい
(3) こうか: 30 ぷんから 3 ぷんへ
| しひょう | さいてきかまえ | さいてきかご |
|---|---|---|
| イメージサイズ | 1.2 GB | 150 MB |
| ビルドじかん | 10 ぷん | 3 ぷん |
| デプロイじかん | 30 ぷん | 3 ぷん |
| セキュリティスコア | 45 | 85 |
3. プロジェクトアーキテクチャ
(1) アプリケーションのこうせい
このレッスンでは Flask + PostgreSQL + Nginx の Todo リストアプリケーションをコンテナかします。
graph TB
USER["ブラウザー"] --> NGX["Nginx<br/>リバースプロキシ + スタティックファイル"]
NGX -->|"proxy_pass :5000"| APP["Flask アプリ<br/>Todo API + UI"]
APP -->|"psycopg2 :5432"| DB["PostgreSQL<br/>Todo データベース"]
DB --> VOL["なまえつきボリューム<br/>pg-data"]
APP --> LOGS["なまえつきボリューム<br/>app-logs"]
(2) コンテナかのほうしん
| コンポーネント | ベースイメージ | ポリシー |
|---|---|---|
| Flask アプリ | python:3.12-slim |
マルチステージ + root ではないユーザー + HEALTHCHECK |
| PostgreSQL | postgres:15-alpine |
オフィシャルイメージ + なまえつきボリューム |
| Nginx | nginx:1.25-alpine |
オフィシャルイメージ + せっていファイルのバインドマウント |
4. Flask アプリの Dockerfile
(1) プロジェクトこうせい
TEXT
📖 参照専用
todo-app/
├── app.py # Flask アプリケーション
├── requirements.txt # Python のいぞんかんけい
├── templates/ # HTML テンプレート
│ └── index.html
├── Dockerfile # ほんばんむけマルチステージビルド
├── .dockerignore # いらないファイルをのぞく
├── nginx.conf # Nginx リバースプロキシせってい
└── docker-run.sh # ワンクリックデプロイスクリプト
▶ サンプル: マルチステージ Dockerfile をかく (むずかしさ: ⭐⭐⭐)
DOCKERFILE
# ============================================
# Flask Todo アプリのマルチステージ Dockerfile
# ステージ 1: かそうかんきょうをビルド
# ステージ 2: ほんばんランタイム
# ============================================
# ---------- ステージ 1: ビルダー ----------
FROM python:3.12-slim AS builder
WORKDIR /build
# キャッシュ: いぞんかんけいをさきにインストール
COPY requirements.txt .
RUN python -m venv /opt/venv && \
/opt/venv/bin/pip install --no-cache-dir -r requirements.txt
# ---------- ステージ 2: ほんばん ----------
FROM python:3.12-slim
# ヘルスチェックように curl をインストール
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# root ではないユーザーをさくせい
RUN groupadd -r appgroup && \
useradd -r -g appgroup -u 1000 -m -d /home/appuser appuser
WORKDIR /app
# ビルダーからかそうかんきょうをコピー
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
# アプリケーションコードをコピー
COPY --chown=appuser:appgroup . .
# ログディレクトリをさくせい
RUN mkdir -p /app/logs && chown appuser:appgroup /app/logs
# root ではないユーザーへきりかえ
USER appuser
# かんきょうへんすうはじっこうじにうわがきできる
ENV FLASK_ENV=production \
LOG_LEVEL=info \
APP_PORT=5000
EXPOSE 5000
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD curl -f http://localhost:5000/health || exit 1
# アプリケーションをかいし
CMD ["python", "app.py"]
(2) .dockerignore
TEXT
📖 参照専用
# .dockerignore
__pycache__
*.pyc
*.pyo
.git
.env
venv
.venv
*.md
Dockerfile
docker-compose*.yml
5. かんきょうせっていのかんり
(1) かんきょうへんすうのゆうせんじゅんい
| レベル | ほうほう | ゆうせんど | むいているばめん |
|---|---|---|---|
| Dockerfile ENV | デフォルトち | ひくい (1) | きょうつうのデフォルト |
| docker run -e | じっこうじのうわがき | ふつう (2) | デプロイせってい |
| .env ファイル | --env-file |
たかい (3) | たくさんのへんすう |
| Docker Secrets | --secret |
もっともたかい | センシティブなじょうほう |
▶ サンプル: かんきょうへんすうをせっていする (むずかしさ: ⭐⭐)
BASH
# カスタムかんきょうへんすうでじっこう
docker run -d \
--name todo-app \
-e FLASK_ENV=production \
-e DATABASE_URL="postgresql://appuser:apppass@todo-db:5432/tododb" \
-e LOG_LEVEL=warning \
-p 5000:5000 \
todo-app:1.0
▶ サンプル: .env ファイルをつかう (むずかしさ: ⭐⭐)
BASH
# .env ファイルをさくせい
cat > .env << 'EOF'
FLASK_ENV=production
DATABASE_URL=postgresql://appuser:apppass@todo-db:5432/tododb
LOG_LEVEL=warning
APP_PORT=5000
EOF
# --env-file でじっこう
docker run -d \
--name todo-app \
--env-file .env \
-p 5000:5000 \
todo-app:1.0
6. ログのえいぞくか
▶ サンプル: ログをえいぞくかする (むずかしさ: ⭐⭐)
BASH
# アプリログようになまえつきボリュームをマウント
docker run -d \
--name todo-app \
-v app-logs:/app/logs \
-e LOG_LEVEL=info \
todo-app:1.0
(1) ログポリシーのくらべかた
| ほうほう | メリット | デメリット |
|---|---|---|
| コンテナないのログファイル | かんたん | コンテナさくじょでうしなわれる |
| ボリュームえいぞくか | コンテナさくじょごものこる | ローテーションをてさぎょうでかんり |
| stdout + log driver | Docker ひょうじゅんのかんり | せっていがふくざつ |
| しゅうやくログ (ELK/Loki) | すべてをけんさくできる | ついかのインフラがひつよう |
7. イメージタグとバージョンかんり
(1) タグのつけかた
| ほうしん | タグのかたち | サンプル | むいているばめん |
|---|---|---|---|
| セマンティックバージョン | vMajor.Minor.Patch |
v2.1.0 |
ほんばんリリース |
| Git SHA | sha-<commit> |
sha-a1b2c3d |
CI/CD のトレース |
| latest | latest |
latest |
かいはつやクイックスタート |
| ブランチめい | <branch> |
main, dev |
かいはつかんきょう |
▶ サンプル: ふくすうタグをプッシュする (むずかしさ: ⭐⭐)
BASH
# ふくすうのタグでビルド
docker build -t todo-app:v1.0.0 -t todo-app:latest .
# すべてのタグをプッシュ
docker push localhost:5000/todo-app:v1.0.0
docker push localhost:5000/todo-app:latest
8. フルスタックのデプロイ
▶ サンプル: Flask + PostgreSQL + Nginx をまとめてデプロイ (むずかしさ: ⭐⭐⭐)
BASH
# ============================================
# ワンクリックデプロイスクリプト
# ============================================
# 1. ネットワークとボリュームをさくせい
docker network create todo-net
docker volume create pg-data
docker volume create app-logs
# 2. PostgreSQL をかいし
docker run -d \
--name todo-db \
--network todo-net \
-e POSTGRES_USER=appuser \
-e POSTGRES_PASSWORD=apppass \
-e POSTGRES_DB=tododb \
-v pg-data:/var/lib/mysql \
--restart=unless-stopped \
postgres:15-alpine
# 3. PostgreSQL のしょきかをまつ
sleep 15
# 4. Flask アプリをビルドしてかいし
docker build -t todo-app:1.0 ./todo-app
docker run -d \
--name todo-app \
--network todo-net \
-e DATABASE_URL="postgresql://appuser:apppass@todo-db:5432/tododb" \
-v app-logs:/app/logs \
--restart=unless-stopped \
todo-app:1.0
# 5. Nginx リバースプロキシをかいし
docker run -d \
--name todo-nginx \
--network todo-net \
-p 80:80 \
-v $(pwd)/todo-app/nginx.conf:/etc/nginx/conf.d/default.conf \
--restart=unless-stopped \
nginx:1.25-alpine
# 6. かくにん
docker ps
curl http://localhost/health
9. けんしょうとさいてきかのけっか
(1) dive でさいてきかをけんしょう
BASH
# マルチステージイメージをぶんせき
dive todo-app:1.0
# きたいち: こうりつスコア > 90%、むだなスペースなし
(2) イメージサイズのくらべかた
| バージョン | Dockerfile | イメージサイズ | ビルドじかん |
|---|---|---|---|
| V1 シングルステージ | FROM python:3.12 + COPY . . + RUN pip install |
1.2 GB | 5 ふん |
| V2 さいてきかしたベース | FROM python:3.12-slim + キャッシュクリア |
350 MB | 3 ぷん |
| V3 マルチステージ | builder + slim + root ではないユーザー + HEALTHCHECK | 150 MB | 3 ぷん (キャッシュヒットなら 30 びょう) |
10. かんぜんなサンプル: Todo リストアプリのコンテナか
BASH
# ============================================
# Flask アプリをコンテナかするながれ
# Dockerfile、ビルド、マルチコンテナデプロイ
# ============================================
# 1. さいてきかイメージをビルド
docker build -t todo-app:v1.0.0 -t todo-app:latest ./todo-app
# 2. イメージをかくにん
docker images todo-app
docker history todo-app:v1.0.0
# 3. インフラをさくせい
docker network create todo-net
docker volume create pg-data
docker volume create app-logs
# 4. えいぞくストレージつき PostgreSQL をかいし
docker run -d \
--name todo-db \
--network todo-net \
-e POSTGRES_USER=appuser \
-e POSTGRES_PASSWORD=apppass \
-e POSTGRES_DB=tododb \
-v pg-data:/var/lib/postgresql/data \
--restart=unless-stopped \
postgres:15-alpine
# 5. Flask アプリをかいし
docker run -d \
--name todo-app \
--network todo-net \
-e DATABASE_URL="postgresql://appuser:apppass@todo-db:5432/tododb" \
-v app-logs:/app/logs \
--restart=unless-stopped \
todo-app:v1.0.0
# 6. Nginx リバースプロキシをかいし
docker run -d \
--name todo-nginx \
--network todo-net \
-p 8080:80 \
-v $(pwd)/todo-app/nginx.conf:/etc/nginx/conf.d/default.conf \
--restart=unless-stopped \
nginx:1.25-alpine
# 7. フルスタックをかくにん
echo "=== Containers ===" && docker ps
echo "=== Health Check ===" && docker inspect todo-app --format='{{.State.Health.Status}}'
echo "=== App Response ===" && curl -s http://localhost:8080/health
# 8. プライベートレジストリへプッシュ
docker tag todo-app:v1.0.0 localhost:5000/todo-app:v1.0.0
docker push localhost:5000/todo-app:v1.0.0
# 9. クリーンアップ
# docker stop todo-nginx todo-app todo-db
# docker rm todo-nginx todo-app todo-db
❓ よくある質問
Q ひとつのコンテナではひとつのプロセスだけをうごかしますか?
A Flask、Nginx、PostgreSQL をべつべつのコンテナにする「1 コンテナ、1 プロセス」がおすすめです。こべつにスケールやこうしんができ、しょうがいもきりはなせます。
Q ログはコンテナないとボリュームのどちらへかきますか?
A アプリから stdout とファイルのりょうほうへだし、ファイルはボリュームへほぞんできます。ほんばんでは stdout と ELK/Loki などのしゅうやくログをくみあわせるほうほうがおすすめです。
Q ビルドでかいはつとほんばんをわけるにはどうしますか?
A Dockerfile.dev と Dockerfile.prod をわけるか、マルチステージビルドと
--target をつかいます。ENV にデフォルトをおき、docker run -e でうわがきするほうほうもあります。Q イメージのバージョンはどうかんりしますか?
A SemVer の
v2.1.0 と、トレースようの Git SHA タグをつかいます。latest はさいしんのあんていばんをしめせますが、ほんばんではせいかくなバージョンをしていしてください。Q コンテナのタイムゾーンはどうせっていしますか?
A
docker run -e TZ=Asia/Tokyo をつかうか、-v /etc/localtime:/etc/localtime:ro でホストのタイムゾーンをつかいます。Alpine では TZ に tzdata がひつようです。📖 まとめ
- マルチステージビルドでは builder で venv をつくり、runner へ venv だけをコピーして 1.2 GB から 150 MB へさくげんする
- かんきょうへんすうは Dockerfile ENV、
docker run -e、.env のじゅんでうわがきする /app/logsへなまえつきボリュームをマウントし、さいきどうやさいビルドのあともログをのこす/healthをヘルスチェックし、さいきどうポリシーでじこしゅうふくする- SemVer、Git SHA、
latestのふくすうタグをつかう - root ではないユーザー、HEALTHCHECK、ログえいぞくかはほんばんむけ Dockerfile のたいせつなようそ
📝 練習問題
- きほん (むずかしさ: ⭐): オープンソースの Flask または Express プロジェクトへ Dockerfile をかき、イメージをビルドしてじっこうしてください。
- おうよう (むずかしさ: ⭐⭐): マルチステージ Dockerfile をかき、シングルステージとのイメージサイズをくらべてください。
- ちょうせん (むずかしさ: ⭐⭐⭐):
diveでさいてきかずみイメージをしらべ、さらにさくげんできるレイヤーをみつけてなおし、サイズのへんかをたしかめてください。