1. 導入:なぜEXPOSEが必要なのか
Dockerでコンテナを構築する際、Dockerfileに記述する「EXPOSE」命令について、「これを書かないとポートが繋がらないのでは?」と誤解されることがあります。結論から言えば、EXPOSEはネットワーク上のポートを直接「開放」するものではありません。しかし、実務においてこの命令を適切に記述することは、インフラの可読性を高め、CI/CDパイプラインやオーケストレーションツールとの連携を円滑にするために不可欠です。本記事では、EXPOSEの本来の役割と、現場で迷わないための使い分けを解説します。
2. 基礎知識:EXPOSEとポート公開の違い
まず、Dockerにおけるポートの扱いには「ドキュメントとしての役割」と「実行時の設定」という2つの側面があります。
EXPOSE(メタデータ): Dockerfile内で「このコンテナは内部的にこのポートで待ち受けをする予定です」と宣言するものです。これ自体にはホスト側のポートをバインドする機能はありません。
-p / –publish(ポート転送): docker run実行時に指定するオプションです。ホストマシンのポートとコンテナのポートを物理的に接続します。
つまり、EXPOSEは「設計図への注釈」、-pは「実際の配線工事」のような関係です。
3. 実装と解決策
EXPOSE命令は、チーム開発において「どのポートをリッスンすべきか」を共有するための重要なドキュメントです。また、Dockerのネットワーク機能において、コンテナ間通信(–linkやカスタムネットワーク)を利用する際、EXPOSEされたポートの情報が自動的に参照されることもあります。
実務でのベストプラクティスは、アプリケーションが利用する主要なポートを明示的に記述し、開発者が `docker ps` や `docker inspect` コマンドだけで構成を把握できるようにすることです。
4. サンプルプログラム
以下は、Node.jsのWebアプリケーションを想定したDockerfileの例です。
ベースイメージの指定
FROM node:18-slim
アプリケーションが使用するポートを明示(ドキュメントとしての役割)
8080ポートでリッスンすることをチームメイトに伝えます
EXPOSE 8080
WORKDIR /app
COPY . .
RUN npm install
アプリケーションの起動
CMD [“node”, “server.js”]
—
実行時のコマンド例:
EXPOSEで宣言したポートをホストの8080にマッピングして起動
docker run -d -p 8080:8080 my-app-image
5. 応用・注意点:現場で陥りやすいポイント
自動化ツールとの連携
AWS ECSやKubernetesなどのオーケストレーションツールを使用する場合、Dockerfile内のEXPOSE命令を読み取り、自動的にロードバランサーの設定やセキュリティグループのルール作成に利用するケースがあります。この場合、EXPOSEを省略すると設定が自動化できず、手動運用の手間が増える原因となります。
セキュリティの誤解
「EXPOSEを書くとセキュリティが甘くなる」という懸念を持つ方がいますが、それは誤りです。EXPOSEは単なる情報提供であり、実際に通信を許可するかどうかは、実行時の `-p` オプションや、クラウド環境のセキュリティグループ/ファイアウォール設定で制御すべきです。
まとめ
EXPOSEは「必須ではないが、書くべき」命令です。インフラ設計の意図をコード(Dockerfile)に込めることは、属人化を防ぎ、トラブルシューティングの時間を大幅に削減します。迷ったら、アプリケーションが待ち受けを行うポートを必ず記述する習慣をつけましょう。

コメント