[ https://stackoverflow.com/questions/21933955 からクロスポストおよび編集して、StackOverflowにはsysadminに似ていると考えられていました。]
別のドッカーコンテナーにリンクするNginxを実行するドッカーコンテナーがあります。 2番目のコンテナーのホスト名とIPアドレスは、起動時に環境変数としてNginxコンテナーに読み込まれますが、それまでは不明です(動的です)。 nginx.conf
これらの値を使用するには-例.
upstream gunicorn {
server $APP_Host_NAME:$APP_Host_PORT;
}
起動時に環境変数をNginx構成に取り込むにはどうすればよいですか?
EDIT 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
From 公式のNginx Dockerファイル:
Nginx構成での環境変数の使用:
初期状態では、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.sh
です。
#!/usr/bin/env bash
export DOLLAR='$'
envsubst < nginx.conf.template > /etc/nginx/nginx.conf
nginx -g "daemon off;"
また、run_nginx.sh
スクリプトに新しいDOLLAR
変数が定義されているため、Nginx自体の変数に対するnginx.conf.template
ファイルの内容は次のようになります。
proxy_set_header X-Forwarded-Host ${DOLLAR}Host;
そして、私の定義した変数は次のようになります:
server_name ${WEB_DOMAIN} www.${WEB_DOMAIN};
また、- ここ 、私の実際の使用例があります。
ルアと一緒にやろう!
server {
set_by_lua $curr_server_name 'return os.getenv("APP_Host_NAME")';
set_by_lua $curr_server_port 'return os.getenv("APP_Host_PORT")';
listen = $curr_server_port
server_name = $curr_server_name;
}
(元の回答は廃止され、削除されました。これは更新された回答です。)
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:
このアプローチでは、Nginxでenv
変数を定義する必要があることに注意してください。
env ENVIRONMENT_VARIABLE_NAME
nginx.conf
のトップレベルのコンテキストでこれを行う必要があります。そうしないと機能しません。 http
コンテキスト(最上位のコンテキストではない)の/etc/nginx/sites-available
に含まれているため、サーバーブロックまたはnginx.conf
の一部のサイトの構成にはありません。
また、このアプローチでは、リダイレクトを行おうとすると、次のようになります。
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/
にリダイレクトします。
公式のnginxイメージ envsubst
を使用することをお勧めしますが、 他の人が指摘したように は、$Host
やその他の変数も置き換えるため、望ましくありません。 。しかし、幸いにもenvsubst
は パラメータとして置き換える変数の名前を取得 できます。
(リンクされた例のように)コンテナーに対する非常に複雑なコマンドパラメーターを回避するために、コマンドを実行する前に環境変数を入力するDockerエントリーポイントスクリプトを記述できます。エントリポイントスクリプトは、パラメータの検証とデフォルト値の設定にも適しています。
以下は、API_Host
およびAPI_PORT
パラメータを環境変数として受け取るnginxコンテナの例です。
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 "$@"
Dockerfile
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;"]
役に立つかもしれないし、役に立たないかもしれないものを書きました: https://github.com/yawn/envplate
環境変数への$ {key}参照を使用して構成ファイルをインライン編集します。オプションで、バックアップを作成し、その内容を記録します。 Goで書かれており、結果の静的バイナリはLinuxおよびMacOSのリリースタブから簡単にダウンロードできます。
また、プロセスのexec()、デフォルトの置き換え、ログ記録を行うことができ、適切な障害セマンティクスを持っています。
Erbの使用に関する回答を参照すると、次のように行うことができます。
NGINX構成ファイルを環境変数を含むerbファイルとして書き込み、erbコマンドを使用して通常の構成ファイルに対して評価します。
erb nginx.conf.erb > nginx.conf
Nginx.conf.erbファイルのサーバーブロック内に
listen <%= ENV["PORT"] %>;
私がしたことは 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;
これは Cloudfoundry staticfile-buildpack で使用されます
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
}
シェルスクリプトを使用してこれを実現します。
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;'
私はこれが古い質問であることを知っていますが、誰かがこれに遭遇した場合(私が今持っているように)に備えて、これを行うはるかに良い方法があります。 dockerはリンクされたコンテナのエイリアスを/ etc/hostsに挿入するため、次のようにできます
upstream upstream_name {
server docker_link_alias;
}
dockerコマンドがdocker run --link othercontainer:docker_link_alias nginx_container
。
別のオプション...今日、このツールを見つけました: https://github.com/kreuzwerker/envplate ... Goで記述されているため、簡単にインストールできます。使い方はとても簡単です。ただし、テンプレート変数をnginx.confに配置する必要があります。
例えば ${SOME_ENV_VAR}
は、ファイルでenvplateのep
コマンドが呼び出されると置き換えられます。したがって、Dockerfileがそのバイナリの取得に失敗したり、何らかの理由でDockerfileが実行されなかったりすると、構成が無効になります。 Perlやlua拡張の使用など、他のソリューションと比較した場合のちょっとした注意。
環境変数が設定されていない場合にも、デフォルト値を設定する方法がとても気に入っています。例${SOME_ENV_VAR:default-value}
(値をエスケープできます)。この場合も、envplateは引き続き正常に実行される必要があります。
このようなアプローチを使用する利点の1つは、他の方法では必要のないあらゆる種類の追加モジュールをインストールするため、必要以上に大きなDockerイメージが作成されないことです。物事が複雑になり始め、デフォルト値の機能が含まれている場合は、sedを使用するよりも簡単かもしれません。
多くの方法があります。一部はいくつかの回答で概説されています。
ngx_http_js_module
を使用する場合、JSでそれを行う方法もあります。
## /etc/nginx/fetch_env.js
function fetch_upstream_Host(r) {
return process.env.UPSTREAM_Host;
}
function fetch_upstream_port(r) {
return process.env.UPSTREAM_PORT;
}
そして
## /etc/nginx/nginx.conf
load_module modules/ngx_http_js_module.so;
env UPSTREAM_Host;
env UPSTREAM_PORT;
http {
js_include fetch_env.js;
js_set $upstream_Host fetch_upstream_Host;
js_set $upstream_port fetch_upstream_port;
server {
...
location / {
...
proxy_pass http://$upstream_Host:$upstream_port;
}
}
Njsモジュール0.33以降を使用していることを確認してください
sed
アプローチの使用例を以下に示します。必ずしも優れているとは限りませんが、一部のユーザーには役立つ場合があります。まず、置換するカスタムキーワードをconfファイル内に追加します。次に、ENV
変数を宣言するdockerfileを作成し、次にCMD
を使用してsed
を使用して構成を編集し、nginxを明示的に実行します。
したがって、default.confにキーワードdocker_Host
が含まれているとします。
location /api { proxy_pass http://docker_Host:9000/api; }
そして、次のようなDockerfileを記述します。
ENV docker_Host localhost
ADD default.conf /etc/nginx/conf.d/default.conf
CMD sed -i.bak s/docker_Host/$docker_Host/g /etc/nginx/conf.d/default.conf && nginx -g "daemon off;"
次に、イメージをビルドし、コンテナを実行します
docker run -d -p 80:80 -e "docker_Host=${env:COMPUTERNAME}" imagename
もう1つの可能性は、正規表現で「sed」コマンドを使用することです。そうすれば、構成ファイルをいじる必要がまったくなくなります。これにより、設定ファイルを通常どおり使用できますが、Dockerを実行すると、値がenv変数と入れ替えられます。これはどれも「検索して置き換える構成ファイルにテキスト文字列を追加する」ことはありません。
環境変数を使用して、置換値を含むrun.shファイルを作成できます。
この行の「7」を変更するには:
client_body_timeout 7s; #Default 60s
client_body_timeoutを検索行として使用し、$ client_body_timeoutを置換環境変数として使用するSedコマンド:
sed -i "s/\(client_body_timeout\).*\?\;/\1 $client_body_timeout;/" /usr/local/nginx/conf/nginx.conf
設定するすべてのパラメーターに対してこの行をコピーして貼り付け、configオプションでclient_body_timeoutを変更し、関連付けられているenv変数で$ client_body_timeoutを変更します。既存の設定ファイルを使用してください。それでうまくいきます。
上記の答えは古くなっているので、luaでこれを行う適切な方法:
server {
set_by_lua $curr_server_name 'return os.getenv("NGINX_SERVERNAME")';
server_name = $curr_server_name;
}