Docker で Nginx 構築完全ガイド:設定ファイルのマウント、HTTPS 設定、リバースプロキシ実践
7 回目の docker restart nginx、ブラウザを更新しても——502 エラーのまま。nginx.conf は書き換えたのに、コンテナ内の設定がどうしても反映されない。
Docker で Nginx を動かすときの設定問題は、コンテナ化に取り組む人なら誰もが一度は踏むポイントです。設定ファイルのマウント、HTTPS 証明書、コンテナ間通信——一見シンプルな操作にも、実は細かな落とし穴が潜んでいます。本記事では、設定ファイルの正しいマウント方法から、HTTPS 証明書の自動更新、リバースプロキシのネットワーク設定まで、すぐ使える Docker Nginx の構成案をまとめます。
本記事で学べること:
- 設定ファイルが反映されない原因と、5 つの正しいマウント方法
- 自己署名証明書から Let’s Encrypt までの HTTPS 構築手順
- 他の Docker コンテナをリバースプロキシするときのネットワーク設定
- 本番環境向けのセキュリティ強化とパフォーマンスチューニング
Docker Nginx の基本設定とファイルマウント
なぜ設定ファイルをマウントするのか
Nginx の設定をイメージに焼き込めばいいのでは?——技術的には可能ですが、運用がつらくなります。
設定を 1 行変えるたびにイメージを再ビルドし、レジストリへプッシュし、pull してコンテナを再起動——この一連の作業だけで十数分は消えます。設定のバージョン管理や、環境ごとの切り替えも面倒です。深夜 2 時に本番障害が起き、設定をすぐロールバックしたいのに、イメージビルドを待つ羽目になる——想像するだけで胃が痛くなります。
設定ファイルをマウントする理由はここにあります。ホスト側のファイルを編集すれば、コンテナ内にすぐ反映される。テスト、ロールバック、チーム開発がすべて楽になります。
Nginx コンテナの主要ディレクトリ構造
まず、Nginx がコンテナ内のどこに何を置いているかを押さえましょう。
/etc/nginx/
├── nginx.conf # メイン設定ファイル
├── conf.d/ # サイトごとの設定ディレクトリ
│ └── default.conf # デフォルトサイト設定
/usr/share/nginx/html # 静的ファイルのルート
/var/log/nginx/ # ログディレクトリ
├── access.log
└── error.log
重要なのは、nginx.conf に include /etc/nginx/conf.d/*.conf; という行があることです。メイン設定が conf.d 以下の .conf を自動読み込みします。nginx.conf だけマウントして conf.d を忘れる——最初の落とし穴はここです。
正しいマウント手順:ステップバイステップ
いきなりコンテナを起動しないでください。先に準備を済ませると、後のトラブルが大幅に減ります。
ステップ 1:コンテナのデフォルト設定をテンプレートとしてコピー
なぜこうするか?公式のデフォルト設定は検証済みで、ゼロから書くより安全だからです。
# 一時コンテナを起動
docker run --name nginx-temp -d nginx
# デフォルト設定をコピー
docker cp nginx-temp:/etc/nginx/nginx.conf ./nginx/nginx.conf
docker cp nginx-temp:/etc/nginx/conf.d ./nginx/conf.d
# 使い終わったら削除
docker stop nginx-temp && docker rm nginx-temp
ステップ 2:ホスト側に標準ディレクトリ構造を作成
私は Docker 関連ファイルを /opt 以下にまとめる習慣があります。好みに合わせて調整してください。
mkdir -p /opt/nginx/{conf,conf.d,html,logs,ssl}
設定、静的ファイル、ログ、SSL 証明書——必要なものが一度に揃います。
ステップ 3:コンテナを起動し、すべてのディレクトリをマウント
ここが本番です。各 -v のパスマッピングに注目してください。
docker run -d --name my-nginx \
-p 80:80 -p 443:443 \
-v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /opt/nginx/conf.d:/etc/nginx/conf.d \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/logs:/var/log/nginx \
-v /opt/nginx/ssl:/etc/nginx/ssl \
nginx
ポイント:
-p 80:80 -p 443:443:HTTP と HTTPS の両ポートを公開(後で HTTPS を設定するため)nginx.confには:ro(読み取り専用)を付け、コンテナ内プロセスによる誤変更を防ぐconf.dはディレクトリごとマウント(単一ファイルではなく。理由は後述)
よく踏む 4 つの落とし穴
落とし穴 1:vim で編集するとコンテナ内に同期されない
私が最初にハマったパターンです。ホスト側の nginx.conf を編集してコンテナを再起動しても、反映されません。
原因:vim は保存時にファイルの inode を変えます。Docker のマウントは inode で紐づいているため、inode が変わるとコンテナ内は古いファイルのままになります。
対処法は 2 つ:
- 案 A:nano など inode を変えないエディタを使う
- 案 B:単一ファイルではなくディレクトリごとマウントする
今は案 B 一択です。ディレクトリマウントなら inode がどう変わっても追従し、設定ファイルの追加・削除も柔軟にできます。
落とし穴 2:include パスの設定ミス
コンテナ内で nginx.conf を確認しましょう。
docker exec -it my-nginx bash
cat /etc/nginx/nginx.conf | grep include
次の行があることを確認してください。
include /etc/nginx/conf.d/*.conf;
/opt/nginx/conf.d/*.conf(ホスト側パス)に書き換えてしまうと誤りです。コンテナ内ではコンテナ内のパスだけが有効です。
落とし穴 3:conf.d ディレクトリのマウント忘れ
nginx.conf だけマウントしても不十分です。ホスト側 conf.d に新しいサイト設定を追加しても、コンテナからは見えません。
確認方法:
docker exec my-nginx ls /etc/nginx/conf.d
ホスト側 /opt/nginx/conf.d のファイルがすべて表示されるはずです。
落とし穴 4:ファイル権限で Nginx が設定を読めない
Linux では起きやすい問題です。設定ファイルの権限が厳しすぎると、Nginx プロセス(通常 nginx ユーザー)が読み取れません。
対処:
chmod 644 /opt/nginx/conf/nginx.conf
chmod 644 /opt/nginx/conf.d/*.conf
設定変更後は、構文チェックを習慣にしましょう。
docker exec my-nginx nginx -t
syntax is ok と出れば安心です。
単一ファイルマウント vs ディレクトリマウント:どちらを選ぶ?
よく聞かれる質問です。私のおすすめは次のとおり。
メイン設定 nginx.conf:単一ファイル + 読み取り専用(:ro)で十分。頻繁には触らないから
conf.d ディレクトリ:必ずディレクトリマウント。サイト設定を柔軟に追加できる
html、logs:ディレクトリマウント。言うまでもなく
覚えておく原則:複数ファイルを柔軟に管理するならディレクトリマウント。コア設定をバージョン管理したいなら単一ファイル + 読み取り専用保護。
HTTPS 設定と Let’s Encrypt 自動更新
自己署名証明書:開発環境での素早い検証
本番では正規の証明書が必要ですが、開発・テストなら自己署名で十分。数コマンドで済みます。
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/nginx/ssl/nginx.key \
-out /opt/nginx/ssl/nginx.crt \
-subj "/C=JP/ST=Tokyo/L=Tokyo/O=Dev/CN=localhost"
このコマンドで 2 つのファイルが生成されます。
nginx.key:秘密鍵。絶対に漏らさないnginx.crt:証明書ファイル
次に /opt/nginx/conf.d/ に ssl.conf を作成します。
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
ポイント:
ssl_certificateのパスはコンテナ内(/etc/nginx/ssl)。ホスト側の/opt/nginx/sslではないssl_protocolsは TLS 1.2 と 1.3 のみ。古いプロトコルには既知の脆弱性がある- 起動時に
-p 443:443を忘れずに。HTTPS ポートを公開しないとアクセスできない
設定をホットリロード:
docker exec my-nginx nginx -s reload
https://localhost にアクセスすると、ブラウザが証明書を信頼しないと警告を出します——正常な挙動です。自己署名証明書はそういうもの。「詳細設定から続行」で問題ありません。
Let’s Encrypt:本番環境の無料証明書
Let’s Encrypt は本当に便利です。無料、自動化、世界中で信頼される。唯一の「欠点」は 90 日で期限切れになること——自動更新を組めば気にしなくてよい。
ここでは docker-compose + certbot コンテナの構成を推奨します。手作業よりずっと確実です。
まず完全な docker-compose.yml を見てみましょう。
version: '3'
services:
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
networks:
- web
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
- web
networks:
web:
driver: bridge
重要なポイント:
1. 証明書と検証ファイルの共有マウント
./certbot/confを 2 つのコンテナにマウント。certbot が証明書を生成し、nginx が読み込む./certbot/wwwは Let’s Encrypt の HTTP 検証(webroot 方式)用
2. Nginx が 6 時間ごとに自動 reload
この command は複雑に見えますが、バックグラウンドで 6 時間ごとに reload するループを起動しているだけです。証明書更新後すぐ反映されます。
3. Certbot が 12 時間ごとに更新をチェック
Let’s Encrypt は 1 日 1 回のチェックを推奨していますが、12 時間にするとより安心です。
初回証明書取得の手順
HTTP 検証用に /opt/nginx/conf.d/ に一時設定 temp.conf を作成します。
server {
listen 80;
server_name your-domain.com; # 自分のドメインに変更
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
サービスを起動:
docker-compose up -d
証明書を申請(your-domain.com と [email protected] を自分の値に置き換え):
docker-compose run --rm certbot certonly --webroot \
-w /var/www/certbot \
-d your-domain.com \
--email [email protected] \
--agree-tos \
--no-eff-email
順調なら “Congratulations!” と表示されます。証明書は ./certbot/conf/live/your-domain.com/ にあります。
本番用 HTTPS 設定に更新します。temp.conf を次の内容に書き換えます。
server {
listen 80;
server_name your-domain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# SSL 最適化設定
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# HSTS(HTTPS 強制)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
設定を reload:
docker-compose exec nginx nginx -s reload
自動更新の検証
Let’s Encrypt 証明書は 90 日有効ですが、certbot は残り 30 日で自動更新します。手動でテストできます。
docker-compose run --rm certbot renew --dry-run
“The dry run was successful” と出れば OK です。
cron ログで更新タスクの動作も確認できます。
docker-compose logs certbot
HTTPS 設定のセキュリティ強化
SSL 設定をより安全にするなら、次も追加できます。
# OCSP Stapling(オンライン証明書ステータス確認)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/your-domain.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# iframe 埋め込み禁止(クリックジャッキング対策)
add_header X-Frame-Options DENY;
# XSS 対策
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
設定後、SSL Labs で SSL 設定のスコアを確認できます。A+ も十分狙えます。
リバースプロキシと Docker コンテナ間通信
コンテナネットワークの基本
Nginx で他の Docker コンテナをプロキシするとき、いちばん面倒なのがネットワーク設定です。コンテナ IP を直接指定して、再起動のたびに IP が変わる——設定の書き直し地獄、経験ある人も多いでしょう。
Docker にはいくつかネットワークモードがありますが、よく使うのは次の 2 つ:
- bridge(ブリッジ):デフォルト。仮想ブリッジ経由でコンテナ間通信
- host:ホストのネットワークスタックを直接使用。性能は良いが隔離性は低い
Nginx リバースプロキシでは、カスタム bridge ネットワークを強く推奨します。理由は:
- コンテナ間でサービス名をそのまま使える。IP 変化を気にしなくてよい
- ネットワークで隔離。プロジェクトごとに独立した通信環境
- 自動 DNS 解決。Docker 組み込みのサービスディスカバリ
カスタムネットワークの作成とコンテナ起動
まずカスタムネットワークを作成:
docker network create my-app-network
バックエンドサービス(Node.js API と仮定)を起動:
docker run -d \
--name backend-api \
--network my-app-network \
-e NODE_ENV=production \
my-backend:latest
Nginx も同じネットワークに接続:
docker run -d \
--name my-nginx \
--network my-app-network \
-p 80:80 -p 443:443 \
-v /opt/nginx/conf.d:/etc/nginx/conf.d \
nginx
ポイント:2 つのコンテナが同じネットワークにいれば、Nginx 設定で backend-api という名前でバックエンドにアクセスできます。
Nginx リバースプロキシ設定の実践
/opt/nginx/conf.d/ に api-proxy.conf を作成します。
upstream backend {
server backend-api:3000; # コンテナ名:ポート
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
# API プロキシ
location /api/ {
proxy_pass http://backend/;
# クライアント情報を転送
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket 対応(必要な場合)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# タイムアウト設定
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 静的ファイルは Nginx が直接配信
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
見落としがちな細部:
1. upstream と proxy_pass のパス処理
proxy_pass http://backend/; の末尾にスラッシュがあります。/api/users は http://backend/users に転送され(/api プレフィックスが除去される)。
proxy_pass http://backend;(スラッシュなし)だと http://backend/api/users に転送され(パス全体が保持される)。
2. X-Forwarded-For ヘッダーの重要性
バックエンドが実クライアント IP を取得するにはこのヘッダーが必要です。設定しないと、バックエンドから見えるのは Nginx コンテナの IP だけになります。
3. keepalive コネクションプール
upstream の keepalive 32 で TCP 接続を再利用し、ハンドシェイクのオーバーヘッドを削減できます。高並行シナリオで効果的です。
docker-compose で複数コンテナをまとめて管理
ネットワークを手動作成し、コンテナを 1 つずつ起動するのは面倒です。docker-compose なら一発です。
version: '3.8'
services:
backend:
image: my-backend:latest
container_name: backend-api
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/mydb
networks:
- app-network
depends_on:
- db
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
- ./nginx/logs:/var/log/nginx
networks:
- app-network
depends_on:
- backend
db:
image: postgres:14
container_name: postgres-db
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
db-data:
1 コマンドでスタック全体を起動:
docker-compose up -d
Docker が自動的に:
app-networkという名前のネットワークを作成depends_onの順序でコンテナを起動- コンテナ間 DNS 解決を設定
Nginx 設定では backend や db をホスト名としてそのまま使えます。とても楽です。
よくあるプロキシ問題の切り分け手順
問題 1:502 Bad Gateway
最も多いエラー。原因はだいたい次のいずれか:
- バックエンドが起動していない、または落ちている
- Nginx とバックエンドが同じネットワークにいない
- バックエンドの待ち受けポートが違う
切り分け手順:
# バックエンドの稼働確認
docker ps | grep backend
# ネットワーク接続の確認
docker network inspect my-app-network
# Nginx コンテナから疎通テスト
docker exec -it my-nginx sh
ping backend-api
curl http://backend-api:3000/health
ping が通らなければネットワーク設定の問題。curl がタイムアウトならバックエンドの待ち受け設定を疑います。
問題 2:リクエストタイムアウト
デフォルトの proxy タイムアウトは 60 秒。大ファイルアップロードや重い処理など、API の処理時間が長い場合は延長が必要です。
location /api/long-running/ {
proxy_pass http://backend/;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
問題 3:POST リクエストボディが失われる
POST が GET になったり、ボディが空になることがあります。次の設定を確認してください。
location /api/ {
proxy_pass http://backend/;
proxy_request_buffering off; # リクエストバッファリングを無効化
client_max_body_size 100M; # 大きなファイルアップロードを許可
}
複数バックエンドのロードバランシング
バックエンドが複数インスタンスなら、Nginx でロードバランシングできます。
upstream backend_cluster {
least_conn; # 最少接続アルゴリズム
server backend-1:3000 weight=3; # 重み 3
server backend-2:3000 weight=1; # 重み 1
server backend-3:3000 backup; # スタンバイサーバー
keepalive 32;
}
server {
listen 80;
location /api/ {
proxy_pass http://backend_cluster/;
# ... その他の proxy 設定
}
}
ロードバランシングアルゴリズム:
round-robin(デフォルト):ラウンドロビンleast_conn:接続数が最も少ないサーバーを優先ip_hash:同一クライアント IP を常に同じサーバーへ
バックエンドが 1 台落ちても、Nginx は自動的に健全なノードへトラフィックを振り分けます。
本番環境のベストプラクティスとパフォーマンス最適化
設定ファイル管理:そのまま本番に置かない
設定ファイルをサーバーに直置きするのは開発環境のやり方。本番ではもう一段、きちんと管理しましょう。
Git で設定を管理
私は Nginx 設定専用のリポジトリを作り、環境ごとにディレクトリを分けています。メリットは明確:
- 変更履歴が一目瞭然。ロールバックは
git checkoutだけ - チーム開発がしやすい。PR で設定変更をレビューできる
- CI/CD と連携し、自動デプロイも可能
設定のテンプレート化
環境ごとに設定はほぼ同じで、差分はごく少数。テンプレート + 変数置換が効きます。デプロイ時に envsubst で変数を置き換えれば OK です。
ログ管理:ディスクが満杯になる前に
Nginx のログは書き込みが速い。高トラフィックサイトなら 1 日数 GB も珍しくありません。放置すると、ある日ディスクが満杯になってコンテナが停止します。
ログローテーション設定
ホスト側で logrotate を設定し、毎日ローテーション、14 日保持、古いログは自動圧縮。ローテーション後は Nginx にログファイルを開き直させる(nginx -s reopen)必要があります。しないと古いファイルに書き続けます。
集中ログの構成
サーバーが複数台なら、ログを集中管理基盤(ELK、Loki、クラウドサービス)へ送るのも手です。Docker ログドライバーや Promtail なら導入も簡単です。
グレースフル reload:ユーザーに気づかせない
設定変更後、docker restart は避けてください。再起動はすべての接続を切断し、処理中のリクエストも失われます。
正しい手順:
# まず構文チェック
docker exec my-nginx nginx -t
# 問題なければ reload
docker exec my-nginx nginx -s reload
reload はグレースフルリロード。新しい worker が新設定を読み込み、古い worker は処理中リクエストを完了してから終了——切り替え中もユーザーは気づきません。
セキュリティ強化チェックリスト
本番公開前に、次を確認してください。
1. Nginx バージョン番号を隠す
デフォルトではエラーページに Nginx バージョンが表示されます。既知の脆弱性を狙った攻撃に使われ得ます。http ブロックに server_tokens off; を追加して非表示に。
2. レート制限で DDoS 対策
シンプルで効果的な防御:
http {
# IP ごとのリクエスト頻度制限
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 同時接続数制限
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_conn conn_limit 10;
proxy_pass http://backend/;
}
}
3. 設定ファイルは読み取り専用マウント
メイン設定に :ro を付け、コンテナ内プロセスによる誤変更を防ぐ。
4. 最小権限の原則
nginx.conf に user nginx; があることを確認。root に変更するとセキュリティリスクが大幅に上がります。
パフォーマンスチューニング:Nginx の性能を引き出す
worker プロセス数の最適化
worker_processes auto; # CPU コア数に自動合わせ
worker_cpu_affinity auto; # CPU アフィニティを設定
auto は手間いらず。Nginx が CPU コア数を自動検出します。
接続数の最適化
events {
worker_connections 2048; # worker あたりの最大接続数
use epoll; # Linux では epoll が最も高速
}
理論上の最大同時接続:worker_processes * worker_connections。ただしファイルディスクリプタ上限(ulimit -n)も考慮が必要です。
gzip 圧縮
テキストコンテンツを圧縮すると転送量を 60〜80% 削減できます。
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # 圧縮レベル 1〜9、6 が性能と圧縮率のバランス点
gzip_types
text/plain
text/css
text/xml
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
gzip_min_length 1000; # 1KB 未満は圧縮しない(CPU の無駄)
}
静的リソースのキャッシュ
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d; # ブラウザキャッシュ 30 日
add_header Cache-Control "public, immutable";
}
HTTP/2 対応
HTTP/2 は性能を大きく向上させます。有効化も簡単:
server {
listen 443 ssl http2; # http2 を追加するだけ
# ... その他の設定
}
前提は HTTPS であること。HTTP/2 は TLS 上で動作します。
モニタリングとヘルスチェック
最後にモニタリングを忘れずに。Prometheus + Grafana と nginx-prometheus-exporter の組み合わせがおすすめです。Nginx 設定で stub_status を有効化し、Docker 内部ネットワークからのみアクセス可能に制限。Prometheus で metrics を取得し、Grafana でダッシュボードを表示します。
まとめ
ここまでの要点を 4 つに整理します。
設定ファイルのマウント:単一ファイルよりディレクトリマウント。メイン設定は読み取り専用で保護。conf.d と ssl ディレクトリを忘れない。vim の inode 問題にも注意。
HTTPS 設定:開発は自己署名で素早く検証、本番は Let’s Encrypt + Certbot で自動化。docker-compose なら更新もほぼお任せ。
リバースプロキシ:カスタム bridge ネットワークが基本。コンテナ名で通信すれば IP 変更を気にしなくてよい。upstream に keepalive を足せば性能と信頼性が向上。
本番運用:Git で設定をバージョン管理、ログローテーションを忘れず、restart ではなく graceful reload。必要なセキュリティ対策は漏れなく。
Docker Nginx はシンプルに見えて細部が多い。ここまで押さえれば、開発から本番まで安定した Web サービス構成を組み立てられます。
本記事でいくつかの落とし穴を避けられたり、長く悩んでいた問題が解けたなら、執筆の甲斐がありました。ぜひ手を動かしてみてください。困ったことがあれば、コメントで気軽にどうぞ。
最後のアドバイス:本記事の設定テンプレートを保存しておき、次回から再利用しましょう。同じ車輪を何度も作る必要はありません。
Docker で Nginx を構築する完全フロー
設定ファイルのマウント、HTTPS 設定、リバースプロキシの実践。設定が反映されない問題やコンテナ間通信のトラブルを解決
⏱️ 目安時間: 1 時間
- 1
ステップ1: 設定ファイルのマウント:5 つの正しい方法
5 つの正しいマウント方法:
• 設定ファイルをマウント:-v ./nginx.conf:/etc/nginx/nginx.conf
• 設定ディレクトリをマウント:-v ./conf.d:/etc/nginx/conf.d
• Volume を使う
• docker-compose で設定
• ConfigMap(K8s 環境)
よくある問題:
• 設定を変更しても反映されない。nginx.conf を書き換えたのにコンテナ内が古いまま
• -v で設定ディレクトリを正しくマウントする
• 設定ファイルの形式が正しいか確認
ベストプラクティス:
• 単一ファイルよりディレクトリマウント
• メイン設定は読み取り専用で保護
• conf.d と ssl ディレクトリを忘れない
• vim の inode 問題に注意 - 2
ステップ2: HTTPS 設定と Let's Encrypt 自動更新
HTTPS 設定:
• Let's Encrypt の無料証明書を使う
• 自動更新:certbot renew
• 証明書ディレクトリをマウント:-v ./certs:/etc/nginx/certs
• SSL 証明書パスを設定
• HTTP/2 と TLS 1.3 に対応
Let's Encrypt 設定:
• certbot で証明書取得:certbot certonly --standalone
• 自動更新のテスト:certbot renew --dry-run
• 証明書をコンテナにマウント:-v ./letsencrypt:/etc/letsencrypt
• nginx.conf で証明書を参照 - 3
ステップ3: リバースプロキシ設定と本番環境のベストプラクティス
リバースプロキシ設定:
• upstream でバックエンドコンテナを指定
• コンテナ名やサービス名を使う:proxy_pass http://backend:8080
• ヘルスチェックを設定
• CORS 問題への対処
• ロードバランシング
本番環境のベストプラクティス:
• docker-compose で複数コンテナを管理
• ヘルスチェックを設定
• リソース制限を設定
• ログローテーション
• 環境変数で設定を管理
• イメージを定期的に更新
Docker Nginx はシンプルに見えて細部が多いが、ここまで押さえれば開発から本番まで安定した Web サービス構成を組み立てられる。
FAQ
Docker Nginx の設定ファイルを変更しても反映されないのはなぜ?
5 つの正しいマウント方法:
1) 設定ファイルをマウント:-v ./nginx.conf:/etc/nginx/nginx.conf
2) 設定ディレクトリをマウント:-v ./conf.d:/etc/nginx/conf.d
3) Volume を使う
4) docker-compose で設定
5) ConfigMap(K8s 環境)
ベストプラクティス:
• 単一ファイルよりディレクトリマウント
• メイン設定は読み取り専用で保護
• conf.d と ssl ディレクトリを忘れない
• vim の inode 問題に注意
Docker Nginx の HTTPS はどう設定する?
• Let's Encrypt の無料証明書を使う
• 自動更新:certbot renew
• 証明書ディレクトリをマウント:-v ./certs:/etc/nginx/certs
• SSL 証明書パスを設定
• HTTP/2 と TLS 1.3 に対応
Let's Encrypt 設定:
• certbot で証明書取得:certbot certonly --standalone
• 自動更新のテスト:certbot renew --dry-run
• 証明書をコンテナにマウント:-v ./letsencrypt:/etc/letsencrypt
• nginx.conf で証明書を参照
Docker Nginx のリバースプロキシはどう設定する?
• upstream でバックエンドコンテナを指定
• コンテナ名やサービス名を使う:proxy_pass http://backend:8080
• ヘルスチェックを設定
• CORS 問題への対処
• ロードバランシング
コンテナ間通信:
• docker-compose でカスタムネットワークを作成
• コンテナを同じネットワークに置く
• サービス名やコンテナ名でアクセス
• upstream でバックエンドサービスを指定
Docker Nginx の本番環境ベストプラクティスは?
• docker-compose で複数コンテナを管理
• ヘルスチェックを設定
• リソース制限を設定
• ログローテーション
• 環境変数で設定を管理
• イメージを定期的に更新
Docker Nginx はシンプルに見えて細部が多いが、ここまで押さえれば開発から本番まで安定した Web サービス構成を組み立てられる。
アドバイス:本記事の設定テンプレートを保存しておき、次回から再利用しよう。
6分で読めます · 公開日: 2025年12月18日 · 更新日: 2026年6月8日
Docker 実践ガイド
検索からこのページに来た場合は、前後の記事もあわせて読むと同じテーマの理解がかなり早く深まります。
前の記事
DockerでMySQLをデプロイ:データ永続化から主従レプリケーションまでの完全ガイド
Docker MySQL のデータ永続化から主従レプリケーション設定まで。コンテナ再起動でデータが消える問題、設定ファイルのマウント、接続失敗などを解説し、本番向けデプロイ手順をまとめます。
第 27 / 37 記事
次の記事
Dockerイメージのセキュリティスキャンと修正:Trivy実践チュートリアルとCI/CD統合ガイド
Docker Hubの76%のイメージにセキュリティ脆弱性が存在します。Trivyスキャンツールの実践的な使い方、体系的な脆弱性修正方法、CI/CD自動化統合まで解説。完全なコマンド例付きで、安全なコンテナアプリ構築を支援します。
第 29 / 37 記事
関連記事
Dockerfile入門:ゼロから最初の Docker イメージを作る(実例付き)
Dockerfile入門:ゼロから最初の Docker イメージを作る(実例付き)
Docker vs 仮想マシン:5分で理解する性能差とシーン別選び方ガイド
Docker vs 仮想マシン:5分で理解する性能差とシーン別選び方ガイド
Docker インストールの落とし穴ガイド 2025:permission denied から正常起動までの完全解決策
コメント
GitHubアカウントでログインしてコメントできます