从docker compose替换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

我试图在通过docker compose配置的docker容器中启动NGINX服务器。然而,关键是我想在http部分内,特别是在“上游”块内,替换一个环境变量

这将是非常棒的工作,因为我有几个其他容器都是通过环境变量配置的,我有大约5个环境需要在任何给定的时间运行。我尝试过使用“envsubt”(正如官方NGINX文档所建议的那样)、perl_set和set_by_lua,但是它们似乎都不起作用

下面是NGINX配置,这是在我最近的试用之后

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;
    }
}