שאלה כיצד ניתן להשתמש במשתני סביבה ב- Nginx.conf


[צולבות וערכו מטה מ 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

שורש 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

143
2018-02-21 15:02




זה לא פתרון גנרי למשתני סביבה, אבל אם אתה רוצה להשתמש משתני סביבה עבור המארחים / כתובות IP של שרתי במעלה, שים לב כי Docker (לפחות בגרסאות האחרונות) משנה / etc / hosts בשבילך. ראה docs.docker.com/userguide/dockerlinks    כלומר, אם המכל המקושר שלך נקרא 'app_web_1', המעגן ייצור שורה ב- / etc / hosts במיכל Nginx. אז אתה יכול פשוט להחליף server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;    עם server app_web_1:5000; - mozz100
תודה @ mozz100 - זה שימושי מאוד - / etc / hosts ערכי הם הרבה יותר יעיל מאשר vv vars במקרה זה. חסר רק מה קורה אם מיכל במעלה מופעל מחדש, ורוכש IP חדש. אני מניח כי מכולות הילד עדיין להצביע על ה- IP המקורי, לא אחד חדש? - Hugo Rodger-Brown
כן, אם אתה מפעיל מחדש app_web_1 הוא יקבל כתובת IP חדשה, כך שיהיה עליך להפעיל מחדש את המכל nginx שלך מדי. Docker היה מחדש את זה עם מעודכן /etc/hosts אז אתה לא צריך לשנות את קובץ nginx config (ים). - mozz100


תשובות:


אם אתה משתמש בקישור, מעגן קובע משתני סביבה ומוסיף כינוי עבור המכל המקושר /etc/hosts. אם אתה מסוגל קשה קוד היציאה (או אם זה רק יציאה 80) אתה יכול פשוט לעשות:

upstream gunicorn {
    server linked-hostname:5000;
}

היציאה זמינה רק במשתנה סביבה, אשר לא ניתן להשתמש בו upstream מודול, ולא בלוקים שרת או מיקום. הם יכולים להיות רק הפניה את התצורה הראשי, אשר לא עוזר לך. אתה יכול לעשות את זה עם את צרור פתוח הכולל את לואה.

אם אתה לא רוצה להשתמש openresty / Lua, אפשרות אחרת היא לעשות קצת החלפה ב מיכל ההפעלה. שלך docker run הפקודה יכולה ליצור את הקישור ואז להפעיל סקריפט עטיפה שמבצע את החלופה המתאימה:

#!/bin/bash
/usr/bin/sed -i "s/server<gunicorn_server_placeholder>/${APP_WEB_1_PORT_5000_TCP_ADDR}/" default
start nginx

56
2018-03-18 06:14



כן - הפתרון הנוכחי (עובד) הוא בדיוק זה. פשוט נראה קצת hacky. (עם זאת, זה רק סביבה מקומית dev, ולכן פריצה היא לא בעיה ענקית.) - Hugo Rodger-Brown
נתקלתי בזה, אז עשיתי קצת יותר כללי מיכל nginx כי באופן אוטומטי מרחיב משתני סביבה בתצורה. - Shepmaster


מ קובץ המעגן הרשמי Nginx:

שימוש במשתני סביבה בתצורת nginx:

Out-of-the-box, Nginx אינה תומכת במשתני סביבה   בתוך רוב בלוקים תצורה.

אבל envsubst עשוי לשמש כ   אם אתה צריך ליצור את התצורה nginx שלך   באופן דינמי לפני nginx מתחיל.

הנה דוגמה באמצעות docker-compose.yml:

image: nginx
volumes:
 - ./mysite.template:/etc/nginx/conf.d/mysite.template
ports:
 - "8080:80"
environment:
 - NGINX_HOST=foobar.com
 - NGINX_PORT=80
command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" 

קובץ mysite.template עשוי לכלול אזכורים משתנים כמו   זו:

listen ${NGINX_PORT};

עדכון:

אבל אתה יודע שזה גרם למשתנים Nginx שלה ככה:

proxy_set_header        X-Forwarded-Host $host;

ניזוק ל:

proxy_set_header        X-Forwarded-Host ;

אז, כדי למנוע את זה, אני משתמש הטריק הזה:

יש לי סקריפט להפעיל Nginx, כי נעשה שימוש על docker-compose הקובץ כמו הפקודה עבור שרת Nginx, אני בשם זה run_nginx.shYou

#!/usr/bin/env bash
export DOLLAR='$'
envsubst < nginx.conf.template > /etc/nginx/nginx.conf
nginx -g "daemon off;"

ובגלל חדש מוגדר DOLLAR משתנה ב run_nginx.sh סקריפט, עכשיו התוכן של שלי nginx.conf.template הקובץ עבור Nginx עצמו משתנה הוא כזה:

proxy_set_header        X-Forwarded-Host ${DOLLAR}host;

ובשביל המשתנה המוגדר שלי הוא כזה:

server_name  ${WEB_DOMAIN} www.${WEB_DOMAIN};

כמו כן כאן, יש מקרה השימוש האמיתי שלי עבור זה.


62
2018-02-11 12:39



זה הורג nginx confs כמו proxy_set_header Host $http_host; - shredding
@ shredding אתה יכול לעבור שמות משתנים להיות מוחלף - אחרים לא נגעו: command: /bin/bash -c "envsubst '$VAR1 $VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" עובד בשבילי ב / ג אני יודע איך הם נקראים ... - pkyeck
בסדר, שכחתי לברוח $, צריך להיות command: /bin/bash -c "envsubst '\$VAR1 \$VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" - pkyeck
עם התחשבות בריחה זה עובד Dockerfile שלך: 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;'"] - KCD
זה פתרון נהדר. תודה. גם את הקישור שהוזכר לעיל github.com/docker-library/docs/issues/496 יש פתרון נהדר עבור הבעיה. - kabirbaidhya


לעשות את זה עם Lua הוא הרבה יותר קל ממה שזה נשמע:

server {
    set_by_lua $server_name 'return os.getenv("NGINX_SERVERNAME")';
}

מצאתי כי כאן:

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:

env ENVIRONMENT_VARIABLE_NAME

אתה צריך לעשות את זה בהקשר ההקשר ב nginx.conf או שזה לא יעבוד! לא בבלוק שרת או בתצורה של אתר כלשהו /etc/nginx/sites-available, כי זה כלול על ידי nginx.conf in http הקשר (שאינו הקשר ברמה העליונה).

כמו כן, שים לב שבגישה זו, אם תנסה לבצע הפניה מחדש, למשל:

server {
    listen 80;
    server_name $server_name;
    return 301 https://$server_name$request_uri;
}

זה לא יעבוד גם כן:

2016/08/30 14:49:35 [emerg] 1#0: the duplicate "server_name" variable in /etc/nginx/sites-enabled/default:8

ואם אתה נותן שם משתנה נפרד אליו:

set_by_lua $server_name_from_env 'return os.getenv("NGINX_SERVERNAME")';

server {
    listen 80;
    server_name $server_name_from_env;
    return 301 https://$server_name$request_uri;
}

nginx לא יפרש אותו ויפנה אותך אל https://%24server_name_from_env/.


26
2017-12-01 16:26



אולי תצטרך env NGINX_SERVERNAME איפשהו ב nginx.conf שלך. - hiroshi
זה לא עובד בשבילי, אם כי יש לי את מודול lua בתמונה nginx שלי מעגן. זה יכול להיות קשור לעובדה כי אני כולל קובץ config בתוך nginx.conf שלי? ניסיתי set_by_luaהמשתנה בקובץ ההגדרות הכלול, בעוד env MY_VAR ההצהרה היתה ב- nginx.conf הראשי, כפי שהוצע. איזו בושה, זה היה הפתרון הנקי! - pederpansen
האם מישהו יודע את היתרונות / חסרונות באמצעות שיטה זו של envsubst? אני מניח Pro הוא שאתה לא צריך להפעיל את envsubstr הפקודה לפני תחילת השרת ואת con הוא שאתה צריך להתקין את מודול lua? אני תוהה אם יש השלכות ביטחוניות על שתי הגישות? - Mark Winterbottom
@MarkWinterbottom לא לבדוק את זה עדיין, אבל זה נראה כאילו לא היית צריך להעניק גישה לכתוב קבצי nginx config, שבו אתה צריך להשתמש envsubst וזו אינה עבירה במקרה שלי - Griddo


כתבתי משהו שעשוי או לא יעזור: https://github.com/yawn/envplate

זה עורך קבצי תצורה עם $ {key} הפניות משתני סביבה, אופציונלי יצירת גיבויים / רישום מה זה עושה. זה כתוב ב בינארי סטטי וכתוצאה מכך ניתן להוריד פשוט מתוך לשונית שחרור עבור לינוקס ו- MacOS.

זה יכול גם exec () תהליכים, ברירות מחדל תחליף, יומני יש סמנטיקה כישלון נבון.


14
2017-11-15 16:02





מה שעשיתי היה להשתמש erb!

cat nginx.conf  | grep -i error_log

error_log <%= ENV["APP_ROOT"] %>/nginx/logs/error.log;

- לאחר שימוש erb

export APP_ROOT=/tmp

erb nginx.conf  | grep -i error_log

error_log /tmp/nginx/logs/error.log;

זה משמש ב ענן

תצורת nginx לדוגמה: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf

במקרה שלך

head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env APP_WEB_1_PORT_5000_TCP_ADDR;
upstream gunicorn {
    server $APP_HOST_NAME:$APP_HOST_PORT;
}

הפכו

head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env <%= ENV["APP_WEB_1_PORT_5000_TCP_ADDR"] %>
upstream gunicorn {
    server <%= ENV["APP_HOST_NAME"] %>:<%= ENV["APP_HOST_PORT"] %>
}

#After applying erb

export APP_WEB_1_PORT_5000_TCP_ADDR=12.12.12.12
export APP_HOST_NAME=test
export APP_HOST_PORT=7089 

erb /etc/nginx/nginx.conf

head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env 12.12.12.12
upstream gunicorn {
    server test: 7089
}

5
2018-02-20 00:11



האם אתה יכול להרחיב על תשובה זו? ראוי לציין כי יש תשובה מקובלת כבר לשאלה זו לעיל, אבל אם אתה מרגיש את התשובה שלך מוסיף ערך אז בבקשה להרחיב על זה. - BE77Y


בהתייחסו לתשובה על השימוש erb, זה יכול להיעשות כמו להלן.

כתוב את קובץ ההגדרות NGINX כקובץ erb המכיל את משתנה הסביבה, והעריך אותו באמצעות הפקודה erb לקובץ תצורה רגיל.

erb nginx.conf.erb > nginx.conf

בתוך בלוק השרת של הקובץ nginx.conf.erb יכול להיות

listen <%= ENV["PORT"] %>;

4
2017-08-01 11:39



האם אני צריך להתקין את רובי אז, בתוך המיכל? (אם לא, איך זה erb מסוגל לעשות תחליף משתנה ... לאחר מיכל התחיל, נכון?) - erb זה רובי דברים ימינה: stuartellis.name/articles/erb - KajMagnus
זה כלי שורת הפקודה שמגיע עם ההתקנה רובי סטנדרטי. נסה אפשרויות אחרות אם אין לך את זה במיכל. - Ruifeng Ma
בסדר, תודה על ההסבר - KajMagnus


אני יודע שזו שאלה ישנה, ​​אבל למקרה שמישהו יעמוד על כך (כפי שיש לי עכשיו), יש דרך טובה יותר לעשות זאת. כי מעגן מוסיף את שם המכל המקושר ב / etc / hosts, אתה יכול פשוט לעשות

upstream upstream_name {
    server docker_link_alias;
}

בהנחה פקודת המעגן שלך הוא משהו כמו docker run --link othercontainer:docker_link_alias nginx_container.


3
2018-03-17 05:16



אתה יכול לקבל את המארח באמצעות שיטה זו, אבל לא את היציאה. אתה צריך גם קוד קשה את היציאה או להניח שזה באמצעות יציאה 80. - Ben Whaley


אפשרות נוספת ... מצאתי את הכלי הזה היום: https://github.com/kreuzwerker/envplate ... נכתב ב Go, זה יכול להיות מותקן בקלות רבה. השימוש בו הוא די פשוט. למרות שאתה צריך מקום משתנים תבנית nginx.conf שלך.

לדוגמה ${SOME_ENV_VAR} יוחלף כאשר envplate של ep הפקודה נקראת על הקובץ. אז צריך Dockerfile שלך ​​לא לקבל את זה בינארי או שזה לא יפעל משום מה, זה היה לארגן את התצורה שלך לא חוקי. רק הערה קטנה בהשוואה לפתרונות אחרים כמו באמצעות הרחבות perl או lua.

אני מאוד אוהב איך להגדיר ערכי ברירת מחדל גם כאשר משתנה הסביבה אינו מוגדר. לדוגמה, ${SOME_ENV_VAR:default-value} (ואתה יכול לברוח ערכים). שוב, envplate חייב עדיין לרוץ בהצלחה.

יתרון אחד של שימוש בגישה כזו היא כי אתה לא בסופו של דבר עם תמונה Docker כי הוא גדול יותר מאשר הצורך כי הלכת להתקין כל מיני מודולים נוספים שאתה לא צריך אחרת. זה עשוי להיות גם קל יותר מאשר להשתמש sed אם הדברים מתחילים לקבל מורכבים והוא מכיל את זה פונקציונליות ערך ברירת המחדל.


2
2017-07-20 00:14



אני מציע github.com/gliderlabs/sigil כמו נתקלתי באגים רבים ובעיות עם envplate. - Nick


אני להשיג זאת באמצעות סקריפט פגז.

הנה תבנית nginx:

server {

    listen 80;
    server_name ___MY_DOMAIN_NAME___;
    charset utf-8;

    location /proxy {
        proxy_pass http://___PROXY_IP___:___PROXY_PORT___;
        proxy_set_header Host            $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
    }

    location / {
        return         200;
    }

}

ואת התסריט להחליף את משתני הסביבה הוא כאן:

echo sleep 3
sleep 3

echo build starting nginx config


echo replacing ___MY_DOMAIN_NAME___/$MY_DOMAIN_NAME
echo replacing ___PROXY_IP___/$LETSENCRYPT_IP
echo replacing ___PROXY_PORT___/$PROXY_PORT

sed -i "s/___MY_DOMAIN_NAME___/$MY_DOMAIN_NAME/g" /etc/nginx/nginx.conf
sed -i "s/___PROXY_IP___/$PROXY_IP/g" /etc/nginx/nginx.conf
sed -i "s/___PROXY_PORT___/$PROXY_PORT/g" /etc/nginx/nginx.conf

cat /etc/nginx/nginx.conf

if [ -z "$MY_DOMAIN_NAME" ]; then
    echo "Need to set MY_DOMAIN_NAME"
    exit 1
fi  
if [ -z "$LETSENCRYPT_IP" ]; then
    echo "Need to set LETSENCRYPT_IP"
    exit 1
fi  
if [ -z "$LETSENCRYPT_PORT" ]; then
    echo "Need to set LETSENCRYPT_PORT"
    exit 1
fi
if [ -z "$LETSENCRYPT_HTTPS_IP" ]; then
    echo "Need to set LETSENCRYPT_HTTPS_IP"
    exit 1
fi 
if [ -z "$LETSENCRYPT_HTTPS_PORT" ]; then
    echo "Need to set LETSENCRYPT_HTTPS_PORT"
    exit 1
fi

nginx -g 'daemon off;'

2
2018-01-20 06:35





התמונה nginx הרשמי ממליץ להשתמש envsubst, אבל כפי שציינו אחרים זה יחליף גם $host ומשתנים אחרים, שאינו רצוי. אבל למרבה המזל envsubst פחית לקחת פרמטר את שמות המשתנים כדי להחליף.

כדי למנוע פרמטר פקודה מורכב מאוד למכולה (כמו בדוגמה המקושרת), ניתן לכתוב סקריפט כניסה של Docker אשר ימלא את משתני הסביבה לפני ביצוע הפקודה. סקריפט entpoint הוא גם מקום טוב לאימות הפרמטרים וקביעת ערכי ברירת המחדל.

הנה דוגמה של מיכל nginx אשר לוקח API_HOST ו API_PORT פרמטרים כמשתני סביבה.

nginx-default.conf.template

resolver  127.0.0.11 valid=10s;  # recover from the backend's IP changing

server {
  listen  80;

  location / {
    root  /usr/share/nginx/html;
  }

  location /api {
    proxy_pass  http://${API_HOST}:${API_PORT};
    proxy_set_header  Host $http_host;
  }
}

docker-entrypoint.sh

#!/usr/bin/env sh
set -eu

envsubst '${API_HOST} ${API_PORT}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf

exec "$@"

מעגן

FROM nginx:1.15-alpine

COPY nginx-default.conf.template /etc/nginx/conf.d/default.conf.template

COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

1
2017-07-02 17:28





אתה צריך לעשות מה שאתה רוצה לעגןשל תבניות.


0
2018-05-20 11:11



האם תוכל להוסיף עוד פרטים? - Pierre.Vriens