当前位置 博文首页 > RtxTitanV的博客:Docker Compose环境变量

    RtxTitanV的博客:Docker Compose环境变量

    作者:[db:作者] 时间:2021-07-07 10:14

    本文主要是对Docker Compose的环境变量以及如何在Compose中设置环境变量进行一个总结。

    一、环境信息

    本文所使用的环境如下:

    • 操作系统:CentOS Linux release 8.1.1911
    • Docker:19.03.11
    • Docker Compose:1.26.0

    二、Docker Compose CLI环境变量

    Docker Compose CLI环境变量主要用来配置Docker Compose命令行的行为。以DOCKER_开头的变量与用于配置Docker命令行客户端的那些变量效果相同。注意也可以使用环境文件来提供其中的一些变量 。至于具体有哪些Docker Compose CLI环境变量,见以下列表:

    • COMPOSE_PROJECT_NAME:设置项目名称。如果未设置,默认为当前工作目录的名称(如果未设置工作目录,工作目录默认为Compose配置文件所在目录)。在项目启动时该值与服务名称会一起添加到容器中。例如项目名称为myapp,并且包含两个服务dbweb,则Compose会分别启动名为myapp_db_1myapp_web_1的容器 。
    • COMPOSE_FILE:指定要使用的Compose配置文件的路径。如果未指定,Compose会先在当前目录中查找docker-compose.yml文件,找不到就依次在上层目录中查找,直到找到为止,如果找不到会报错。此变量支持由路径分隔符分隔的多个Compose文件(在Linux和macOS上路径分隔符为:,在Windows上为;)。例如, COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml。路径分隔符也可以使用COMPOSE_PATH_SEPARATOR进行自定义。
    • COMPOSE_API_VERSION:设置此变量的目的是为了解决Compose需要临时运行而客户端和服务器版本不匹配的情况。在生产环境中不推荐使用这个临时方案,最好通过升级来保证客户端和服务端版本的兼容性。
    • DOCKER_HOST:设置Docker守护进程(Daemon)的监听URL 。与Docker客户端一样,默认为unix:///var/run/docker.sock
    • DOCKER_TLS_VERIFY:如果该环境变量不为空,则与Docker守护进程的所有交互都通过TLS协议进行加密。
    • DOCKER_CERT_PATH:配置用于TLS验证的ca.pemcert.pem以及key.pem文件的路径。默认为~/.docker
    • COMPOSE_HTTP_TIMEOUT:配置Compose向Docker守护进程发送请求的超时时间。单位为秒,默认值60s。
    • COMPOSE_TLS_VERSION:配置与Docker守护进程进行TLS通信的TSL版本。默认版本为TLSv1。支持TLSv1TLSv1_1TLSv1_2三个版本。
    • COMPOSE_CONVERT_WINDOWS_PATHS:在卷的定义中是否启用从Windows形式到Unix形式的路径转换。默认值为0true1启用,false0禁用。
    • COMPOSE_PATH_SEPARATOR:指COMPOSE_FILE环境变量中的路径间隔符。
    • COMPOSE_FORCE_WINDOWS_HOST:是否启用使用short syntax解析卷的声明并始终假设主机路径是Windows路径,即使Compose在基于UNIX的系统上运行。true1启用,false0禁用。
    • COMPOSE_IGNORE_ORPHANS:是否启用不检测项目中的孤儿容器。true1启用,false0禁用。
    • COMPOSE_PARALLEL_LIMIT:设置Compose可以执行进程的最大并发数。默认值为64,并且设置不能低于2
    • COMPOSE_INTERACTIVE_NO_CLI:是否启用不使用Docker命令行执行runexec命令。true1启用,false0禁用。在CLI被上述操作需要的Windows上,此选项不可用。

    三、在文件中声明环境变量

    Compose支持在名为.env的环境文件中声明默认环境变量,该文件放置在执行docker-compose命令的文件夹(当前工作目录)中即可生效。所以可以将不同的.env放置在不同的目录下,在哪个目录执行docker-compose命令,哪个目录下的.env文件就会生效。

    1.语法规则

    • env文件中的每一行都采用VAR=VAL格式。
    • #开头的行将作为注释处理并被忽略。
    • 忽略空白行。
    • 引号不会被特殊处理,意味着它们是VAL的一部分。

    2.作用

    定义在.env中的环境变量主要用于Compose配置文件中的变量替换,特别是当多个Compose配置文件都用到同一个环境变量时,可以将该环境变量定义在.env中,当环境变量的值改变了也不必修改所有Compose配置文件,只需修改.env文件中的环境变量值即可,很方便维护。也可以用于定义以下Docker Compose CLI环境变量:

    • COMPOSE_API_VERSION
    • COMPOSE_CONVERT_WINDOWS_PATHS
    • COMPOSE_FILE
    • COMPOSE_HTTP_TIMEOUT
    • COMPOSE_TLS_VERSION
    • COMPOSE_PROJECT_NAME
    • DOCKER_CERT_PATH
    • DOCKER_HOST
    • DOCKER_TLS_VERIFY

    另外关于.env还有以下两点需注意:

    • 运行时环境中存在的值始终会覆盖.env文件内部定义的值。同样,通过命令行参数传递的值也具有优先权。
    • .env文件中定义的环境变量在容器内部不会自动显示。

    四、Docker Compose设置环境变量

    Docker Compose中设置环境变量十分灵活,总结为以下几种方式。

    1.替换Compose配置文件中的环境变量

    可以使用shell中的环境变量替换Compose配置文件中的值,${VARIABLE}$VARIABLE这两种语法都支持。如有以下Compose配置:

    version: '3'
    services:
      web:
        image: "myapp:${MYAPP_TAG}"
        ports:
          - "5000:5000"
      redis:
        image: "redis:alpine"
    

    通过export设置环境变量MYAPP_TAG的值为v1.0.1,然后验证Compose配置文件发现环境变量已被替换:
    环境变量已被替换
    如果未设置环境变量,则Compose会将配置文件中的环境变量替换为空字符串。这里环境变量MYAPP_TAG未设置,image选项的值为myapp:,见下图:
    环境变量替换为空字符
    可以使用典型的shell语法提供内联默认值,支持以下两种语法:

    • ${VARIABLE:-default}:如果VARIABLE未设置或为空,则会应用default的值。
    • ${VARIABLE-default}:仅当VARIABLE未设置时才会应用default的值。

    比如Compose配置文件中有以下配置:

    services:
      web:
        image: "myapp:${MYAPP_TAG:-v1.0.0}"
    

    未设置环境变量和设置为空时,都会应用默认值:
    都会应用默认值
    改为以下写法:

    services:
      web:
        image: "myapp:${MYAPP_TAG-v1.0.0}"
    

    此时该变量设置为空,但没有应用默认值:
    没有应用默认值
    关闭终端再重新打开终端,此时该环境变量已清除,再次验证Compose配置文件发现应用了默认值:
    发现应用了默认值
    可以使用以下两种语法来强制要求变量必须赋值:

    • ${VARIABLE:?err}:如果VARIABLE未设置或为空,退出并输出一条包含err的错误信息。
    • ${VARIABLE?err}:如果VARIABLE未设置,退出并输出一条包含err的错误信息。

    比如Compose配置文件中有以下配置:

    services:
      web:
        image: "myapp:${MYAPP_TAG:?version error}"
    

    未设置环境变量和设置为空时,会输出错误信息:
    会输出错误信息
    改为以下写法:

    services:
      web:
        image: "myapp:${MYAPP_TAG?version error}"
    

    此时该变量设置为空,没有输出错误信息:
    没有输出错误信息
    关闭终端再重新打开终端,此时该环境变量已清除,再次验证Compose配置文件发现输出了错误信息:
    发现输出了错误信息
    当配置中需要$符号时,可以使用$$符号。也可以防止Compose插值,因此$$ 可以引用不想由Compose处理的环境变量。例如以下配置:

    version: '3'
    services:
      web:
        image: "myapp:v1.0.0"
        ports:
          - "5000:5000"
        command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"    
      redis:
        image: "redis:alpine"
    

    设置了环境变量VAR_NOT_INTERPOLATED_BY_COMPOSE,Compose配置文件中的VAR_NOT_INTERPOLATED_BY_COMPOSE也不会被替换:
    不会被替换

    2.设置容器中的环境变量

    可以通过environment关键字设置服务容器中的环境变量,就像 docker run -e VARIABLE=VALUE ...一样 。比如Compose配置文件中有以下配置,等价于docker run -e DEBUG=1

    services:
      web:
        environment:
          - DEBUG=1
    

    验证Compose配置文件:
    验证Compose配置文件

    3.将环境变量传递到容器

    使用environment关键字时不赋值就可以将shell中的环境变量传递给服务容器,就像使用docker run -e VARIABLE ...一样。比如Compose配置文件中有以下配置,等价于docker run -e DEBUG

    services:
      web:
        environment:
          - DEBUG
    

    shell中没有设置该环境变量时,Compose配置文件中默认为将它解释为null
    它解释为null
    通过export将该环境设置为2,验证Compose配置文件,已经传递到容器:
    已经传递到容器
    容器中的DEBUG变量的值是从运行Compose的shell中的同名变量中获取的。

    4.通过env_file为容器设置多个环境变量

    可以通过env_file配置选项将外部文件中配置的多个环境变量传递到服务容器,就像使用docker run --env-file=FILE ...一样。比如Compose配置文件中有以下配置,等价于docker run --env-file=web-variables.env

    services:
      web:
        env_file:
          - web-variables.env
    

    在Compose配置文件目录新建一个名为web-variables.env的文件,随意配置几个测试用环境变量:

    APPNAME=MyApp
    AUTHOR=RtxTitanV
    VERSION=v1.0.0
    CREATETIME
    DESCRIPTION=web service
    

    通过export设置CREATETIME,验证Compose配置文件,可知Compose把web-variables.env配置内容解释为了environment配置,多个环境变量已成功设置:
    多个环境变量已成功设置

    5.使用docker-compose run命令设置环境变量

    可以使用docker-compose run -e设置一次性容器上的环境变量,就像docker run -e命令一样。使用以下Compose配置文件进行测试:

    version: '3'
    services:
      tomcat:
        image: "tomcat:9.0-jdk8-corretto"
        ports:
          - "8080:8080"
      redis:
        image: "redis:alpine"
    

    执行以下命令后台启动两个服务:

    docker-compose up -d
    

    启动两个服务
    执行以下命令在tomcat服务一次性容器上设置环境变量并查看环境变量:

    docker-compose run -e DEBUG=1 tomcat env
    

    结果见下图,已成功设置:
    已成功设置
    也可以通过从shell中传递环境变量的值,而不是直接赋值,执行以下命令:

    export DEBUG=2
    docker-compose run -e DEBUG tomcat env
    

    结果见下图,已成功设置:
    已成功设置2

    6.通过.env文件设置环境变量

    可以在名为.env的环境文件中为Compose配置文件中引用的任何环境变量设置默认值,或者用于配置Compose。如有以下Compose配置:

    version: '3'
    services:
      web:
        image: "myapp:${MYAPP_TAG}"
        ports:
          - "5000:5000"
        environment:
          - APPNAME
      redis:
        image: "redis:alpine"
    

    在Compose配置文件所在目录新建一个.env文件,内容如下:

    MYAPP_TAG=v1.0.0
    APPNAME=MyApp
    

    验证Compose配置文件,环境变量都被解释为.env文件中配置的默认值:
    环境变量都被解释为.env文件中配置的默认值
    当在多个文件中设置相同的环境变量时,Compose选择要使用的值的优先级如下:

    1. Compose配置文件
    2. Shell环境变量
    3. 环境文件
    4. Dockerfile
    5. 未定义的变量

    下面通过export设置环境变量,发现Compose选择使用了Shell环境变量的值:
    选择使用了Shell环境变量的值
    然后修改Compose配置文件的以下部分:

    services:
      web:
        environment:
          - APPNAME=TestApp
    

    验证Compose配置文件,可知Compose最终选择了Compose配置文件中设置的值:
    最终选择了Compose配置文件中设置的值

    NodeJS容器中需注意的细节:
    如果有脚本的package.json条目像NODE_ENV=test node server.js一样启动,那么这将覆盖docker-compose.yml文件中的任何设置。

    7.设置Compose CLI环境变量

    可以通过Docker Compose CLI环境变量来配置Docker Compose命令行的行为,它们以COMPOSE_DOCKER_开头。这里以COMPOSE_FILECOMPOSE_PROJECT_NAME这两个最常用的Compose CLI环境变量为例进行设置。使用以下配置进行测试:

    version: '3'
    services:
      tomcat:
        image: "tomcat:9.0-jdk8-corretto"
        ports:
          - "8080:8080"
      redis:
        image: "redis:alpine"
    

    其中docker-compose.yml/root/compose-env-test目录下,在/root/compose-env-test目录下新建一个test目录并进入,然后再新建一个/root/compose-env-test2目录。在/root/compose-env-test/test目录下执行以下命令后台启动项目并指定工作目录为/root/compose-env-test2目录:

    docker-compose --project-directory /root/compose-env-test2 up -d
    

    此时没有通过设置COMPOSE_FILE-f选项指定使用的Compose配置文件,工作目录以及它的所有上层目录中都没有docker-compose.yml文件,而当前目录的上层目录中有docker-compose.yml文件,启动成功:
    启动成功
    /root/compose-env-test2目录下执行以下命令后台启动项目并指定工作目录为/root/compose-env-test目录:

    docker-compose --project-directory /root/compose-env-test up -d
    

    工作目录中有docker-compose.yml文件,而当前目录以及它的所有上层目录中都没有docker-compose.yml文件,启动失败:
    启动失败
    所以在Compose配置文件未指定时,Compose会先在当前目录中查找docker-compose.yml文件。找不到就依次在上层目录中查找,直到找到为止,如果找不到会报错。继续在/root/compose-env-test2目录下执行以下命令:

    export COMPOSE_FILE=/root/compose-env-test/docker-compose.yml
    docker-compose --project-directory /root/compose-env-test up -d
    

    在通过COMPOSE_FILE环境变量指定了Compose配置文件之后后台启动成功:
    通过COMPOSE_FILE环境变量指定了Compose配置文件之后后台启动成功
    /root/compose-env-test3目录下新建一个docker-compose.yml文件,内容如下,服务名和之前不一样:

    version: '3'
    services:
      tomcat2:
        image: "tomcat:9.0-jdk8-corretto"
        ports:
          - "8080:8080"
      redis2:
        image: "redis:alpine"
    

    继续在/root/compose-env-test2目录下执行以下命令:

    export COMPOSE_FILE=/root/compose-env-test/docker-compose.yml
    docker-compose -f /root/compose-env-test3/docker-compose.yml --project-directory /root/compose-env-test up -d
    

    COMPOSE_FILE环境变量和-f选项同时使用时,会使用-f选项指定的Compose配置文件:
    会使用-f选项指定的Compose配置文件
    继续在/root/compose-env-test2目录下执行以下命令:

    docker-compose -f /root/compose-env-test3/docker-compose.yml up -d
    

    此时没有通过设置COMPOSE_PROJECT_NAME-p指定项目名称,也没有指定工作目录,默认工作目录为Compose配置文件所在目录,而此时项目名称正好为这个目录名称:
    此时项目名称正好为这个目录名称
    执行以下命令后台启动,指定工作目录为/root/compose-env-test

    docker-compose -f /root/compose-env-test3/docker-compose.yml --project-directory /root/compose-env-test up -d
    

    此时项目名称正好为工作目录名称:
    此时项目名称正好为工作目录名称
    所以可以肯定,在没有通过设置COMPOSE_PROJECT_NAME-p指定项目名称时,默认为当前工作目录名称。下面通过COMPOSE_PROJECT_NAME指定项目名称,执行以下命令:

    export COMPOSE_PROJECT_NAME=myproject
    docker-compose -f /root/compose-env-test3/docker-compose.yml --project-directory /root/compose-env-test up -d
    

    此时项目名称为COMPOSE_PROJECT_NAME中设置的名称:
    此时项目名称为COMPOSE_PROJECT_NAME中设置的名称
    执行以下命令:

    export COMPOSE_PROJECT_NAME=myproject
    docker-compose -f /root/compose-env-test3/docker-compose.yml -p myproject2 --project-directory /root/compose-env-test up -d
    

    在同时使用COMPOSE_PROJECT_NAME环境变量和-p选项设置项目名称时,会将-p选项的设置作为项目名称:
    会将-p选项的设置作为项目名称

    8.通过link创建环境变量

    在v1版的Compose配置文件中使用links选项时,会为每个链接创建环境变量。它们记录在Link环境变量参考中。但是,这些变量现已被弃用。取而代之的是使用link别名作为主机名。

    cs