socatを使ってDockerコンテナ内からlocalhostでホストPCのサービスにアクセスする

socatを使ってDockerコンテナ内からlocalhostでホストPCのサービスにアクセスする

Dockerコンテナ内からlocalhostでホストPCのサービスに接続したいとき、alpine/socatをリレーとし て挟みnetwork_mode: "service:..."でネットワーク名前空間を共有することで、コードを変えずに実現できます。
2026.02.25

devcontainer(Docker)で開発をしていると、たまにコンテナ内からホストPC上で動いているサービス(開発用APIサーバーなど)に接続したい場面があります。

しかしコンテナ内で localhost127.0.0.1 を指定すると、それはコンテナ自身を指すため、ホストPCには届きません。

この問題の一般的な解決策は、Dockerが用意した特殊なホスト名 host.docker.internal を使うことです。
このホスト名はホストPCのIPアドレスに解決されるため、コンテナ内からホストのサービスにアクセスできます。

参考:How-tos | Docker Docs

弊社ブログでも、host.docker.internal を使った接続方法が紹介されています。

https://dev.classmethod.jp/articles/troubleshooting-docker-mysql-connection/

localhost や 127.0.0.1 が固定されていて変えられない場合

では、コードの接続先URLを変えられない場合はどうすれば良いでしょうか?

host.docker.internal を使うには、接続先のURLが変更可能でないといけません。
既存コードに localhost127.0.0.1 がハードコードされていて変更できないケースもあります。

そういったときに役立つのが、socatを使ったポートリレーです。socat のコンテナをリレー役として挟むことで、 アプリケーションのコードを一切変えずに localhost 接続をホストPCへ中継できます。
これを試してみました。

最初に結論

alpine/socat を使ったリレーサービスを追加します。

docker-compose.ymlの例
services:
  proxy-relay:
    image: alpine/socat:latest
    command: TCP-LISTEN:80,fork,reuseaddr TCP-CONNECT:host.docker.internal:3000
  my-app:
    image: curlimages/curl:latest
    command: [ "sleep", "infinity" ]
    network_mode: "service:proxy-relay"
    depends_on:
      - proxy-relay

my-app コンテナ内から http://localhost/ でアクセスすると、 proxy-relay がホストPCの 3000 番ポートへ中継します。

イメージ的にはこんな感じです。

socatとは

socat(SOcket CAT)は、2つのデータストリーム間でデータを双方向に中継するコマンドラインツールです。TCP、UDP、UNIXソケット、ファイルなど様々なデータチャンネルに対応しています。

今回は alpine/socat というDockerイメージを使います。
Alpine Linuxベースの軽量イメージで、Docker Composeのサービスとして簡単に組み込めます。

実装手順

前提環境

  • Docker、Docker Composeがインストール済み

docker-compose.ymlの設定

以下の例では、ホストPCの 3000 番ポートで動いているサービスにコンテナ内から接続できるようにします。

services:
  # ホストPCへの中継サービス
  proxy-relay:
    image: alpine/socat:latest
    command: TCP-LISTEN:80,fork,reuseaddr TCP-CONNECT:host.docker.internal:3000
    ## Linux環境の場合必要
    # extra_hosts:
    #   - host.docker.internal:host-gateway
  # アプリケーションサービス(例)
  my-app:
    image: curlimages/curl:latest
    command: ["sleep", "infinity"]
    network_mode: "service:proxy-relay"
    depends_on:
      - proxy-relay

socat コマンドの各パラメーターの意味は次のとおりです。

パラメーター 説明
TCP-LISTEN:80 80 番ポートでTCP接続を待ち受ける
fork 接続ごとに子プロセスを作成し、複数接続を並行処理する
reuseaddr ソケットをすぐに再利用できるようにする
TCP-CONNECT:host.docker.internal:3000 ホストPCの 3000 番ポートへ転送する

extra_hosts: host.docker.internal:host-gateway はLinux環境で必要な設定です。
macOSとWindowsでは host.docker.internal が標準で使えますが、Linuxでは明示的に追加する必要があります。

network_mode: "service:proxy-relay" を指定すると、my-app コンテナは proxy-relay のネットワーク名前空間を共有します。これにより my-app 内の localhostproxy-relay 自身のループバックインターフェースを指すようになり、socat が待ち受けているポートへ届きます。

参考:Services | Docker Docs

動作確認

実際に動作確認してみます。ホストPCでPythonの簡易HTTPサーバーを起動します。

# ホストPCで実行
$ python3 -m http.server 3000
Serving HTTP on :: port 3000 (http://[::]:3000/) ...

次に、コンテナを起動してコンテナ内から接続を確認します。

# コンテナ内で実行
$ curl http://localhost
<!DOCTYPE HTML>
...

ホストPCの簡易HTTPサーバーのレスポンスが返ってきました。コンテナ内からホストのサービスに接続できています。

ホストPC側のターミナルにもアクセスログが表示されます。

# ホストPCのターミナル
::ffff:127.0.0.1 - - [25/Feb/2026 15:31:38] "GET / HTTP/1.1" 200 -

注意点

接続するポートごとにsocatサービスが必要

1つの socat サービスは1ポートの中継に対応します。複数のポートを中継したい場合は、それぞれにサービスを追加するか、 socat コマンドを複数並べる工夫が必要です。

セキュリティ

開発環境での使用を想定しています。本番環境への適用は慎重に検討してください。

おわりに

socat を使ったDockerコンテナからホストPC接続の方法を紹介しました。

docker-compose.yml に数行追加するだけで、アプリケーションのコードを一切変更せずに localhost 接続をホストPCへ中継できます。既存コードに手を加えたくないケースや、devcontainer環境からホストのサービスに気軽につなぎたいときに便利です。

このブログがどなたかのお役に立てれば幸いです。

参考資料

この記事をシェアする

FacebookHatena blogX

関連記事