Сборка лаунчера завершается ошибкой с Docker 19.03.0 из-за параметра сети Docker

С выходом 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 в режиме standalone.

@codinghorror Всё это прекрасно, но если стандартная установка в автономном режиме — единственный способ, которым должен работать Discourse, зачем тогда предоставлять поддержку конфигурации контейнеров через yml в папке ./containers и включать примеры этого в ./samples? Файл, который я использовал, полностью прокомментирован с инструкциями по эксплуатации, в частности этот участок:

# любые дополнительные аргументы для Docker?
# docker_args:

Единственное, что я использую:

docker_args: "--network reverse-proxy"

Что, как и прежде, отлично работало уже год. Очевидно, что что-то изменилось. Пожалуйста, поймите: я не пытаюсь быть конфронтационным (это было бы глупо, раз я прошу о помощи), но я действительно хочу подчеркнуть, что использую опции, которые предоставляются в примерах 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 is некорректный MAC-адрес

Это баг, внесенный коммитом bfc79e7 (GitHub - discourse/discourse_docker: A Docker image for Discourse · GitHub).
Функция merge_user_args вызывается из set_template_info, но set_template_info вызывается дважды при пересборке (в run_run и run_bootstrap).
Поэтому вместо того чтобы user_args равнялось $user_args $docker_args, у нас получается $user_args $docker_args $docker_args.

Docker не позволяет настраивать одну и ту же сеть несколько раз:
docker: сеть "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

Круто! Значит, я не грезил. Спасибо вам за то, что разобрались в этом.