docker-compose的一些占位符运用

这是一个普通的docker-compose文件

version: '3'
services:
  applymgr:
    image: harbor.cloud.test/online/applymgr:b88b2301
    networks:
      - default
    dns:
      - 10.99.165.22
    extra_hosts:
      - "zk_hadoop_hbase_kafka:10.109.95.32"
    environment:
      CONFIG_SERVER_URI: http://10.09.65.43:8002
      DEUREKA_URL: http://user:123@10.19.25.53:8001
      JAVA_OPTS: -Xms1024m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
    command: java -jar -Dspring.profiles.active=test3 manager.jar
    ports:
      - "18001:8080"
networks:
  default:
    driver: bridge

这里 environment 表示环境变量。我们这里设置了一些环境变量。数量不多,但是显得很繁琐。

command 表示我们使用什么命令启动镜像中的jar 文件,它会覆盖Dockerfile中的CMD指令。

这里我们看到配置都是写死的,怎么才能配置化呢?

docker-compose 其实支持文件环境变量

 

version: '3'
services:
  applymgr:
    image: harbor.cloud.test/online/applymgr:b88b2301
    networks:
      - default
    dns:
      - 10.99.165.22
    extra_hosts:
      - "zk_hadoop_hbase_kafka:10.109.95.32"
    env_file:
      - ./common.env
    command: java -jar ${RUN_PROFILE} manager.jar
    ports:
      - "18001:8080"
networks:
  default:
    driver: bridge

这里可以看到我们把具体的环境变量换成了引用 当前目录下的 common.env文件。同时command 指令也使用了占位符来获取环境变量的值。看下环境变量文件中的内容:

CONFIG_SERVER_URI=http://10.88.75.83:8002
EUREKA_URL=http://user:123@10.88.75.83:8001
JAVA_OPTS=-Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
RUN_PROFILE=-Dspring.profiles.active=test3
TZ="Asia/Shanghai"

 这里需要注意的是,环境变量文件 最好使用 key=value的形式 不要使用 key:value的形式,否则会出现null的情况

之后怎么验证呢,其实我们可以使用命令查看docker-compose.yml效果

docker-compose config

执行该命令,得到结果:

 

networks:
  default:
    driver: bridge
services:
  applymgr:
    command: java -jar  manager.jar
    dns:
    - 10.99.165.22
    environment:
      CONFIG_SERVER_URI: http://10.88.75.83:8002
      EUREKA_URL: http://user:123@10.88.75.83:8001
      JAVA_OPTS: -Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m
        -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection
        -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
      RUN_PROFILE: -Dspring.profiles.active=test3
    extra_hosts:
    - zk_hadoop_hbase_kafka:10.109.95.32
    image: harbor.cloud.test/online/applymgr:b88b2301
    networks:
      default: null
    ports:
    - 18001:8080/tcp
version: '3.0'

发现环境变量都设置进去了,但是我们再commond 那里设置的占位符 却变成了空格。那说名占位符并没有取到环境变量的值。

那么这是什么原因了。如果我们把 common.env 重命名为  .env 。同时更改docker-compose.yml文件 env_file 中的文件名。此时可以看到

version: '3'
services:
  applymgr:
    image: harbor.cloud.test/online/applymgr:b88b2301
    networks:
      - default
    dns:
      - 10.99.165.22
    extra_hosts:
      - "zk_hadoop_hbase_kafka:10.109.95.32"
    env_file:
      - ./.env
    command: java -jar ${RUN_PROFILE} manager.jar
    ports:
      - "18001:8080"
networks:
  default:
    driver: bridge

结果:

networks:
  default:
    driver: bridge
services:
  applymgr:
    command: java -jar -Dspring.profiles.active=test3 manager.jar
    dns:
    - 10.99.165.22
    environment:
      CONFIG_SERVER_URI: http://10.88.75.83:8002
      EUREKA_URL: http://user:123@10.88.75.83:8001
      JAVA_OPTS: -Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m
        -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection
        -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
      RUN_PROFILE: -Dspring.profiles.active=test3
    extra_hosts:
    - zk_hadoop_hbase_kafka:10.109.95.32
    image: harbor.cloud.test/online/applymgr:b88b2301
    networks:
      default: null
    ports:
    - 18001:8080/tcp
version: '3.0'

可以看到command 获取环境变量成功了。因为如果我们使用文件设置环境变量。那么文件名 尽量设置为 .env。

同时获取 环境变量 可以使用 ${} 也可以直接使用 $

 

需要注意的是,当我们使用java docker时,如果要设置自定义参数时,尽量避免 使用 JAVA_OPTS 这个环境变量的Key。因为如果设置了这个环境变量,启动后并不会按照你设置的参数来启动java应用,而是会走默认的一个java参数,因此可以设置一个其他名称来启动(如:MY_JAVA_OPTS)。具体的其实可以 通过docker-compose cofig命令来看。

实际上我们还可以做一个实验。就是 我们不设置 JAVA_OPTS 这个环境变量

但是在写 command 的时候 加上 $JAVA_OPTS 环境变量   。如 java -jar $JAVA_OPTS  xx.jar

这个时候使用 docker-compose config 来查看 会发现 command 命令已经加上了启动参数(虽然我们并没有设置这个环境变量)。

之所以会出现这个,是因为docker-compose 对各种情况下的环境变量有个优先级的概念!也就是我们构建的镜像的基础镜像设置了这个环境变量,但是我们设置的环境变量并没有覆盖基础镜像设置的环境变量。

 

还有一点是需要注意的。如果我们在docker-compose.yml 的environment中添加了环境变量,同时在command中使用了这个变量,其实是并不生效的。

 

.......


environment:
    JAVA_FILE: app.jar

# 这里 返回的实际是 java -jar    。只有使用env_file(且该值为.env)设置的环境变量占位符才会被替换
command: java -jar ${JAVA_FILE}


.......

那么如果 environment 中定义的环境变量 和 env_file中定义的变量重复了会怎么样。

实际通过docker-compose config的测试发现。

例如。我们的 .env 文件中 定义了  JAVA_FILE: test.jar。我们的docker-compose.yml定义为。

.......


environment:
    JAVA_FILE: app.jar

env_file:
  - ./.env

# 这里 返回的实际是 java -jar    。只有使用env_file(且该值为.env)设置的环境变量占位符才会被替换
command: java -jar ${app.jar}


.......

实际结果却是

.......


environment:
    JAVA_FILE: app.jar

command: java -jar test.jar


.......

 

因此我们可以得到结论,environment跟env_file的作用范围是有差别的,就单纯从环境变量来看,environment的优先级更高,从占位符替换来看,却只能使用env_file(.env)

 

有时候我们的服务不是一下子都写好的,有可能是先启动了几个应用,然后过了几天又要上线几个应用,那么我们又得编辑docker-compose文件。把新添加的服务加上去,

然后使用

#停止服务,并删除容器
docker-compose down
#后台启动所有服务 docker
-compose up -d

如果你的应用比较多,那么过程会很慢。其实如果我们在docker-compose.yml中新添加了几个应用,这个时候是可以单独启动这几个应用的。

docker-compose -f docker-compose.yml up -d  [新添加的应用名]

这样就可以单独启动新加的应用了,而且新加的应用也是可以访问之前的应用的。之前的应用也可以访问新添加的应用

 

posted @ 2021-04-08 18:56  陈无问  阅读(1166)  评论(0编辑  收藏  举报