こうした場面でつまずく方は少なくありません。
EXPOSE命令はDockerfileに書く命令ですが、ホスト側にポートを公開する処理は行いません。
ホストからコンテナへ通信を届けるには、docker runに-pオプションを指定するか、docker-compose.ymlのports設定が必要です。
この記事では、DockerfileのEXPOSE命令とdocker runの-pオプション・docker-compose.ymlのports設定の役割を整理します。
NginxコンテナをCompose管理するシンプルな構成を例にして、ポートの対応関係と動作確認の方法を確認します。
想定環境はDocker Engine 24以降、AlmaLinux 9またはUbuntu 24.04 LTSです。
この記事のポイント
・EXPOSEはポート番号を宣言するだけで、ホストへの公開は行わない
・ホストから接続するにはdocker run -p ホストポート:コンテナポート の形で指定する
・docker-compose.ymlのports:はdocker runの-pと同じ役割を担う
・ssコマンドでホスト側のリッスンポートを確認できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
DockerfileのEXPOSEはポート番号の宣言であり公開設定ではない
DockerfileのEXPOSE命令は、このイメージがどのポートを使用するかをイメージの利用者やDockerツールに伝えるためのメタデータです。コンテナを起動したとき、EXPOSE 80と書いてあっても、ホストの80番ポートにトラフィックが届く設定は行われていません。
EXPOSEにはドキュメントとしての役割と、docker run --publish-all(-P)オプションとの連携という2つの用途があります。
EXPOSEの用途まとめ:
・イメージの利用者にポート番号を伝えるドキュメントとしての役割
・docker run -Pを使ったとき、ランダムなホストポートへのマッピングのヒントになる
・同一Composeネットワーク内でのコンテナ間通信では、EXPOSEされたポートが通信可能になる
「EXPOSE 80と書いたからポートが公開された」という理解は誤りで、ホストからアクセスするには別途-pオプションの指定が必要です。
docker runの-pオプションでホストにポートを公開する
1. 基本の書き方:ホストポートとコンテナポートを対応させる
docker runに-pオプションを指定すると、「ホストのXXX番ポートに来たリクエストをコンテナのYYY番ポートへ転送する」という設定が行われます。# 書式 docker run -p ホストポート:コンテナポート イメージ名 # Nginxをホストの8080番ポートで公開する例 docker run -p 8080:80 nginx # バックグラウンドで起動する場合 docker run -d -p 8080:80 nginx
コンテナポートの番号はDockerfileのEXPOSE命令で宣言されている番号と一致させるのが基本です。
Nginxの公式イメージはEXPOSE 80と宣言されているため、コンテナポートの指定は80になります。
2. 複数ポートを同時に公開する
-pオプションは複数指定できます。HTTPとHTTPSを両方公開する場合など、必要なポート数だけ-pを繰り返します。
# HTTPとHTTPSを両方公開する例 docker run -d \ -p 80:80 \ -p 443:443 \ nginx
3. バインドアドレスを指定して公開範囲を絞る
-pには「どのネットワークインターフェースからの接続を受け付けるか」を指定できます。# すべてのネットワークインターフェースから受け付ける(デフォルト) docker run -d -p 0.0.0.0:8080:80 nginx # ローカルループバックのみ受け付ける(外部からアクセス不可) docker run -d -p 127.0.0.1:8080:80 nginx
docker-compose.ymlのports設定でCompose管理する
1. ports:のYAML記法
docker-compose.ymlではports:キーを使って、docker runの-pと同じポート公開設定を行います。# docker-compose.yml の例 services: web: image: nginx ports: - "8080:80"
Composeでは数値を文字列で書く形式(- "80:80")が最もよく使われます。
YAMLマッピング形式(target: 80、published: 8080)を使う書き方もありますが、現場の設定ファイルでは文字列形式が一般的です。
2. EXPOSEとports:の役割分担
DockerfileのEXPOSEとdocker-compose.ymlのports:は、次のように役割が分かれています。| 設定箇所 | 役割 | ホスト公開 |
|---|---|---|
| Dockerfile EXPOSE | コンテナが使うポートの宣言(ドキュメント) | しない |
| docker run -p | ホストポート→コンテナポートの転送設定 | する |
| docker-compose ports: | docker run -pと同じ転送設定(Compose管理) | する |
| docker-compose expose: | コンテナ間通信用のポート宣言(ホストには公開しない) | しない |
docker-compose.ymlのexpose:はDockerfileのEXPOSEと同じ効果で、同一Composeネットワーク内のコンテナ間通信にのみ影響します。
ホストからアクセスするにはports:の設定が必要です。
NginxとAPIサーバーのCompose実構成例
フロントにNginxを置き、バックエンドのAPIサーバーとCompose管理する構成を見てみます。Dockerfileの例:
# Dockerfile(Node.js APIサーバーの例) FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "server.js"]
# docker-compose.yml services: web: image: nginx:alpine ports: - "80:80" depends_on: - api api: build: . expose: - "3000"
Dockerfileに書いたEXPOSE 3000は、docker-compose.ymlのexpose:の値と対応しています。
外部に公開する必要のないAPIサーバーをports:でホストに公開してしまうのはセキュリティ上のリスクになるため、このようにNginxをフロントエンドに置く設計がよく使われます。
Dockerの設計パターンや実践的な構築方法を体系的に学びたい方は、Docker実践講座もご覧ください。
ポートが公開されないときの確認手順
コンテナを起動してもホストからアクセスできない場合、次の順で確認します。1. コンテナが起動しているかdocker psで確認する
docker ps # 出力例(環境により異なります) CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a1b2c3d4e5f6 nginx "/docker-entrypoint..." 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp my_nginx
何も表示されていない場合は-pオプションを指定せずに起動しています。
2. ホスト側でポートが待受状態になっているかssで確認する
# ホスト側のリッスンポートを確認する ss -tlnp | grep 8080 # 出力例(環境により異なります) LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=12345,fd=4))
出力が空の場合は-pオプションの指定が抜けています(Linux ポート確認の全コマンド)。
3. ファイアウォールでポートが遮断されていないか確認する
ホスト側のファイアウォール設定でポートが遮断されている場合もあります。# firewalldが有効な環境で確認する場合 sudo firewall-cmd --list-ports # iptablesで確認する場合 sudo iptables -L DOCKER -n --line-numbers
4. コンテナ内でサービスが起動しているか確認する
ポートフォワードの設定は正しくても、コンテナ内のサービスが起動していなければアクセスできません。# コンテナ内でプロセスを確認する(コンテナIDは実際のIDに置き換えてください) docker exec -it a1b2c3d4e5f6 bash # コンテナ内で実行 ps aux
まとめ
DockerfileのEXPOSEとdocker runの-p・Composeのports:の対応関係をまとめます。| やりたいこと | 設定方法 |
|---|---|
| ホストからコンテナのポートにアクセスする | docker run -p ホストポート:コンテナポート |
| Composeでポートを公開する | docker-compose.ymlのports: - "ホスト:コンテナ" |
| コンテナ間通信のみ(ホスト非公開) | docker-compose.ymlのexpose: - "コンテナポート" |
| ポート公開状態を確認する | docker ps のPORTS列、またはss -tlnp |
EXPOSEはポート番号のドキュメントであり、ホスト公開の設定ではありません。
「コンテナが起動しているのにアクセスできない」場合は、まず-pオプションまたはports:設定が抜けていないかを確認してください。
Composeでは内部サービス(DBやAPIなど)はexpose:のみで管理し、外部に公開するフロントエンドだけにports:を指定する設計が、セキュリティ上もシンプルな管理の面でも有効です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、
Dockerコンテナの基礎からComposeを使った実践的なサーバー構築まで、ハンズオン形式でスキルを身につけられます。
>>Docker実践講座の詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:docker compose runで使い捨てコンテナを起動する方法|exec・upとの使い分けとテスト・マイグレーション実行のCompose設計
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます