[Перемещено и отредактировано вниз по адресу https://stackoverflow.com/questions/21933955, поскольку оно считалось слишком похожим на sysadmin для StackOverflow.]
У меня есть докер-контейнер с запущенным Nginx, который ссылается на другой докер-контейнер. Имя хоста и IP-адрес второго контейнера загружаются в контейнер Nginx как переменные среды при запуске, но до этого не были известны (это динамически). Я хочу, чтобы мои nginx.conf
использовали эти значения - например,
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
Как я могу получить переменные окружения в конфигурации Nginx при запуске?
РЕДАКТИРОВАТЬ 1
Это весь файл, после предложенного ответа ниже:
env APP_WEB_1_PORT_5000_TCP_ADDR;
# Nginx host configuration for django_app
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
location / {
proxy_pass http://gunicorn;
}
}
Перезагрузка nginx, затем ошибки:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
РЕДАКТИРОВАТЬ 2: больше деталей
Текущие переменные среды
root@87ede56e0b11:/# env | grep APP_WEB_1
APP_WEB_1_NAME=/furious_turing/app_web_1
APP_WEB_1_PORT=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP_PROTO=tcp
APP_WEB_1_PORT_5000_TCP_PORT=5000
APP_WEB_1_PORT_5000_TCP_ADDR=172.17.0.63
Root nginx.conf:
root@87ede56e0b11:/# head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env APP_WEB_1_PORT_5000_TCP_ADDR;
Конфигурация сайта nginx:
root@87ede56e0b11:/# head /etc/nginx/sites-available/default
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
Перезагрузите конфигурацию nginx:
root@87ede56e0b11:/# nginx -s reload
nginx: [emerg] directive "server" is not terminated by ";" in /etc/nginx/sites-enabled/default:3
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
наserver app_web_1:5000;
app_web_1
его, он получит новый IP-адрес, поэтому вам также необходимо перезапустить ваш контейнер nginx. Docker перезапустит его с обновленным,/etc/hosts
так что вам не нужно будет изменять конфигурационные файлы nginx.Ответы:
Из официального файла докера Nginx:
Обновить:
Но вы знаете, что это вызвало его переменные Nginx, как это:
поврежден:
Итак, чтобы предотвратить это, я использую этот трюк:
У меня есть скрипт для запуска Nginx, который используется в
docker-compose
файле как опция команды для сервера Nginx, я назвал егоrun_nginx.sh
:И из-за определенной новой
DOLLAR
переменной вrun_nginx.sh
скрипте, теперь содержимое моегоnginx.conf.template
файла для самой переменной Nginx выглядит так:И для моей определенной переменной это так:
Также здесь есть мой реальный пример использования для этого.
источник
proxy_set_header Host $http_host;
command: /bin/bash -c "envsubst '$VAR1 $VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
работает для меня, потому что я знаю, как они называются ...$
, должно бытьcommand: /bin/bash -c "envsubst '\$VAR1 \$VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
CMD ["/bin/sh","-c", "if [ -n \"${SOME_ENV}\" ]; then echo envsubst '${SOME_ENV}' with ${SOME_ENV} && envsubst '${SOME_ENV}' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf; fi ; nginx -g 'daemon off;'"]
Делать это с Lua значительно проще, чем кажется:
Я нашел это здесь:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Редактировать:
Очевидно, для этого требуется установить модуль lua: https://github.com/openresty/lua-nginx-module
Изменить 2:
Обратите внимание, что при таком подходе вы должны определить
env
переменную в Nginx:Вы должны сделать это в контексте верхнего уровня,
nginx.conf
иначе это не сработает! Не в блоке сервера или в конфигурации какого-либо сайта/etc/nginx/sites-available
, потому что он включенnginx.conf
вhttp
контекст (который не является контекстом верхнего уровня).Также обратите внимание, что при таком подходе, если вы попытаетесь сделать перенаправление, например:
это не сработает
И если вы дадите ему отдельное имя переменной:
nginx не будет его интерпретировать и перенаправит вас на
https://%24server_name_from_env/
.источник
env NGINX_SERVERNAME
где-нибудь в вашем nginx.conf.set_by_lua
переменную во включенном файле конфигурации, в то время какenv MY_VAR
объявление было в основном nginx.conf, как предложено. Какой позор, это было бы самое чистое решение!envsubst
? Я полагаю, что вы не должны запускатьenvsubstr
команду перед запуском сервера, а дело в том, что вам нужно установить модуль lua? Интересно, есть ли какие-либо последствия для безопасности любого из этих подходов?envsubst
и которые в моем случаеenv
директива должна быть выполнена "в контексте верхнего уровня в nginx.conf", что именно означает "nginx.conf"? Где этот файл должен быть?Я написал что-то, что может или не может быть полезным: https://github.com/yawn/envplate
Он встраивает файлы конфигурации со ссылками $ {key} на переменные среды, при необходимости создавая резервные копии и записывая, что он делает. Он написан на Go, и полученный статический двоичный файл можно просто загрузить с вкладки релиза для Linux и MacOS.
Он также может выполнять процессы exec (), заменять значения по умолчанию, протоколировать журналы и имеет разумную семантику сбоев.
источник
Официальное изображение nginx рекомендует использовать
envsubst
, но, как отмечают другие, оно заменит также$host
и другие переменные, что нежелательно. Но, к счастью,envsubst
может принимать в качестве параметра имена переменных для замены .Чтобы избежать очень сложного параметра команды для контейнера (как в связанном примере), вы можете написать сценарий точки входа Docker, который будет заполнять переменные среды перед выполнением команды. Сценарий точки входа также является хорошим местом для проверки параметров и установки значений по умолчанию.
Ниже приведен пример Nginx контейнера , который принимает
API_HOST
иAPI_PORT
параметры , как переменные среды.Nginx-default.conf.template
docker-entrypoint.sh
Dockerfile
источник
Что я сделал, так это использовал erb !
- после использования erb
Это используется в Cloudfoundry staticfile-buildpack
Пример конфигурации nginx: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
В твоем случае
стали
источник
Обращаясь к ответу об использовании erb, это можно сделать, как показано ниже.
Запишите файл конфигурации NGINX в виде файла erb, содержащего переменную среды, и оцените его с помощью команды erb в обычном файле конфигурации.
Внутри серверного блока файла nginx.conf.erb может быть
источник
erb
выполнить подстановку переменных ... после того, как контейнер был запущен, верно?) -erb
это правильно с Ruby: stuartellis.name/articles/erbЯ знаю, что это старый вопрос, но на случай, если кто-то наткнется на это (как у меня сейчас), есть гораздо лучший способ сделать это. Поскольку docker вставляет псевдоним связанного контейнера в / etc / hosts, вы можете просто сделать
Предполагая, что ваша команда Docker что-то вроде
docker run --link othercontainer:docker_link_alias nginx_container
.источник
Другой вариант ... Я только что нашел этот инструмент сегодня: https://github.com/kreuzwerker/envplate ... Написанный на Go, его можно очень легко установить. Используя это довольно просто. Хотя вам нужно будет разместить переменные шаблона в вашем nginx.conf.
Например,
${SOME_ENV_VAR}
будет заменено при вызовеep
команды envplate для файла. Поэтому, если ваш Dockerfile не сможет получить этот двоичный файл или он по какой-то причине не запустится, он сделает вашу конфигурацию недействительной. Небольшое замечание по сравнению с другими решениями, такими как использование расширений perl или lua.Мне очень нравится, как вы можете установить значения по умолчанию, когда переменная окружения не установлена. Ex.
${SOME_ENV_VAR:default-value}
(и вы можете избежать значений). Опять же, envplate должен все еще успешно работать.Одно из преимуществ использования такого подхода заключается в том, что вы не получаете образ Docker, который больше необходимого, потому что вы прекратили устанавливать все виды дополнительных модулей, которые вам не нужны в противном случае. Это также может быть проще, чем использование sed, если все начинает усложняться, и оно содержит функциональные значения по умолчанию.
источник
Я делаю это с помощью сценария оболочки.
Вот шаблон nginx:
И скрипт для замены переменных окружения находится здесь:
источник
Другая возможность - использовать команду «sed» с регулярными выражениями, тогда вам вообще не придется возиться с файлами конфигурации! Таким образом, вы можете использовать ваши конфигурационные файлы как обычно, но когда вы запустите docker, он поменяет значения с переменными env. Ничто из этого «не добавляет строку текста в ваши файлы конфигурации, которые вы ищете и заменяете».
Вы можете создать файл run.sh со значениями замены, используя переменные среды.
Чтобы изменить «7s» в этой строке:
Команда Sed, использующая client_body_timeout в качестве строки поиска и $ client_body_timeout в качестве переменной env замены:
Скопируйте / вставьте эту строку для каждого параметра, который вы хотите установить, и измените client_body_timeout с параметром config и $ client_body_timeout с переменной env, с которой он связан. Используйте с существующим конфигурационным файлом, и он будет просто работать.
источник
Вот пример использования
sed
подхода, не обязательно лучшего, но он может быть полезен для некоторых. Сначала добавьте пользовательское ключевое слово для замены в файле conf. Во-вторых, создайте dockerfile, который объявляетENV
переменную, а затем a,CMD
который используетсяsed
для редактирования конфигурации, прежде чем явно запускать nginx.Итак, предположим, что ваш default.conf содержит это с ключевым словом
docker_host
:И напишите свой Dockerfile, похожий на:
Затем создайте образ и запустите контейнер, используя
источник
Правильный способ сделать это с Луа, так как ответ выше является устаревшим:
источник
Вы должны иметь возможность делать то, что вы хотите с шаблонами Dockerize .
источник