#docker #nginx #docker-compose
Вопрос:
(Похоже на вчерашнее сообщение без ответа, но с тех пор я увеличил масштаб причины моей проблемы, поэтому повторно опубликую здесь меньше текста и удалю вчерашнее сообщение)
С помощью изображения nginx можно передавать глобальные переменные env. Документация. По ссылке есть раздел » Использование переменных среды в конфигурации nginx (новое в 1.19)». При запуске этого контейнера функциональность, описанная выше в отношении глобальных переменных, действительно работает должным образом.
Если я войду в запущенный контейнер, я увижу скрипт на корневом уровне системы каталогов docker-entrypoint.sh
. Из исследований следует, что метод, который nginx docker использует для передачи глобальных переменных, основан на том, что этот сценарий запускается при запуске контейнера и что это автоматический процесс.
Проблема в том, что у моего докера-сочинителя есть команда command: "/bin/sh -c 'while :; do sleep 6h amp; wait $${!}; nginx -s reload; done amp; nginx -g "daemon off;"'"
. Когда я включаю эту команду и запускаю ее, она нарушает функциональность глобальных переменных. От выполнения некоторого поиска добавление команды нарушает любые сценарии точек входа? Похоже, я могу использовать функциональность глобальной переменной только в том случае, если я не добавлю никаких команд в свой docker-compose с момента его остановки docker-entrypoint.sh от того, что им управляли.
Есть ли «правильный» способ обойти это?
Работает — глобальные переменные передаются в nginx:
version: "3.5"
networks:
collabora:
services:
nginx:
image: nginx
depends_on:
- certbot
- collabora
volumes:
- ./data/nginx/templates:/etc/nginx/templates
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
env_file: .env
networks:
- collabora
Не работает, глобальные переменные не передаются, и шаблон default.conf-это все, что я получаю:
version: "3.5"
networks:
collabora:
services:
nginx:
image: nginx
depends_on:
- certbot
- collabora
volumes:
- ./data/nginx/templates:/etc/nginx/templates
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
env_file: .env
command: "/bin/sh -c 'while :; do sleep 6h amp; wait ${!}; nginx -s reload; done amp; nginx -g "daemon off;"'"
networks:
- collabora
Комментарии:
1. Можете ли вы удалить
command:
и вручную перезапустить контейнер , когда вам это необходимо? Или используйте задание cron на хосте, чтобы перезапустить его, если ему нужно перезапустить по расписанию?
Ответ №1:
Взгляните на сценарий точки входа внутри контейнера, в частности на if
инструкцию, которая защищает большую часть кода:
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
...
fi
Шаблоны и другие сценарии точек входа будут выполняться только в том случае, если $1
это nginx
или nginx-debug
. Это не относится к вашему файлу Dockefile, в котором $1
было бы /bin/sh
.
Самым простым вариантом было бы заменить сценарий точки входа модифицированной версией, которая запускает сценарии точки входа безоговорочно. Есть несколько способов сделать это, но самый простой, вероятно,:
- Создайте пользовательский
docker-entrypoint.sh
сценарий в своем локальном каталоге (убедитесь, что он исполняемый). - Установите это поверх стандартной версии в вашем
docker-compose.yml
:version: "3.5" networks: collabora: services: nginx: image: nginx depends_on: - certbot - collabora volumes: # Here is where we orverride the entrypoint script. - ./data/docker-entrypoint.sh:/docker-entrypoint.sh - ./data/nginx/templates:/etc/nginx/templates - ./data/certbot/conf:/etc/letsencrypt - ./data/certbot/www:/var/www/certbot ports: - "80:80" - "443:443" env_file: .env command: "/bin/sh -c 'while :; do sleep 6h amp; wait ${!}; nginx -s reload; done amp; nginx -g "daemon off;"'" networks: - collabora
Удаление if
заявления о защите дает нам:
#!/bin/sh
# vim:sw=4:ts=4:et
set -e
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
exec 3>amp;1
else
exec 3>/dev/null
fi
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
echo >amp;3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
echo >amp;3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
case "$f" in
*.sh)
if [ -x "$f" ]; then
echo >amp;3 "$0: Launching $f";
"$f"
else
# warn on shell scripts without exec bit
echo >amp;3 "$0: Ignoring $f, not executable";
fi
;;
*) echo >amp;3 "$0: Ignoring $f";;
esac
done
echo >amp;3 "$0: Configuration complete; ready for start up"
else
echo >amp;3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
fi
exec "$@"
Комментарии:
1. Я не совсем все здесь понимаю, но вы хотите сказать, что мне просто нужно скопировать существующий
docker-entrypoint.sh
в свой каталог, а затем создать том с ним как часть моего сочинения? Хорошо, я попробую это сейчас2. …не забудьте, конечно, изменить его, чтобы удалить это утверждение if. И, пожалуйста, дайте мне знать, если вы хотите, чтобы я что-то прояснил в этом ответе.
3. Что, если утверждение, похоже, в значительной степени соответствует всему сценарию, нет? Я в замешательстве! Не могли бы вы поделиться тем, как именно
docker-entrypoint.sh
должен выглядеть новый измененный файл?4. Я обновил ответ, чтобы показать измененный сценарий.
5. Могу я предложить вам другое потенциальное решение? Кто-то предложил добавить скрипт в контейнер,
docker-entrypoint.d
и тогда мне не пришлось бы вручную корректироватьdocker-entrypoint.sh
приведенный выше сценарий. Я попробовал это, я добавил командную часть моего docker-compose выше (/bin/sh -c 'while :; do sleep 6h amp; wait...
) в файлtest.sh
, а затем в раздел тома/test.sh:/docker-entrypoint.d/test.sh
. Это «почти» работает. Служба запускается, и в контейнере/etc/nginx/conf.d
содержится правильно преобразованный файл app.conf с моими глобальными переменными, замененными на но …