🍎

複数の並行開発におけるDocker Composeのポート競合を何とかする(Mac)

に公開

とにかく競合しがちな3000と8000

複数の開発のお仕事を頂いて対応していると、このポート競合に悩まされてしまうということがよくあります。まあその時立ち上げるcomposeの環境を一つだけに限定すればいい、という話ではあるのですが、AIコーディングが常用化された今の環境化では平行に開発できないと辛いというのが実情なわけです。

大体の現場は、並行で開発をしないといけないタイプのエンジニアのことは特に考慮してくれません。故に3000番ポートというある意味Web開発デファクトみたいなポートはくっっっっっそ被ります。8000番も同じくよく使われるものなので、これをまあ被る。いちいちcompose.yamlのポートを手動で書き換えれば一応解決はしますが、変更をgitのステージ状態のまま持ちたくないというのが心情ですね。間違ってコミットする事故も生まれますし。

Mac限定にはなりますが、ループバックアドレスを増やして、それを使う設定に変える。と比較的かんたんにこの問題を解決させることができます。

ループバックアドレスとはなにか

普段開発で使っている、127.0.0.1〜127.255.255.254 の範囲のものをループバックアドレスとよぶ特殊なアドレスで、すべてlocalhostに対しての通信を示します。そしてポート番号の競合が起きるのは、1つのアドレスに対して同じポートを指定した場合 に発生します。つまり各プロジェクトのcomposeのport設定をループバックアドレス込みの設定に変えてあげることで、実質的に127.0.0.0/8の、1677万の3000番ポートが同時に使えるようになるわけです。つよすぎ。

これだけあればどれだけ平行にAIコーディングしていてもまるで困ることはありません。とってもうれしいね。

設定

まずループバックアドレスはMac環境下では下記のコマンドで追加することができます。Mac以外でも概念自体はあるはずなので、WinやLinuxの人は調べてみてください。

sudo ifconfig lo0 alias 127.0.0.x up

lo0というのがループバックアドレスを示すものになります。ifconfigを叩くと下記のように情報が出力されます

$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
        options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
        inet 127.0.0.1 netmask 0xff000000
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
        nd6 options=201<PERFORMNUD,DAD>
....

使いたい数だけ、このaliasを設定していく形になります。自分はひとまず適当に255分を作ってます。

# 127.0.0.1は使われているので2から作る
for ((i=2;i<256;i++))
do
  sudo ifconfig lo0 alias 127.0.0.$i up
done

そして、設定したループバックアドレスを、各環境のcompose.yamlに適用します。ただそのまま既存のcompose.yamlに適用すると、gitのステージ状態になって誤コミットのもとになります。とてもつらい。それを回避する手段として、compose.override.yamlを使います。
https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/

docker composeでは特に指定しなくても自動でcompose.override.yamlを読んでくれます。なのでループバックアドレス付きポート指定はこちらに記載して、このファイル自体をgit ignoreしちゃえばいい感じになります。

services:
  contaner1:
    # portsをリスト形式で記載するとそれは既存設定へに追加になるので、
    # !overrideを挟んで上書きすること
    ports: !override
      - "127.0.0.2:3000:3000"

  db:
    ports: !override
      # そもそもホストにバインドしないという選択肢もある
      # DBクライアント等で接続する場合は無理だが...
      - 5432
...

このとき注意すべきは、この環境に接続するときのURLが127.0.0.2:3000となること。localhostのままだとつながりません。ブラウザで動作確認したい、とかフロントからAPI接続したい!みたいな場合も、127.0.0.2:3000と明確に指定しなければなりません。なので各種接続先の環境変数とかも差し替える必要があります。と、なるとIPアドレスで扱うのはしんどくなってきます。人間そんなもんです。なので、/etc/hosts にエイリアスとして任意の名前を設定しちゃいましょう。

127.0.0.2 project1

これで、ブラウザやその他でアクセスするときはproject1:3000でつながるようになります。ただしcompose.yamlではIPアドレスの指定が要求されますので、ここには間違ってエイリアスを指定しないように。

Discussion