[Publicado en forma cruzada y editado desde https://stackoverflow.com/questions/21933955 ya que se consideró demasiado parecido a un administrador de sistemas para StackOverflow.]
Tengo un contenedor acoplable que ejecuta Nginx, que se vincula a otro contenedor acoplable. El nombre de host y la dirección IP del segundo contenedor se cargan en el contenedor Nginx como variables de entorno en el inicio, pero no se conocen antes (es dinámico). Quiero nginx.conf
que use estos valores, p. Ej.
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
¿Cómo puedo obtener variables de entorno en la configuración de Nginx al inicio?
EDITAR 1
Este es el archivo completo, después de la respuesta sugerida a continuación:
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;
}
}
Recargando nginx luego errores:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
EDIT 2: más detalles
Variables de entorno actuales
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;
Configuración del sitio 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;
Recargar la configuración de 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;
conserver app_web_1:5000;
app_web_1
, obtendría una nueva dirección IP, por lo que también necesitaría reiniciar su contenedor nginx. Docker lo reiniciará con una actualización/etc/hosts
para que no tenga que alterar los archivos de configuración nginx.Respuestas:
Del archivo docker oficial de Nginx:
Actualizar:
Pero sabes que esto causó a sus variables Nginx así:
dañado a:
Entonces, para evitar eso, uso este truco:
Tengo un script para ejecutar Nginx, que se usa en el
docker-compose
archivo como opción de comando para el servidor Nginx, lo llamérun_nginx.sh
:Y debido a la nueva
DOLLAR
variable definida en elrun_nginx.sh
script, ahora el contenido de minginx.conf.template
archivo para la variable Nginx es así:Y para mi variable definida es así:
También aquí , está mi caso de uso real para eso.
fuente
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 mí b / c Sé cómo se llaman ...$
, debería 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;'"]
Hacer esto con Lua es sustancialmente más fácil de lo que parece:
Encontré eso aquí:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Editar:
Aparentemente, esto requiere instalar el módulo lua: https://github.com/openresty/lua-nginx-module
Edición 2:
Tenga en cuenta que con este enfoque debe definir la
env
variable en Nginx:¡Tienes que hacer esto en contexto de nivel superior
nginx.conf
o no funcionará! No en el bloque de servidor o en la configuración de algún sitio en/etc/nginx/sites-available
, porque está incluidonginx.conf
enhttp
contexto (que no es el contexto de nivel superior).También tenga en cuenta que con este enfoque si intenta hacer una redirección, por ejemplo:
no funcionará tan bien:
Y si le das un nombre de variable por separado:
nginx no lo interpretará y lo redireccionará a
https://%24server_name_from_env/
.fuente
env NGINX_SERVERNAME
algún lugar en su nginx.conf.set_by_lua
la variable en el archivo de configuración incluido, mientras que laenv MY_VAR
declaración estaba en el nginx.conf principal, como se sugirió. ¡Qué pena, esta hubiera sido la solución más limpia!envsubst
? Supongo que el profesional es que no necesita ejecutar elenvsubstr
comando antes de iniciar el servidor y la desventaja es que necesita instalar el módulo lua. Me pregunto si hay alguna implicación de seguridad en cualquiera de los enfoques.envsubst
y que en mi caso es un no-goEscribí algo que puede o no ser útil: https://github.com/yawn/envplate
Edita en línea los archivos de configuración con referencias $ {key} a variables de entorno, opcionalmente crea copias de seguridad / registra lo que hace. Está escrito en Go y el binario estático resultante se puede descargar simplemente desde la pestaña de lanzamiento para Linux y MacOS.
También puede ejecutar procesos (), sustituir valores predeterminados, registros y tiene una semántica de fallas sensible.
fuente
La imagen oficial de nginx recomienda usar
envsubst
, pero como lo señalaron otros , también reemplazará a$host
otras variables, lo que no es deseable. Pero afortunadamenteenvsubst
puede tomar como parámetro los nombres de las variables a reemplazar .Para evitar un parámetro de comando muy complejo en el contenedor (como en el ejemplo vinculado), puede escribir un script de punto de entrada de Docker que completará las variables de entorno antes de ejecutar el comando. El script de punto de entrada también es un buen lugar para validar los parámetros y establecer valores predeterminados.
Aquí hay un ejemplo de un contenedor nginx que toma
API_HOST
yAPI_PORT
parámetros como variables de entorno.nginx-default.conf.template
docker-entrypoint.sh
Dockerfile
fuente
¡Lo que hice fue usar el erb !
--Después de usar erb
Esto se usa en Cloudfoundry staticfile-buildpack
Ejemplo de configuración de nginx: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
En tu caso
volverse
fuente
Refiriéndose a la respuesta sobre el uso de erb, se puede hacer de la siguiente manera.
Escriba el archivo de configuración NGINX como un archivo erb que contiene la variable de entorno y evalúelo utilizando el comando erb en un archivo de configuración normal.
Dentro del bloque del servidor del archivo nginx.conf.erb podría haber
fuente
erb
capaz de hacer una sustitución de variables ... después de que se inició el contenedor, ¿verdad?) - ¿erb
Es correcto este material de Ruby: stuartellis.name/articles/erbSé que esta es una vieja pregunta, pero en caso de que alguien se encuentre con esto (como ahora lo hago), hay una manera mucho mejor de hacerlo. Debido a que Docker inserta el alias del contenedor vinculado en / etc / hosts, simplemente puede hacer
suponiendo que su comando docker es algo así
docker run --link othercontainer:docker_link_alias nginx_container
.fuente
Otra opción ... Acabo de encontrar esta herramienta hoy: https://github.com/kreuzwerker/envplate ... Escrita en Go, se puede instalar muy fácilmente. Usarlo es bastante simple. Aunque necesitará colocar variables de plantilla en su nginx.conf.
Por ejemplo
${SOME_ENV_VAR}
, se reemplazará cuando se invoque elep
comando envplate en el archivo. Entonces, si su Dockerfile no puede obtener ese binario o si no se ejecuta por alguna razón, dejaría su configuración inválida. Solo una pequeña nota en comparación con otras soluciones como el uso de extensiones perl o lua.Realmente me gusta cómo puede establecer valores predeterminados también para cuando la variable de entorno no está configurada. Ex.
${SOME_ENV_VAR:default-value}
(y puedes escapar de los valores). Nuevamente, envplate aún debe ejecutarse con éxito.Una ventaja de usar un enfoque como este es que no terminas con una imagen de Docker que es más grande de lo necesario porque dejaste de instalar todo tipo de módulos adicionales que de otro modo no necesitarías. También puede ser más fácil que usar sed si las cosas comienzan a complicarse y contiene esa funcionalidad de valor predeterminado.
fuente
Lo logro usando un script de shell.
Aquí está la plantilla nginx:
Y el script para reemplazar las variables de entorno está aquí:
fuente
Otra posibilidad es usar el comando 'sed' con expresiones regulares, ¡entonces no tendrá que meterse con sus archivos de configuración! De esa manera, puede usar sus archivos de configuración normalmente, pero cuando ejecuta Docker, intercambiará los valores con las variables env. Nada de esto "agrega una cadena de texto a los archivos de configuración que busca y reemplaza".
Puede crear un archivo run.sh con valores de reemplazo utilizando sus variables de entorno.
Para cambiar los "7" en esta línea:
Comando Sed usando client_body_timeout como línea de búsqueda y $ client_body_timeout como variable de reemplazo de env:
Copie / pegue esta línea para cada parámetro que desee establecer y cambie client_body_timeout con la opción de configuración y $ client_body_timeout con la variable env con la que está asociado. Úselo con el archivo de configuración existente y simplemente funcionará.
fuente
Aquí hay un ejemplo del uso del
sed
enfoque, no necesariamente mejor, pero puede ser útil para algunos. Primero, agregue una palabra clave personalizada para ser reemplazada dentro del archivo conf. En segundo lugar, cree un dockerfile que declare unaENV
variable y luego unaCMD
que usesed
para editar la configuración antes de ejecutar nginx explícitamente.Supongamos que su default.conf contiene esto con la palabra clave
docker_host
:Y escriba su Dockerfile similar a:
Luego construye la imagen y ejecuta el contenedor usando
fuente
La forma correcta de hacer esto con lua, ya que la respuesta anterior es obsoleta:
fuente
Debería poder hacer lo que quiera con las plantillas de Dockerize .
fuente