[Postado e editado em https://stackoverflow.com/questions/21933955 , pois foi considerado muito semelhante ao sysadmin para o StackOverflow.]
Eu tenho um contêiner de docker executando o Nginx, vinculado a outro contêiner de docker. O nome do host e o endereço IP do segundo contêiner são carregados no contêiner Nginx como variáveis de ambiente na inicialização, mas não são conhecidos antes (é dinâmico). Eu quero que eu nginx.conf
use esses valores - por exemplo,
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
Como posso obter variáveis de ambiente na configuração do Nginx na inicialização?
EDIT 1
Este é o arquivo inteiro, após a resposta sugerida abaixo:
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;
}
}
Recarregando nginx e erros:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
EDIT 2: mais detalhes
Variáveis de ambiente atuais
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;
Configuração do site 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;
Recarregue a configuração do 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;
porserver app_web_1:5000;
app_web_1
, obterá um novo endereço IP, portanto, você também precisará reiniciar o contêiner nginx. O Docker reinicia-o com uma atualização,/etc/hosts
para que você não precise alterar o (s) arquivo (s) de configuração do nginx.Respostas:
A partir do arquivo oficial estivador Nginx:
Atualizar:
Mas você sabe que isso causou às suas variáveis Nginx assim:
danificado para:
Então, para evitar isso, eu uso este truque:
Eu tenho um script para executar o Nginx, usado no
docker-compose
arquivo como opção de comando para o servidor Nginx, que o nomeeirun_nginx.sh
:E por causa da nova
DOLLAR
variável definida norun_nginx.sh
script, agora o conteúdo do meunginx.conf.template
arquivo para a variável Nginx é assim:E para a minha variável definida é assim:
Também aqui , há o meu caso de uso real para isso.
fonte
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;'"
funciona para me b / c eu sei que eles são chamados ...$
, deve sercommand: /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;'"]
Fazer isso com Lua é substancialmente mais fácil do que parece:
Eu achei isso aqui:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Editar:
Aparentemente, isso requer a instalação do módulo lua: https://github.com/openresty/lua-nginx-module
Edição 2:
Observe que, com essa abordagem, você deve definir a
env
variável no Nginx:Você precisa fazer isso no contexto de nível superior
nginx.conf
ou não funcionará! Não está no bloco do servidor ou na configuração de algum site/etc/nginx/sites-available
, porque está incluídonginx.conf
nohttp
contexto (que não é o contexto de nível superior).Observe também que, com essa abordagem, se você tentar fazer um redirecionamento, por exemplo:
não vai funcionar tão bem:
E se você der um nome de variável separado para ela:
O nginx não o interpretará e o redirecionará para
https://%24server_name_from_env/
.fonte
env NGINX_SERVERNAME
algum lugar no seu nginx.conf.set_by_lua
a variável no arquivo de configuração incluído, enquanto aenv MY_VAR
declaração estava no nginx.conf principal, conforme sugerido. Que pena, essa teria sido a solução mais limpa!envsubst
? Eu acho que o profissional é que você não precisa executar oenvsubstr
comando antes de iniciar o servidor e o golpe é que você precisa instalar o módulo lua? Gostaria de saber se existem implicações de segurança em qualquer uma das abordagens.envsubst
e que não éEu escrevi algo que pode ou não ser útil: https://github.com/yawn/envplate
Ele inline edita arquivos de configuração com $ {key} referências a variáveis de ambiente, opcionalmente criando backups / registrando o que faz. Está escrito em Go e o binário estático resultante pode ser simplesmente baixado na guia de lançamento do Linux e MacOS.
Também pode exec () processa, substitui padrões, registra e tem semântica de falha sensível.
fonte
A imagem oficial do nginx recomenda o uso
envsubst
, mas, como indicado por outras pessoas, ela substituirá também$host
e outras variáveis, o que não é desejável. Felizmente, porém,envsubst
podemos tomar como parâmetro os nomes das variáveis a serem substituídas .Para evitar um parâmetro de comando muito complexo no contêiner (como no exemplo vinculado), você pode escrever um script de ponto de entrada do Docker que preencherá as variáveis de ambiente antes de executar o comando. O script do ponto de entrada também é um bom local para validar os parâmetros e definir valores padrão.
Aqui está um exemplo de um contêiner nginx que recebe
API_HOST
eAPI_PORT
parâmetros como variáveis de ambiente.nginx-default.conf.template
docker-entrypoint.sh
Dockerfile
fonte
O que eu fiz foi usar o erb !
- Depois de usar erb
Isso é usado no staticfile-buildpack Cloudfoundry
Exemplo de configuração do nginx: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
No seu caso
tornar-se
fonte
Referindo-se à resposta sobre o uso de erb, isso pode ser feito conforme abaixo.
Escreva o arquivo de configuração NGINX como um arquivo erb que contém a variável de ambiente e avalie-o usando o comando erb em um arquivo de configuração normal.
Dentro do bloco do servidor do arquivo nginx.conf.erb, pode haver
fonte
erb
? Capaz de fazer a substituição de variáveis ... depois de o contentor foi iniciado, à direita) -erb
é este direito material Ruby: stuartellis.name/articles/erbSei que essa é uma pergunta antiga, mas, caso alguém se depare com essa questão (como agora tenho), há uma maneira muito melhor de fazer isso. Como o docker insere o alias do contêiner vinculado em / etc / hosts, você pode simplesmente
assumindo que o seu comando docker é algo parecido
docker run --link othercontainer:docker_link_alias nginx_container
.fonte
Outra opção ... Acabei de encontrar esta ferramenta hoje: https://github.com/kreuzwerker/envplate ... Escrita no Go, ela pode ser instalada com muita facilidade. Usá-lo é bastante simples. Embora você precise colocar variáveis de modelo no seu nginx.conf.
Por exemplo
${SOME_ENV_VAR}
, será substituído quando oep
comando envplate for chamado no arquivo. Portanto, se o seu Dockerfile falhar ao obter esse binário ou se não for executado por algum motivo, isso tornaria sua configuração inválida. Apenas uma pequena nota em comparação com outras soluções, como usar extensões perl ou lua.Eu realmente gosto de como você pode definir valores padrão também para quando a variável de ambiente não está definida. Ex.
${SOME_ENV_VAR:default-value}
(e você pode escapar de valores). Novamente, o envplate ainda deve ser executado com êxito.Um benefício do uso de uma abordagem como essa é que você não acaba com uma imagem do Docker maior que o necessário, porque instalou todos os tipos de módulos extras que não seriam necessários. Também pode ser mais fácil do que usar o sed se as coisas começarem a ficar complexas e contiver essa funcionalidade de valor padrão.
fonte
Eu faço isso usando um script de shell.
Aqui está o modelo nginx:
E o script para substituir as variáveis de ambiente está aqui:
fonte
Outra possibilidade é usar o comando 'sed' com expressões regulares, para que você não precise mexer nos seus arquivos de configuração! Dessa forma, você pode usar seus arquivos de configuração normalmente, mas quando você executa o docker, ele troca os valores com as variáveis env. Nada disso "adiciona uma sequência de texto aos arquivos de configuração que você pesquisa e substitui".
Você pode criar um arquivo run.sh com valores de substituição usando suas variáveis de ambiente.
Para alterar os "7s" nesta linha:
Comando Sed usando client_body_timeout como linha de pesquisa e $ client_body_timeout como variável de env de substituição:
Copie / cole esta linha para cada parâmetro que você deseja definir e altere o client_body_timeout com a opção de configuração e $ client_body_timeout com a variável env à qual está associado. Use com o arquivo de configuração existente e ele simplesmente funcionará.
fonte
Aqui está um exemplo de uso da
sed
abordagem, não necessariamente melhor, mas pode ser útil para alguns. Primeiro, adicione uma palavra-chave personalizada para ser substituída no arquivo conf. Segundo, crie um arquivo docker que declare umaENV
variável e depois umCMD
que usesed
para editar a configuração antes de executar o nginx explicitamente.Então, suponha que seu default.conf contenha isso com a palavra
docker_host
- chave :E escreva seu Dockerfile semelhante a:
Em seguida, crie a imagem e execute o contêiner usando
fonte
Maneira correta de fazer isso com lua, pois a resposta acima é obsoleta:
fonte
Você deve poder fazer o que quiser com os modelos do Dockerize .
fonte