概要

ホストOS上でnginxやpostgresqlが動いていて、内側にdockerコンテナがある。

  • ホストとdockerコンテナの間で通信したい
  • ホストの外側からはアクセスできないようにしたい。

いままでdocker0ブリッジのアドレスにlistenさせていたが、postgresqlとdocker の開始順序を調整するのが systemdだとダルい。

今回の記事ではdummyブリッジを作ってホストやdockerコンテナからそのアドレスにlistenするよう設定する。

  • このアドレスはホストの外側からアクセスできない。
  • dockerブリッジと異なり通常のLANとほぼ同タイミングで設定される。サービス起動順序を調停しなくてもlistenできる。
  • DB等のクライアント接続のリトライが不適切な場合はコンテナ側に一工夫する必要があるが、それは難しくない。

手順

dummyブリッジを作る

IPアドレスとホスト名を決める。 今回は 192.168.3.1 din2 にしよう。この名前に意味はない。

/etc/hosts を編集

以下の行を追記する。

192.168.3.1 din2

/etc/netplan/02-dummy.yaml を作成

既存ファイルとぶつからないようにファイル名先頭の番号を調整すること。 内容はこんな感じだ。

network:
  version: 2
  renderer: networkd
  bridges:
    dummy0:
      dhcp4: no
      dhcp6: no
      accept-ra: no
      interfaces: [ ]
      addresses:
        - 192.168.3.1/32

設定反映、動作確認

netplan apply
ifconfig |grep 192.168.3.1
ping din2

各サービスの対応

listenする側

このブリッジは起動時にdockerやpostgresより先に作られるので、dockerもpostgresも起動順序に関係なくlistenできる。 たとえばdocker-composeを使ってるなら、コンテナのports指定に “192.168.3.1:1234:8080” とか書くと露出ポート 192.168.3.1:1234 からコンテナの8080ポートへの中継が行われる。なお残念ながらdocker-compose.ymlのポート指定にはホスト名を書けず、IPアドレスを生で指定するしかない。

アクセスする側

たとえばホスト側のpostgresがdummyブリッジにlistenして、dockerコンテナが起動時にpostgresにアクセスするような場合。postgresとdockerの起動順序の調停がイヤだというのが話の出発点なので、dockerコンテナ側はpostgresがまだ準備できていない段階で起動する場合がある。 コンテナ側がリトライを適切に行なってくれればよいが、そうでない場合はdocker-composeに一工夫入れることになる。


docker-composeに一工夫

docker-compose.yml に次のようなサービスを追加する。 ncコマンドの引数にホスト側のサービスのホストとポートを指定する。

  delay:
    # ubuntu 18.04未満ではncコマンドがプリインストールされている
    image: ubuntu:14.04
    command: >
      /bin/bash -c "
        while ! nc -z din2 5431;
        do
          echo sleeping;
          sleep 1;
        done;
        echo Connected!;
        sleep 10;
      "

続いて、待機させたいサービスに depends_on 指定を追加する。

  sidekiq:
    build: .
    …
    depends_on:
     - redis
     - delay       <==== これ

delayコンテナだけ動作確認してみよう。

$ docker-compose up delay
Pulling delay (ubuntu:14.04)...
14.04: Pulling from library/ubuntu
2e6e20c8e2e6: Pull complete
0551a797c01d: Pull complete
512123a864da: Pull complete
Digest: sha256:43cb19408de1e0ecf3ba5b5372ec98978963d6d0be42d0ad825e77a3bd16b5f7
Status: Downloaded newer image for ubuntu:14.04
Recreating m2j_delay_1 ... done
Attaching to m2j_delay_1
delay_1      | Connected!
m2j_delay_1 exited with code 0

次は普通に起動。

$docker-compose up -d
$docker-compose logs

delayコンテナは起動しっぱなしではなく、スクリプトが終わると終了してしまう。無駄なメモリ消費はない。依存コンテナの実行は継続される。

これでOS再起動時にpostgresqlやpgbouncerの起動を待ってから残りのコンテナを起動できるようになった。ホストOSの設定を特に変更しないのが利点だ。