ポート公開と簡単な Web コンテナ — Docker Tips
コンテナは外からそのまま届きません。-p ホスト:コンテナ で穴を開けます。nginx を立ててブラウザで開き、ポート競合と EXPOSE の意味も触ります。
参考: Publish ports · docker run -p · EXPOSE · Networking
目次
- ポート公開がなぜ必要か
-p HOST:CONTAINERの書き方- nginx コンテナを立てて確認する
- ブラウザでの確認手順
- ポートが既に使われているとどうなるか
EXPOSEと-pの違い- 複数ポート・ランダムポートの公開
- うまくいかないとき
ポート公開がなぜ必要か
コンテナは Docker が管理する仮想的なネットワーク空間(ブリッジネットワーク)の中で動いています。コンテナ内で Web サーバーが 80 番ポートで待ち受けていても、ホスト側のブラウザからは何も見えません。ホストの localhost:8080 のようなアドレスからコンテナ内のプロセスへ届けるには、ホストのポートとコンテナのポートを明示的につなぐ 作業が必要です。これが「ポート公開(publish)」です。
| 用語 | 意味 |
|---|---|
| ホストポート | PC(ローカル環境)側で開くポート番号 |
| コンテナポート | コンテナ内のプロセスが実際に listen しているポート番号 |
| 公開(publish) | ホストポート ⇄ コンテナポートの対応付け |
対応付けをしない限り、コンテナのネットワークは既定でホストから閉じています。これは意図しないポート露出を防ぐための安全側の挙動です。
-p HOST:CONTAINER の書き方
docker run の -p(--publish)は次の形式を取ります。
-p [ホストIP:]ホストポート:コンテナポート[/プロトコル]| 記法 | 意味 |
|---|---|
-p 8080:80 |
ホストの 8080 → コンテナの 80 |
-p 127.0.0.1:8080:80 |
ホストの localhost からのみアクセス可(外部 NIC からは不可) |
-p 8080:80/udp |
UDP ポートを公開(省略時は TCP) |
-p 8080:80 -p 8443:443 |
複数ポートをまとめて公開 |
よくある勘違い: -p 80:8080 のように 左右を逆に書くミスです。左(コロンの前)が ホスト側、右(コロンの後)が コンテナ側 です。
nginx コンテナを立てて確認する
公式の nginx イメージはビルド不要で、デフォルトで 80 番ポートを待ち受けます。
docker run -d --name web-demo -p 8080:80 nginx| オプション | 意味 |
|---|---|
-d |
バックグラウンドで起動(デタッチモード) |
--name web-demo |
コンテナ名を指定 |
-p 8080:80 |
ホストの 8080 をコンテナの 80 に接続 |
nginx |
公式イメージ名(タグ省略時は latest) |
起動状態とポートの対応は次で確認できます。
docker ps --filter name=web-demoPORTS 列に 0.0.0.0:8080->80/tcp のような表示が出れば、公開が成立しています。より詳細な対応は docker port でも見られます。
docker port web-demoブラウザでの確認手順
- コンテナが
Up状態であることをdocker psで確認する - ブラウザで
http://localhost:8080を開く - nginx の Welcome ページ("Welcome to nginx!")が表示されれば成功
コマンドラインで確認する場合は PowerShell の Invoke-WebRequest、または curl.exe を使います(PowerShell の curl は別名として動くため curl.exe を明示すると挙動が安定します)。
curl.exe http://localhost:8080HTML の先頭に <!DOCTYPE html> と Welcome to nginx! の文字列が返れば、ホスト→コンテナの通信が通っています。
確認後の後片付け
docker stop web-demodocker rm web-demoポートが既に使われているとどうなるか
同じホストポートを複数のコンテナで公開しようとすると、次のようなエラーになります。
Error response from daemon: driver failed programming external connectivityon endpoint web-demo2 (...): Bind for 0.0.0.0:8080 failed:port is already allocated原因は次のいずれかです。
| 原因 | 具体例 |
|---|---|
| 別のコンテナが同じホストポートを公開中 | web-demo が 8080 を掴んでいる |
| ホスト上の別プロセスが使用中 | 開発用サーバーやほかのアプリが 8080 で listen |
| 直前のコンテナが正しく停止していない | docker stop 前に PC を落とした等 |
対処
# 何が 8080 を使っているか確認docker ps --filter "publish=8080"# 使っていないコンテナを止めるdocker stop web-demo# または別のホストポートを使うdocker run -d --name web-demo2 -p 8081:80 nginx「コンテナ内側のポート」は複数コンテナで重複しても問題ありません(例えば全部が 80 で listen していてよい)。競合するのは ホスト側のポート だけです。
EXPOSE と -p の違い
Dockerfile に書く EXPOSE は、実際にはポートを公開しません。「このイメージはどのポートで listen する想定か」を伝えるドキュメント(メタデータ) です。
FROM nginx:alpineEXPOSE 80| 項目 | EXPOSE(Dockerfile) |
-p / --publish(run 時) |
|---|---|---|
| 実際にホストへ公開するか | しない(情報提供のみ) | する |
| 書く場所 | Dockerfile | docker run / Compose の ports |
| コンテナ間通信への影響 | なし(同一ネットワーク内は EXPOSE なしでも到達可) |
なし |
-P(大文字)との関係 |
EXPOSE した番号を -P でランダムなホストポートへ一括公開できる |
— |
つまり EXPOSE だけを書いて -p を付けずに docker run すると、コンテナは起動してもホストからは一切アクセスできません。逆に EXPOSE を書かなくても -p さえ指定すれば公開自体は機能します。EXPOSE は省略しても動くが、読み手への意思表示として書いておく のが実務的な運用です。
複数ポート・ランダムポートの公開
# 複数ポートを個別に公開docker run -d --name multi-demo -p 8080:80 -p 8443:443 nginx# EXPOSE されている全ポートをランダムなホストポートに一括公開docker run -d --name random-demo -P nginxdocker port random-demo-P(大文字)はポート番号を自分で決めたくない検証時に便利ですが、番号が毎回変わるため docker port での確認が前提になります。恒常的に使うサービスでは -p で固定するほうが扱いやすいです。
うまくいかないとき
| 症状 | 原因 | 対処 |
|---|---|---|
port is already allocated |
ホストポートが他のコンテナ/プロセスで使用中 | docker ps --filter "publish=<port>" で特定して停止、または別ポートを使う |
ブラウザで localhost:8080 に繋がらない |
ポート未公開、または公開先を間違えた | docker ps の PORTS 列と -p の左右(ホスト:コンテナ)を確認 |
コンテナは Up なのに接続できない |
アプリがコンテナ内の 0.0.0.0 ではなく 127.0.0.1 だけで listen している |
アプリ側の bind アドレス設定を確認(Docker の問題ではなくアプリ設定の問題) |
-p を付けたのに EXPOSE していないポート番号を使ったら失敗する気がする |
誤解。EXPOSE の有無は -p の動作に影響しない |
EXPOSE は必須ではない。-p ホスト:コンテナ の対応が正しければ動く |
| Windows Defender ファイアーウォールに阻まれる | プライベート/パブリックネットワークの許可設定 | 初回接続時のダイアログで許可、または Windows のファイアーウォール設定を確認 |
| 停止済みのはずのコンテナがポートを掴み続けている | docker stop せず PC をシャットダウンした |
docker ps -a で残存コンテナを確認し docker rm で削除 |
ポート公開は「ホスト側の入口」と「コンテナ側の出口」を対応付ける単純な仕組みですが、左右を混同する・公開し忘れる・番号が衝突する、という 3 パターンでほとんどのトラブルが説明できます。