[Przekazano i poddano edycji z https://stackoverflow.com/questions/21933955, ponieważ uznano go za zbyt podobny do sysadmin dla StackOverflow.]
Mam kontener dokerów z systemem Nginx, który łączy się z innym kontenerem dokowania. Nazwa hosta i adres IP drugiego kontenera są ładowane do kontenera Nginx jako zmienne środowiskowe podczas uruchamiania, ale przedtem nie są znane (jest dynamiczne). Chcę nginx.conf
używać tych wartości - np
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
Jak mogę wprowadzić zmienne środowiskowe do konfiguracji Nginx podczas uruchamiania?
EDYCJA 1
To jest cały plik, po sugerowanej odpowiedzi poniżej:
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;
}
}
Przeładowanie nginx następnie błędy:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
EDYCJA 2: więcej szczegółów
Bieżące zmienne środowiskowe
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
Zrootuj 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;
Konfiguracja strony 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;
Załaduj ponownie konfigurację 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;
zserver app_web_1:5000;
app_web_1
, otrzyma nowy adres IP, więc musisz zrestartować również swój kontener nginx. Docker uruchomiłby go ponownie po zaktualizowaniu/etc/hosts
, abyś nie musiał zmieniać plików konfiguracyjnych nginx.Odpowiedzi:
Z oficjalnego pliku dokera Nginx:
Aktualizacja:
Ale wiesz, że spowodowało to takie zmienne Nginx:
uszkodzony do:
Aby temu zapobiec, używam tej sztuczki:
Mam skrypt do uruchomienia Nginx, użyty w
docker-compose
pliku jako opcja polecenia dla serwera Nginx, nazwałem gorun_nginx.sh
:Z powodu zdefiniowanej nowej
DOLLAR
zmiennej wrun_nginx.sh
skrypcie zawartość mojegonginx.conf.template
pliku dla samej zmiennej Nginx wygląda następująco:A dla mojej zdefiniowanej zmiennej jest to tak:
Również tutaj jest mój prawdziwy przypadek użycia.
źródło
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;'"
działa dla mnie b / c Wiem, jak się je nazywa ...$
, powinno być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;'"]
Robienie tego z Luą jest znacznie łatwiejsze niż się wydaje:
Znalazłem to tutaj:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Edytować:
Najwyraźniej wymaga to instalacji modułu lua: https://github.com/openresty/lua-nginx-module
Edycja 2:
Zauważ, że przy takim podejściu musisz zdefiniować
env
zmienną w Nginx:Musisz to zrobić w kontekście najwyższego poziomu, w
nginx.conf
przeciwnym razie nie zadziała! Nie w bloku serwera ani w konfiguracji niektórych witryn/etc/nginx/sites-available
, ponieważ jest on uwzględnionynginx.conf
whttp
kontekście (który nie jest kontekstem najwyższego poziomu).Pamiętaj również, że przy takim podejściu, jeśli próbujesz dokonać przekierowania, np .:
to też nie zadziała:
A jeśli nadasz jej osobną nazwę zmiennej:
nginx nie zinterpretuje tego i przekieruje cię do
https://%24server_name_from_env/
.źródło
env NGINX_SERVERNAME
gdzieś w swoim pliku nginx.conf.set_by_lua
zmiennej w dołączonym pliku konfiguracyjnym, podczas gdyenv MY_VAR
deklaracja znajdowała się w głównym pliku nginx.conf, jak sugerowano. Szkoda, że byłoby to najczystsze rozwiązanie!envsubst
? Myślę, że pro jest to, że nie musisz uruchamiaćenvsubstr
polecenia przed uruchomieniem serwera, a wada polega na tym, że musisz zainstalować moduł lua? Zastanawiam się, czy są jakieś konsekwencje dla bezpieczeństwa w obu podejściach?envsubst
i które w moim przypadku są nie doNapisałem coś, co może, ale nie musi być pomocne: https://github.com/yawn/envplate
Inline edytuje pliki konfiguracyjne z odwołaniami $ {key} do zmiennych środowiskowych, opcjonalnie tworząc kopie zapasowe / rejestrując, co robi. Jest napisany w Go, a wynikowy statyczny plik binarny można po prostu pobrać z karty wersji dla systemów Linux i MacOS.
Może także wykonywać procesy (), zastępować wartości domyślne, logować i ma sensowną semantykę awarii.
źródło
Oficjalny obraz nginx zaleca używanie
envsubst
, ale jak zauważyli inni , zastąpi także$host
inne zmienne, co nie jest pożądane. Ale na szczęście jako parametrenvsubst
można przyjąć nazwy zmiennych do zamiany .Aby uniknąć bardzo złożonego parametru polecenia dla kontenera (jak w przykładzie z linkiem), możesz napisać skrypt punktu wejścia Docker, który wypełni zmienne środowiskowe przed wykonaniem polecenia. Skrypt punktu wejścia jest również dobrym miejscem do sprawdzania poprawności parametrów i ustawiania wartości domyślnych.
Oto przykład pojemnika nginx który pobiera
API_HOST
iAPI_PORT
parametry zmienne środowiska.nginx-default.conf.template
docker-entrypoint.sh
Plik Docker
źródło
To, co zrobiłem, to użycie erbu !
- Po użyciu erb
Jest to używane w pakiecie staticfile-buildpack Cloudfoundry
Przykładowa konfiguracja nginx: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
W Twoim przypadku
stają się
źródło
Odnosząc się do odpowiedzi dotyczącej używania erb, można to zrobić jak poniżej.
Zapisz plik konfiguracyjny NGINX jako plik erb zawierający zmienną środowiskową i oceń go za pomocą polecenia erb do normalnego pliku konfiguracyjnego.
Wewnątrz bloku serwera pliku nginx.conf.erb może być
źródło
erb
można dokonać podstawienia zmiennych ... po uruchomieniu kontenera, prawda?) -erb
czy te ruby są prawidłowe: stuartellis.name/articles/erbWiem, że to stare pytanie, ale na wypadek, gdyby ktoś natknął się na to (tak jak teraz), jest na to znacznie lepszy sposób. Ponieważ okno dokowane wstawia połączony alias kontenera do / etc / hosts, możesz po prostu to zrobić
zakładając, że polecenie dokera jest podobne
docker run --link othercontainer:docker_link_alias nginx_container
.źródło
Inna opcja ... Właśnie znalazłem to narzędzie dzisiaj: https://github.com/kreuzwerker/envplate ... Napisane w Go, można je bardzo łatwo zainstalować. Korzystanie z niego jest dość proste. Chociaż będziesz musiał umieścić zmienne szablonu w swoim pliku nginx.conf.
Na przykład
${SOME_ENV_VAR}
zostanie zastąpiony, gdy w pliku zostanie wywołaneep
polecenie envplate . Więc jeśli plik Docker nie otrzyma tego pliku binarnego lub jeśli z jakiegoś powodu nie zostanie uruchomiony, spowoduje to, że twoja konfiguracja będzie nieważna. Tylko mała uwaga w porównaniu do innych rozwiązań, takich jak używanie rozszerzeń perla lub lua.Bardzo podoba mi się to, jak można ustawić wartości domyślne, gdy zmienna środowiskowa nie jest ustawiona. Dawny.
${SOME_ENV_VAR:default-value}
(i możesz uciec od wartości). Znów envplate musi nadal działać poprawnie.Jedną z zalet takiego podejścia jest to, że nie kończy się obrazem Dockera, który jest większy niż to konieczne, ponieważ odszedłeś instalując wszelkiego rodzaju dodatkowe moduły, których inaczej nie potrzebujesz. Może być również łatwiejsze niż używanie sed, jeśli sprawy zaczynają się komplikować i zawiera tę funkcję wartości domyślnej.
źródło
Osiągam to za pomocą skryptu powłoki.
Oto szablon nginx:
Skrypt zastępujący zmienne środowiskowe znajduje się tutaj:
źródło
Inną możliwością jest użycie polecenia „sed” z wyrażeniami regularnymi, wtedy nie będziesz musiał w ogóle zadzierać z plikami konfiguracyjnymi! W ten sposób możesz normalnie korzystać z plików konfiguracyjnych, ale po uruchomieniu dokera zmieni on wartości na zmienne env. Nic z tego „nie dodaje ciągu tekstowego do plików konfiguracyjnych, które wyszukujesz i zastępujesz”.
Możesz utworzyć plik run.sh z wartościami zastępczymi, używając zmiennych środowiskowych.
Aby zmienić „7” w tym wierszu:
Sed Command, używając client_body_timeout jako linii wyszukiwania i $ client_body_timeout jako zastępczą zmienną env:
Skopiuj / wklej ten wiersz dla każdego parametru, który chcesz ustawić i zmień time_body_body_timeout za pomocą opcji config i $ client_body_timeout za pomocą zmiennej env, z którą jest on powiązany. Użyj z istniejącym plikiem konfiguracyjnym i to po prostu będzie działać.
źródło
Oto przykład zastosowania tego
sed
podejścia, niekoniecznie lepszego, ale może być przydatne dla niektórych. Najpierw dodaj niestandardowe słowo kluczowe, które ma zostać zastąpione w pliku conf. Po drugie, utwórz plik docker, który deklarujeENV
zmienną, a następnie plik,CMD
który używased
do edycji konfiguracji przed jawnym uruchomieniem nginx.Załóżmy więc, że plik default.conf zawiera to słowo kluczowe
docker_host
:I napisz plik Docker podobny do:
Następnie zbuduj obraz i uruchom kontener za pomocą
źródło
Właściwy sposób to zrobić za pomocą lua, ponieważ powyższa odpowiedź jest nieaktualna:
źródło
Powinieneś móc robić, co chcesz, korzystając z szablonów Dockerize .
źródło