🐋

Dockerでlocalhostで他のサービスにアクセスしたい(socat)

2025/03/06に公開

始めに

以前、docker間通信をするときにどのドメイン名やIPを指定すればいいかを調べました。

しかし、例えばS3の署名付きURLを発行した後、フロントから直接署名付きURLでS3にアクセスする場合にはdocker内部ネットワークで解決した名前ではなく、localhostでアクセスさせたいです。

今回の記事では、フロントからS3の操作とバックエンドからS3の操作を統一できるようにするsocatについてまとめます。socatは様々なプロトコルやネットワーク間でデータを転送するためのユーティリティツールで、この問題解決に役立ちます。

環境

  • docker
    • 27.4.1
  • socat
    • alpine/socat
      • 1.8.0.1
  • minio
    • minio/minio
      • RELEASE.2025-02-28T09-55-16Z

ゴール

別のdocker imageからlocalhostでS3相当のminioにアクセスできること。今回は単純にするため、cURLでアクセスできたら成功とします。

また、cURLが使えるDocker imageではない場合、次のコマンドでcURLをインストールしてください。

apt-get update && apt-get install curl

実装

今回アクセスさせたいapiサービスとstorageサービスをcompose.ymlで記載します。

  api:
    # 適当なイメージ
  storage:
    image: minio/minio
    entrypoint: sh
    command: -c "mkdir -p /data/data-exchange.local /data/tmp.local && /usr/bin/minio server --address :9000 --console-address :9001 /data"
    ports:
      - "9000:9000" # APIとして
      - "9001:9001" # consoleとして
    env_file:
      - docker.env
    networks:
      - development_network

ネットワークをリレーさせるためにrelayサービスを作成し、dockerネットワークでアクセスさせるためにsocatを使用します。

次の書き方をするだけで、apiサービスからTCPlocalhost:9000した場合、storageサービスの9000番ポートにアクセスさせられます。

  # docker 内networkで localhost:9000 でアクセスさせるために必要
  relay:
    image: alpine/socat
    depends_on:
      - api
      - storage
    command: "TCP-LISTEN:9000,fork TCP:storage:9000"
    network_mode: service:api

ソースコード

終わりに

基本的にはdocker内部の通信だけ把握していれば事足りますが、どのサービスでも同じようにアクセスさせたいときに便利です。この方法を使用することで、フロントエンドとバックエンドの両方から一貫した方法でS3(この場合はminio)にアクセスすることができます。

Discussion