Docker 19.03.0 のネットワークパラメータにより、ランチャーの再構築が失敗

Docker がバージョン 19.03.0 をロールアウトしたことで、Discourse ランチャーはインスタンスを再構築後に起動できなくなり、以下のメッセージが表示されるようになりました:

/usr/bin/docker: --network は有効な MAC アドレスではありません。
'/usr/bin/docker run --help' を参照してください。

実行されたコマンドは以下の通りです(セキュリティ上の理由で一部を変更しています):

+ /usr/bin/docker run --shm-size=512m -d --restart=always -e LANG=en_US.UTF-8 -e RAILS_ENV=production -e UNICORN_WORKERS=2 -e UNICORN_SIDEKIQS=1 -e RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 -e RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 -e RUBY_GC_HEAP_INIT_SLOTS=400000 -e RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 -e DISCOURSE_DB_SOCKET=/var/run/postgresql -e DISCOURSE_DB_HOST= -e DISCOURSE_DB_PORT= -e DISCOURSE_HOSTNAME=discourse.mydomain.com -e VIRTUAL_HOST=discourse.mydomain.com -e DISCOURSE_DEVELOPER_EMAILS=admin@mydomain.com -e DISCOURSE_SMTP_ADDRESS=mail.mydomain.com -e DISCOURSE_SMTP_PORT=587 -e DISCOURSE_SMTP_USER_NAME=discourse@mydomain.com -e DISCOURSE_SMTP_PASSWORD=MySuperDuperPass -h vps-discourse -e DOCKER_HOST_IP=172.17.0.1 --name discourse -t --expose 80 --mac-address --network reverse-proxy --network reverse-proxy local_discourse/discourse /sbin/boot
/usr/bin/docker: --network は有効な MAC アドレスではありません。
'/usr/bin/docker run --help' を参照してください。

これは、リバースプロキシ(reverse-proxy という名前のネットワーク上で実行中)の背後で使用しています。これまで正常に動作していましたが、今日から問題が発生しました。どうやら、提供されていない MAC アドレスの値を期待しているようです。

見てみましょう..

root@endoffice-a:/var/discourse# docker --version
Docker version 19.03.0, build aeac949

先ほど ./launcher rebuild app を実行しましたが、正常に完了しました:

+ /usr/bin/docker run --shm-size=512m -d --restart=always -e LANG=en_US.UTF-8 -e RAILS_ENV=production -e UNICORN_WORKERS=8 -e UNICORN_SIDEKIQS=1 -e RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 -e RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 -e RUBY_GC_HEAP_INIT_SLOTS=400000 -e RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 -e DISCOURSE_DB_SOCKET=/var/run/postgresql -e DISCOURSE_DB_HOST= -e DISCOURSE_DB_PORT= -e LETSENCRYPT_DIR=/shared/letsencrypt -e UNICORN_SIDEKIQ_MAX_RSS=1000 -e DISCOURSE_HOSTNAME=discourse.codinghorror.com -e DISCOURSE_DEVELOPER_EMAILS=jatwood@codinghorror.com -e DISCOURSE_SMTP_ADDRESS=smtp.mailgun.org -e DISCOURSE_SMTP_PORT=587 -e DISCOURSE_SMTP_USER_NAME={redacted} -e DISCOURSE_SMTP_PASSWORD={redacted} -e LETSENCRYPT_ACCOUNT_EMAIL={redacted} -e DISCOURSE_CDN_URL=https://discourse-cdn.codinghorror.com -h endoffice-a-app -e DOCKER_HOST_IP=172.17.0.1 --name app -t -p 80:80 -p 443:443 -v /var/discourse/shared/standalone:/shared -v /var/discourse/shared/standalone/log/var-log:/var/log --mac-address 02:72:e3:65:d5:32 local_discourse/app /sbin/boot

--mac-address オプションが表示され値が設定されていますが、--network 行はあなたの環境固有の設定であり、標準的なスタンドアロン Discourse インストールとは異なります。

@codinghorror それは素晴らしいことですが、もし Discourse が想定している運用方法が「標準的なスタンドアロンインストール」だけなら、なぜ ./containers 内で yml コンテナ設定のサポートを提供し、さらに ./samples にその例を含めるのでしょうか?私が使用したファイルには運用に関する完全なコメントが記載されており、特にこの部分がそうです:

# any extra arguments for Docker?
# docker_args:

私が使用しているのはこれだけです:

docker_args: "--network reverse-proxy"

これもまた、1 年間問題なく動作していました。つまり、明らかに何かが変化しました。対立的になろうとしているわけではないこと(助けを求めているのだから、そんなことをするのは少しばかげています)はおわかりください。しかし、私は Discourse のサンプルで提供されているオプションを使用しているという点を強調したいのです。

もしかすると、その MAC アドレスがどのように生成されるかを理解すれば、環境変更に関する問題のヒントが見つかるかもしれません。それが私の期待です。

launcher で以下のような記述があります:

     if [ -z "$SKIP_MAC_ADDRESS" ] ; then
      mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
     fi

これを分解して、解決策を見つけられるか確認します。

更新:これを見てみると、--skip-mac-address を使用できることに気づきました。これを実行するとインスタンスが正常に起動するため、MAC アドレスを算出するプロセスに問題があるようです。

まとめると、ビルド操作はどのような状況でも成功しますが、ビルド操作(./launcher rebuild myinstance)の最終ステップであるコンテナの起動が、何らかの理由で MAC アドレスが設定されていないために失敗します。

ただし、その後で単に ./launcher start myinstance を実行すれば正常に起動し、MAC アドレスも存在します。不思議なことです。

私も同じ問題に直面しています。
@codinghorror 再現手順と、この回帰現象を修正するための手がかりを以下に示します。

再現手順:

  1. コンテナの設定 (app) に以下を設定:
    docker_args: "--network reverse-proxy"
  2. 再構築
    ./launcher rebuild app
  3. エラーを確認
    /usr/bin/docker: --network は有効な MAC アドレスではありません

これは、コミット bfc79e7 (GitHub - discourse/discourse_docker: A Docker image for Discourse · GitHub) によって導入されたバグです。
merge_user_argsset_template_info によって呼び出されますが、set_template_info は再構築時に 2 回呼び出されます(run_runrun_bootstrap)。
そのため、user_args$user_args $docker_args になるはずが、$user_args $docker_args $docker_args となってしまいます。

Docker は同じネットワークを複数回設定することを許可しません。
docker: network "reverse-proxy" が複数回指定されています

このコミットをロールバックするか、merge_user_args を冪等なものにしていただくようお願いいたします。

名探偵のような調査、ありがとう! :male_detective: @saj さん、そのコミットは @deargle さんと共署名されたようですね。

以下のパッチがあります。

このパッチを適用し、コンテナ定義で docker_args キーを設定すると、最終的な docker run 引数ベクトルは次のようになります。

/usr/bin/docker run --shm-size=512m -d --restart=always -e ... -h saj-launcher-testing-app -e DOCKER_HOST_IP=172.17.0.1 --name app -t -p 80:80 -p 443:443 -v /var/discourse/shared/standalone:/shared -v /var/discourse/shared/standalone/log/var-log:/var/log --mac-address 02:07:fa:c6:c4:82 --network foonet local_discourse/app /sbin/boot

すごい!夢じゃなかったんですね。調査してくださってありがとうございます。