Dockerハンズオン|nginxでWebサーバを立ててブラウザからアクセスする【ポート転送の応用】
2-7 では Python と PostgreSQL を使って、コンテナの中で完結する操作を体験しました。今回はいよいよコンテナの外(あなたのPCのブラウザ)からコンテナの中(nginx)にアクセスします。2-6 で学んだ -p ポート転送と -v ボリュームマウントの実戦投入編です。
①
docker run -p 8080:80 nginx でWebサーバを起動、ブラウザで http://localhost:8080 を開いて nginx の画面を確認②
docker logs でアクセスログが流れる様子を観察③
-v で自分の書いた index.html を配信(カスタムHTMLの差し替え)④ コンテナの中を覗いて、nginx がどこに設定ファイルを置いているか確認
目次
- 前提:ここまで学んだオプション
- なぜ nginx でハンズオン?
- Part 1:nginx を起動してブラウザでアクセス
- Part 2:アクセスログを観察する
- Part 3:自分の HTML を配信する(
-v) - Part 4:コンテナの中身を覗いてみる(好奇心編)
- 後片付け
- 今回使ったオプションまとめ
- よくあるつまずき
- 次のステップ:第3章 → 自分専用イメージを作る
1. 前提:ここまで学んだオプション
第2章の前半で以下を身につけてきました。このハンズオンで一気に組み合わせて使います。
| 記事 | 学んだこと | 今回使う場面 |
|---|---|---|
| 2-2 主要コマンド | run / ps / logs / exec |
全編 |
| 2-5 デタッチモード | -d / --name |
nginx を常駐起動 |
| 2-6 ポートマッピング | -p 8080:80 |
ブラウザから接続するための橋渡し |
| 2-6 ボリュームマウント | -v /host/path:/in/container |
自作HTMLをコンテナに渡す |
| 2-7 Python/Postgres ハンズオン | docker exec -it で中に入る |
nginx の設定ファイルを覗く |
docker version が通ることと、ホスト側のポート 8080 が空いていること(他のアプリで使用中ならエラーになります)を確認してください。使用中の場合は -p 9080:80 のようにホスト側ポート番号を変えればOKです。
2. なぜ nginx でハンズオン?
nginx(エンジンエックス)は世界で最も使われているWebサーバの1つです。静的ファイル配信・リバースプロキシ・ロードバランサーなど、現場のあらゆる場所で登場します。
今回 nginx を題材に選んだ理由は2つ:
- 起動して即アクセスできる:公式イメージは何も設定しなくてもデフォルトのWelcomeページを配信してくれる。つまりポート転送の効果がすぐ目で確認できる。
- 設定ファイルの場所が決まっている:
/usr/share/nginx/html(公開ディレクトリ)、/etc/nginx/(設定)。これは-vボリュームマウントの練習に最適。
httpd(Apache)・caddy・node(Express等)・python:3.12(Flask/FastAPIアプリ)も全部同じ流れで動かせます。今日の学びはnginx以外にもそのまま使えます。
3. Part 1:nginx を起動してブラウザでアクセス
3-1. イメージを取得する
docker pull nginx
約 200MB 前後のイメージです。ダウンロード後、docker images で一覧を確認できます。
3-2. ポート転送付きで起動する
docker run -d --name web -p 8080:80 nginx
各オプションを確認しましょう。
| オプション | 役割 |
|---|---|
-d |
バックグラウンド起動(2-5 復習) |
--name web |
後で logs/exec/stop で指定するための名前 |
-p 8080:80 |
ホスト側 8080 番ポートをコンテナ内の 80 番に転送(2-6 復習) |
nginx |
使うイメージ(タグ省略で latest) |
-p HOST:CONTAINER の順番を覚えるコツ「家の外(HOST)から、家の中(CONTAINER)へ」の順。左が外(ブラウザが叩く側)、右が中(nginxが待ち受ける側)。左右を間違えるとアクセスできません。
3-3. ブラウザで開いてみる
Webブラウザで次のURLを開いてください。
http://localhost:8080
「Welcome to nginx!」の画面が表示されれば成功です。こんな画面です:
あなたは今、自分のPCにnginxをインストールせずにWebサーバを立てて、ブラウザからアクセスしました。これが Docker の一番わかりやすい嬉しさです。
3-4. 通信の流れを図で把握する
ブラウザから nginx までの通り道を整理しておきましょう。-p 8080:80 はこの「橋」を架けるオプションです。
-p 8080:80 がホストの8080とコンテナの80を橋渡し
ホスト側を
9090 にしたいときは -p 9090:80。アクセスURLも http://localhost:9090 になります。コンテナ側(右の80) は nginx が待ち受けているポートなので基本は変えません。
3-5. シミュレータで同じ流れを試す
下のシミュレータで docker run -d nginx → docker ps → docker exec -it と一連を体験できます(クイックアクションボタンが便利)。
4. Part 2:アクセスログを観察する
ブラウザでアクセスした時、nginx はアクセスログを出力しています。このログを見ると、いつ・どこから・どのURLに誰が来たかがわかります。
4-1. docker logs で見てみる
docker logs web
こんな行が並んでいるはずです(あなたがアクセスした回数だけ)。
172.17.0.1 - - [20/Apr/2026:03:15:22 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 ..."
172.17.0.1 - - [20/Apr/2026:03:15:22 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "-" "Mozilla/5.0 ..."
| ログの一部 | 意味 |
|---|---|
172.17.0.1 |
アクセス元のIP(Docker内部ネットワーク経由で見えている) |
GET / |
トップページへのリクエスト |
200 |
正常応答(ステータスコード) |
GET /favicon.ico ... 404 |
ブラウザが自動で探しに行ったファビコン(今は無いので404) |
4-2. リアルタイムで流れを見る(-f フォロー)
docker logs -f web
この状態でブラウザをリロード(F5)すると、1行ずつログが増えていくのがリアルタイムで見えます。止めるときは Ctrl+C。
docker logs で nginx のログが見えるのか?nginx 公式イメージは、アクセスログファイル
/var/log/nginx/access.log をコンテナの標準出力に、エラーログを標準エラー出力にシンボリックリンクで繋いでいます。Docker は各コンテナの標準出力を記録しているので、docker logs で一括で見えるわけです。自作アプリでも print(...) や console.log(...) をそのまま標準出力に出しておけば同じ仕組みで見られます。
5. Part 3:自分の HTML を配信する(-v)
Welcome ページだけでは味気ないので、自分で書いた HTML を配信してみましょう。-v ボリュームマウント(2-6 復習)を使います。
5-1. 準備:カスタム index.html を作る
作業用ディレクトリを決めて、そこに index.html を1つ置きます。
# 作業用ディレクトリを作る
mkdir myhtml
cd myhtml
# index.html を作成(エディタで作ってもOK)
cat > index.html <<'EOF'
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="utf-8"><title>My Docker Page</title></head>
<body style="font-family:sans-serif;background:#e3f2fd;padding:2em">
<h1>🐳 Docker ハンズオン成功!</h1>
<p>これは -v でマウントした自作ページです。</p>
</body>
</html>
EOF
5-2. いったん古いコンテナを止める
docker stop web
docker rm web
5-3. ボリュームマウントで再起動
# macOS / Linux / WSL2
docker run -d --name web -p 8080:80 \
-v "$(pwd)":/usr/share/nginx/html:ro nginx
# Windows PowerShell
docker run -d --name web -p 8080:80 `
-v "${PWD}:/usr/share/nginx/html:ro" nginx
追加された -v オプションの中身:
| 部分 | 意味 |
|---|---|
$(pwd) / ${PWD} |
ホスト側の現在のディレクトリ(絶対パス) |
:/usr/share/nginx/html |
nginx がデフォルトで HTML を探す場所(固定) |
:ro |
read-only(コンテナから書き込ませない安全策) |
5-4. ブラウザで確認
再び http://localhost:8080 を開いてください(F5でリロード)。先ほどの Welcome ページではなく、自分で書いた🐳のページが表示されているはずです:
Welcome ページと見比べると、同じ URL・同じコンテナなのに配信内容が入れ替わったことが一目瞭然です。これがボリュームマウントの威力です。
5-5. マウントの関係を図で整理
-v $(pwd):/usr/share/nginx/html:ro で両者を紐付け
index.html をエディタで編集して保存すれば、コンテナを再起動しなくてもブラウザ更新で新しい内容が見られます。これが -v の本番での大きな価値:開発中はホストで編集、コンテナはそのまま動かし続ける。
5-6. シミュレータでマウントの挙動を確認
下のシミュレータで「ホスト側で編集したファイルが、コンテナ内から見えるようになる」仕組みを可視化できます。
6. Part 4:コンテナの中身を覗いてみる(好奇心編)
ここは必須ではないですが、「コンテナって内部どうなってるの?」を体感するのに最高の素材です。2-7 と同じく docker exec -it で入ります。
docker exec -it web bash
コンテナ内のシェルに切り替わります。いくつか探検してみましょう。
6-1. nginx の公開ディレクトリを見る
root@xxx:/# ls /usr/share/nginx/html
index.html
root@xxx:/# cat /usr/share/nginx/html/index.html
ホスト側で書いた index.html が見えるはずです。これは -v マウントのおかげです。
6-2. nginx の設定ファイルを眺める
root@xxx:/# ls /etc/nginx/
conf.d/ fastcgi_params mime.types nginx.conf ...
root@xxx:/# head -20 /etc/nginx/nginx.conf
全てのnginx設定がここに置かれています。本格的な運用ではこれらを -v や Dockerfile でカスタマイズします。
6-3. アクセスログの場所を確認
root@xxx:/# ls -la /var/log/nginx/
lrwxrwxrwx 1 root root 11 ... access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 ... error.log -> /dev/stderr
/dev/stdout /dev/stderr にリンクされているので、nginx がログに書き込む=コンテナの標準出力に出る=docker logs で見える、という設計になっています。「Dockerでログはどこ?」の答えはこれです。
探検が終わったらコンテナから抜けます。
root@xxx:/# exit
web コンテナは引き続き動いています(2-7 で学んだとおり、exec で入ったシェルを抜けてもコンテナは停止しません)。
7. 後片付け
docker stop web
docker rm web
イメージも不要なら削除。
docker rmi nginx
-v でマウントしたのはホスト側のディレクトリなので、コンテナを消しても index.html はそのまま手元に残ります。これがボリュームマウントの「データはホスト側にある」メリットです。
8. 今回使ったオプションまとめ
| オプション | 役割 | 今回の使い方 |
|---|---|---|
-d |
バックグラウンド起動 | nginx を常駐させる |
--name web |
名前付け | logs/exec/stop で指定 |
-p 8080:80 |
ポート転送 | ホスト8080 → コンテナ80 |
-v $(pwd):/usr/share/nginx/html:ro |
ボリュームマウント(読み取り専用) | カスタム index.html を配信 |
docker logs web |
コンテナの標準出力を表示 | アクセスログ観察 |
docker logs -f web |
ログをリアルタイム表示 | ブラウザF5で流れを見る |
docker exec -it web bash |
動作中コンテナに入る | 中身を探検 |
9. よくあるつまずき
| 症状 | 原因 | 対処 |
|---|---|---|
port is already allocated |
ホスト8080が他のアプリで使用中 | -p 9080:80 のようにホスト側ポートを変える |
| ブラウザで「接続できません」 | -p を付け忘れた/コンテナが起動していない |
docker ps で Up を確認、-p を付けて再起動 |
| 403 Forbidden が出る | マウント先に index.html が無い/権限が無い |
ファイル名が index.html か、ホスト側で読める権限か確認 |
docker: Error response from daemon: invalid mount config(Windows) |
パスの書き方が違う | PowerShell なら "${PWD}:/usr/share/nginx/html"、cmd なら "%cd%:/usr/share/nginx/html" |
| 編集したのに反映されない | ブラウザキャッシュ | Ctrl+F5 でスーパーリロード |
2回目の --name web でエラー |
同名コンテナが残っている | docker rm web で削除してから起動 |
| WSL2でボリュームが空に見える | Docker Desktop の file sharing 未許可 | Docker Desktop → Settings → Resources → File Sharing でドライブ許可 |
10. 次のステップ:第3章 → 自分専用イメージを作る
今回は公式イメージをそのまま使って、外から -v で HTML を差し込む形でカスタマイズしました。小規模な確認や開発用にはこれで十分です。
ただ本番運用では、こんな要件が出てきます:
- HTMLだけでなく nginx の設定自体を変えたい(リバースプロキシ設定・独自モジュール追加 等)
- チームの他メンバーにも同じ環境を一発で配りたい
- CI/CD パイプラインで自動ビルドしたい
そこで登場するのが Dockerfile。公式の nginx イメージを土台に、自分の HTML や設定を最初から焼き込んだ独自イメージを作れます。
-v で外からHTML注入独自イメージを作る
3-1 Dockerfile 完全入門で、
FROM nginx から始まる Dockerfile を書いて、今回の index.html を含んだイメージを作ってみましょう。「docker build → docker push → 別のPCで docker pull → 動く」が1ループで体験できます。
11. まとめ
| 体験したこと | 使ったコマンド | 学んだこと |
|---|---|---|
| nginx をバックグラウンド起動 | docker run -d --name web -p 8080:80 nginx |
-p HOST:CONTAINER でブラウザから到達可能に |
| アクセスログ観察 | docker logs -f web |
コンテナの標準出力がログとして確認できる |
| カスタムHTML配信 | -v $(pwd):/usr/share/nginx/html:ro |
ホスト側のファイルをコンテナに注入、編集→F5で即反映 |
| コンテナ内を探検 | docker exec -it web bash |
nginx の公開ディレクトリ・設定・ログのシンボリックリンク |
| 後片付け | docker stop / rm |
ホスト側のデータはマウント元に残る |
これで第2章のハンズオン2本(2-7 Python/Postgres、2-8 nginx)をクリアしました。「コンテナの中で完結」も「外からアクセス・データ注入」も一通り体験できたので、第3章ではいよいよ自分専用のコンテナイメージを Dockerfile で作るステップに進みます。
参考リンク
- Docker Hub: nginx(公式イメージ) — 利用可能なタグ、公開ディレクトリ・設定ファイルのパスなど公式仕様。
- nginx 公式ドキュメント — nginx 自体の設定リファレンス。
- Published ports(Docker公式) —
-pオプションの詳細(範囲指定・IP指定など)。 - Bind mounts(Docker公式) —
-vボリュームマウントの一次情報源。



コメント