从docker compose替换NGINX配置中的环境变量
我试图在通过docker compose配置的docker容器中启动NGINX服务器。然而,关键是我想在http部分内,特别是在“上游”块内,替换一个环境变量 这将是非常棒的工作,因为我有几个其他容器都是通过环境变量配置的,我有大约5个环境需要在任何给定的时间运行。我尝试过使用“envsubt”(正如官方NGINX文档所建议的那样)、perl_set和set_by_lua,但是它们似乎都不起作用 下面是NGINX配置,这是在我最近的试用之后从docker compose替换NGINX配置中的环境变量,docker,nginx,docker-compose,environment-variables,Docker,Nginx,Docker Compose,Environment Variables,我试图在通过docker compose配置的docker容器中启动NGINX服务器。然而,关键是我想在http部分内,特别是在“上游”块内,替换一个环境变量 这将是非常棒的工作,因为我有几个其他容器都是通过环境变量配置的,我有大约5个环境需要在任何给定的时间运行。我尝试过使用“envsubt”(正如官方NGINX文档所建议的那样)、perl_set和set_by_lua,但是它们似乎都不起作用 下面是NGINX配置,这是在我最近的试用之后 user nginx; worker_process
user nginx;
worker_processes 1;
env NGINXPROXY;
load_module modules/ngx_http_perl_module.so;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
perl_set $nginxproxy 'sub { return $ENV{"NGINXPROXY"}; }';
upstream api-upstream {
server ${nginxproxy};
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
下面是NGINX dockerfile
# build stage
FROM node:latest
WORKDIR /app
COPY ./ /app
RUN npm install
RUN npm run build
# production stage
FROM nginx:1.17.0-perl
COPY --from=0 /app/dist /usr/share/nginx/html
RUN apt-get update && apt-get install -y gettext-base
RUN rm /etc/nginx/conf.d/default.conf
RUN rm /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d
COPY nginx.conf /etc/nginx
RUN mkdir /certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
以下是NGINX服务器的docker-compose.yml部分(名称和IP已更改)。在我的疑难解答中,envsubt命令在此时被有意注释掉
front-end:
environment:
- NGINXPROXY=172.31.67.100:9300
build: http://gitaccount:password@gitserver.com/group/front-end.git#develop
container_name: qa_front_end
image: qa-front-end
restart: always
networks:
qa_network:
ipv4_address: 172.28.0.215
ports:
- "9080:80"
# command: /bin/bash -c "envsubst '$$NGINXPROXY' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"
当我尝试使用envsubt时,我得到一个错误,使它听起来像是命令弄乱了nginx.conf文件的格式
qa3_front_end | 2019/06/18 12:49:02 [emerg] 1#1: no "events" section in configuration
qa3_front_end | nginx: [emerg] no "events" section in configuration
qa3_front_end exited with code 1
我被卡住了,所以提前感谢您的帮助。您可以通过定义自己的入口点来避免使用Compose解释环境变量的一些麻烦。请参见以下简单示例:
- entrypoint.sh(确保此文件可执行)
config
文件与您的nginx.conf
具有相同的内容,只是我必须使用Perl模块对行进行注释
请注意,我必须先将配置文件装载到另一个位置,然后才能envsubt
it。我遇到了一些奇怪的行为,文件在替换后变成空的,这可以通过这种方法避免。在您的特定情况下,这不应该是一个问题,因为您已经在构建时将其嵌入到映像中
编辑 为了完整起见,要尽可能少地更改设置,只需确保导出环境变量。调整您的命令如下:
command: ["/bin/bash", "-c", "export NGINXPROXY && envsubst '$$NGINXPROXY' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"]
命令:[“/bin/bash”、“-c”、“导出NGINXPROXY&envsubt”$$NGINXPROXY'/etc/nginx/nginx.conf&&nginx-g“守护进程关闭”]
…你应该很乐意去。不过,我总是推荐使用“更干净”的方法来定义您自己的入口点。因此,在对这个问题进行了一些思考之后,我设法使它与bellackn提供的答案类似。我将在这里发布我的精确解,以防其他人需要引用完整解 步骤1:以通常的方式编写nginx.conf或default.conf。将文件另存为“nginx.conf.template”或“default.conf.template”,具体取决于您尝试将变量替换到的文件
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
upstream api-upstream {
server 192.168.25.254;
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
步骤2:用${VARNAME}格式的变量替换要替换为环境变量的任何值:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
upstream api-upstream {
server ${SERVER_NAME};
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
步骤3:在docker文件中,将nginx配置文件(nginx.conf.template或default.conf.template)复制到容器中的适当位置:
# build stage
FROM node:latest
WORKDIR /app
COPY ./ /app
RUN npm install
RUN npm run build
# production stage
FROM nginx:1.17.0-perl
COPY --from=0 /app/dist /usr/share/nginx/html
RUN apt-get update && apt-get install -y gettext-base
RUN rm /etc/nginx/conf.d/default.conf
RUN rm /etc/nginx/nginx.conf
#-----------------------------------#
|COPY default.conf /etc/nginx/conf.d|
|COPY nginx.conf.template /etc/nginx|
#-----------------------------------#
RUN mkdir /certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
步骤4:使用“environment”部分标签在docker-compos.yml文件中设置环境变量。确保您的环境变量名与您在nginx配置文件中选择的任何变量名匹配。在docker容器中使用“envsubt”命令,用中的变量值替换nginx.conf.template中的变量,并将输出写入正确位置的名为nginx.conf的文件中。这可以在docker-compose.yml文件中使用“命令”部分标签完成:
version: '2.0'
services:
front-end:
environment:
- SERVER_NAME=172.31.67.100:9100
build: http://git-account:git-password@git-server.com/project-group/repository-name.git#branch-ame
container_name: qa_front_end
image: qa-front-end-vue
restart: always
networks:
qa_network:
ipv4_address: 172.28.0.215
ports:
- "9080:80"
command: >
/bin/sh -c
"envsubst '
$${SERVER_NAME}
'< /etc/nginx/nginx.conf.template
> /etc/nginx/nginx.conf
&& nginx -g 'daemon off;'"
版本:“2.0”
服务:
前端:
环境:
-服务器名称=172.31.67.100:9100
建造:http://git-account:git-password@git-server.com/project group/repository name.git#branch ame
集装箱名称:qa\U前端
图:qa前端vue
重新启动:始终
网络:
qa_网络:
ipv4地址:172.28.0.215
端口:
- "9080:80"
命令:>
/垃圾箱/垃圾箱-c
“envsubs”
$${SERVER_NAME}
“/etc/nginx/nginx.conf
&&nginx-g“守护进程关闭;”“
步骤5:使用docker compose up运行堆栈(使用您需要的任何其他开关),nginx服务器现在应该从docker-compose.yml的“环境”部分中提供的任何值开始
正如上面的解决方案中所提到的,您也可以定义自己的入口点,但是这个解决方案也被证明工作得很好,并将所有内容都保存在一个配置文件中,使我能够直接从git运行服务堆栈,而只需一个docker-compose.yml文件
非常感谢大家花时间做好准备,感谢bellackn花时间帮助我解决问题。您现在可以在配置中使用环境变量与docker compose。我使用了以下设置:
# file: docker/nginx/templates/default.conf.conf
upstream api-upstream {
server ${API_HOST};
}
# file: docker-compose.yml
services:
nginx:
image: nginx:1.19-alpine
volumes:
- "./docker/nginx/templates:/etc/nginx/templates/"
environment:
NGINX_ENVSUBST_TEMPLATE_SUFFIX: ".conf"
API_HOST: api.example.com
我将稍微偏离文档中的示例脚本。注意模板文件上额外的.conf
扩展名-这不是打字错误。在nginx映像的文档中,建议将文件命名为default.conf.template
。启动时,脚本将获取该文件,替换环境变量,然后使用原始文件名将该文件输出到/etc/nginx/conf.d/,并删除.template
后缀
默认情况下,后缀为.template
,但这会中断语法高亮显示,除非您配置编辑器。相反,我指定.conf
作为模板后缀。如果您仅将文件命名为default.conf
,结果将是一个名为/etc/nginx/conf.d/default的文件,您的站点将不会按预期提供服务。<
# build stage
FROM node:latest
WORKDIR /app
COPY ./ /app
RUN npm install
RUN npm run build
# production stage
FROM nginx:1.17.0-perl
COPY --from=0 /app/dist /usr/share/nginx/html
RUN apt-get update && apt-get install -y gettext-base
RUN rm /etc/nginx/conf.d/default.conf
RUN rm /etc/nginx/nginx.conf
#-----------------------------------#
|COPY default.conf /etc/nginx/conf.d|
|COPY nginx.conf.template /etc/nginx|
#-----------------------------------#
RUN mkdir /certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
version: '2.0'
services:
front-end:
environment:
- SERVER_NAME=172.31.67.100:9100
build: http://git-account:git-password@git-server.com/project-group/repository-name.git#branch-ame
container_name: qa_front_end
image: qa-front-end-vue
restart: always
networks:
qa_network:
ipv4_address: 172.28.0.215
ports:
- "9080:80"
command: >
/bin/sh -c
"envsubst '
$${SERVER_NAME}
'< /etc/nginx/nginx.conf.template
> /etc/nginx/nginx.conf
&& nginx -g 'daemon off;'"
# file: docker/nginx/templates/default.conf.conf
upstream api-upstream {
server ${API_HOST};
}
# file: docker-compose.yml
services:
nginx:
image: nginx:1.19-alpine
volumes:
- "./docker/nginx/templates:/etc/nginx/templates/"
environment:
NGINX_ENVSUBST_TEMPLATE_SUFFIX: ".conf"
API_HOST: api.example.com
# After variable substitution, this will replace /etc/nginx/conf.d/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
# Proxy API calls to another destination; the default for the variable is
# set in docker-defaults.sh
proxy_pass $PROXY_API_DEST;
}
}