Skip to content
VDS · Dockerとコンテナ

Dockerネットワークとポートフォワーディング

コンテナ間の通信の仕組み、ポート公開と単なるEXPOSEの違い、Dockerがufwのルールをバイパスする理由を説明します。

更新日 2026年8月23日

コンテナの問題の半分はネットワーク関連です。サービスがデータベースに接続できない、ポートが使用中、コントロールパネルが突然インターネット全体に公開される。この仕組みを整理しましょう。

3種類のネットワーク

  • bridge — デフォルトです。コンテナは内部アドレスを取得して相互に通信し、外部へはホストの NAT を通じて出ていきます。
  • host — コンテナはホストのネットワークを直接使用します。ポートの公開は不要で、機能もしません。高速ですが分離はありません。コンテナのポート 80 はホストのポート 80 になります。
  • none — ネットワークがまったくありません。不要なタスク向けです。

自分で作成した、または Compose が作成したカスタムネットワークは、デフォルトの bridge と重要な点で1つ異なります。名前解決が機能するのです。app コンテナは db という名前で db コンテナに到達できます。

docker network create backend
docker network ls
docker network inspect backend

Compose では、このようなネットワークがプロジェクトごとに自動で作成されます。

ポートの公開

ports:
  - "127.0.0.1:8080:8080"   # accessible only from the machine itself
  - "80:80"                 # accessible to the whole internet

左がホスト側のポート、右がコンテナ内のポートです。イメージ内の EXPOSE ディレクティブは何も公開しません。アプリケーションがどのポートで待ち受けるかを示すメモにすぎません。

ルールはシンプルです。外部からアクセスする必要があるものだけを公開します。データベース、コントロールパネル、内部 API は 127.0.0.1 に置き、証明書を持つ Web サーバーがそれらを外部へ公開します。

Docker は iptables のルールを自身で書き込み、しかも ufw が管理するチェーンより前に行います。-p 8080:8080 として公開されたポートは、ufw が「deny」と表示していてもインターネットからアクセスできます。ファイアウォールに頼らず、ポートを 127.0.0.1 にバインドしてください。

コンテナ間の通信

services:
  app:
    networks: [frontend, backend]
  db:
    networks: [backend]
  proxy:
    networks: [frontend]
    ports:
      - "80:80"
      - "443:443"

networks:
  frontend:
  backend:

ここではデータベースはアプリケーションからのみアクセスでき、外部に面しているのは Web サーバーだけです。これはどのようなスタックにも適した正しい構成です。

コンテナ内からは、隣接するサービスをサービス名で参照します。postgres://db:5432/app。コンテナ内の localhost というアドレスはホストではなくコンテナ自身を指します。これは latest に次いでよくある間違いです。

ホスト自体で動作しているサービスにコンテナから到達するには、host.docker.internal という名前を使用し、次を追加します。

extra_hosts:
  - "host.docker.internal:host-gateway"

診断

docker compose exec app ping -c2 db
docker compose exec app getent hosts db
sudo ss -tulpn | grep LISTEN
docker port <container>

ss はポートが実際にどのインターフェースで待ち受けているかを表示します。0.0.0.0:8080 は外部に公開、127.0.0.1:8080 は公開していません。

よくある間違い

  • 「ポートはすでに使用されています」。 別のコンテナまたはホストのサービスが占有しています。sudo ss -tulpn | grep :80 で原因を特定できます。
  • 異なる Compose プロジェクトのコンテナは互いに認識できません。 各プロジェクトには独自のネットワークがあります。networks: { shared: { external: true } } で明示的に接続してください。
  • アプリケーションがコンテナ内の 127.0.0.1 で待ち受けています。 この場合、公開しても役に立ちません。コンテナの外部から到達できないのです。アプリケーションが 0.0.0.0 で待ち受けるように設定してください。
  • 帯域幅。 ホストあたり最大 500 Mbps を共有します。ファイル配信はそれを他のすべてと共有します。