在运行时将带有docker-compose.yml的ENV变量传递给Dockerfile [英] Pass ENV variable with docker-compose.yml at runtime to Dockerfile

查看:102
本文介绍了在运行时将带有docker-compose.yml的ENV变量传递给Dockerfile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图根据docker-compose.yml中的环境(dev / uat / prod)覆盖dockerfile中的ENV值。由于某些设置是敏感的,因此我不能将这些设置放在docker映像的构建步骤之外,因此必须在运行时覆盖这些值。我一直试图通过docker stack deploy -c命令部署以下docker-compose,但是我注意到我的环境变量没有覆盖dockerfile中的现有变量。

I am trying to override the ENV values in my dockerfile depending on the environment (dev/uat/prod) from my docker-compose.yml. Because some of the settings are sensitive I cant have these settings be apart of the build step of the docker image, instead these values must be overridden during runtime. Ive been trying to deploy the following docker-compose via the docker stack deploy -c command, however i noticed my environment variables are not overriding the existing ones in the dockerfile.

Dockerfile:

Dockerfile:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
VOLUME /etc

ADD sample-0.0.1-SNAPSHOT.jar app.jar

ENV ENV_SETTINGS=ssldev
ENV ZK_HOST=zoo1
ENV JAVA_OPTS="-server -Xms6048m -Xmx6048m -XX:+UseParNewGC - XX:+UseConcMarkSweepGC -XX:+UseTLAB -XX:NewSize=128m -XX:MaxNewSize=128m - XX:MaxTenuringThreshold=0 -XX:SurvivorRatio=1024 - XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=40 - XX:MaxGCPauseMillis=1000 -XX:InitiatingHeapOccupancyPercent=50 - XX:+UseCompressedOops -XX:ParallelGCThreads=8 -XX:ConcGCThreads=8 - XX:+DisableExplicitGC -Dspring.profiles.active=${ENV_SETTINGS}"

EXPOSE 8080
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
HEALTHCHECK CMD curl --fail -k https://localhost:8080/status || exit 1

docker-compose.yml

docker-compose.yml

version: '3.1'

services:
api:
    image: SOME_RANDOM_IMAGE
    ports:
        - "9083:8080"
    networks:
        - net
    deploy:
        restart_policy:
            condition: on-failure
        mode: global
    environment:
        - ENV_SETTINGS: default,ssldev,postgres
        - ZK_HOST: zoo1:2181,zoo2:2181
networks:
nsp_net:
  external:
    name: net


推荐答案

时在Dockerfile中的ENV 语句中, docker build 步骤完全扩展了该范围,并嵌入了所构建映像中的扩展值。 Docker没有提供在 docker run 时重新扩展环境变量的步骤。也就是说,您的问题不是 ENV_SETTINGS 没有设置,而是 JAVA_OPTS 没有被重新解释。 ENV_SETTINGS 的新值。

When you write an ENV statement in a Dockerfile, the docker build step fully expands that and "bakes in" the expanded value in the image it builds. Docker does not provide a step that will re-expand environment variables at docker run time. That is, your issue is not that ENV_SETTINGS is not getting set, but rather that JAVA_OPTS is not getting reinterpreted with the new value of ENV_SETTINGS.

要解决此问题,您可以提供一个设置环境的Shell脚本。我倾向于将图像分为两部分:

To work around this, you can provide a shell script that sets up the environment. I tend to structure images that need this in two parts:


  1. 图像的ENTRYPOINT是设置环境变量并进行其他准备工作的脚本,并以 exec $ @ 结尾以运行映像的CMD或传递给 docker run 的任何命令。

  2. 图像的CMD是您要运行的实际命令。

  1. The image's ENTRYPOINT is a script that sets up environment variables and does other preparation, and ends with exec "$@" to run the image's CMD or whatever command got passed to docker run.
  2. The image's CMD is the actual command you want it to run.

您的shell脚本可能看起来像像这样:

Your shell script might look like this:

#!/bin/sh
JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=${ENV_SETTINGS:-ssldev}"
exec "$@"

相应的Dockerfile如下所示:

The corresponding Dockerfile would look like:

FROM openjdk:8-jdk-alpine
# Don't declare VOLUME of anything, especially not system directories.
# Prefer COPY to ADD.
COPY sample-0.0.1-SNAPSHOT.jar app.jar
# Should be executable (chmod +x) as checked into source control.
COPY entrypoint.sh entrypoint.sh

ENV ENV_SETTINGS=ssldev
ENV ZK_HOST=zoo1
# Don't include -Dspring.profiles.active here.
# Do include -Djava.security.egd here.
# The JVM knows about $JAVA_OPTS.
ENV JAVA_OPTS="-server -Xms6048m -Xmx6048m -XX:+UseParNewGC - XX:+UseConcMarkSweepGC -XX:+UseTLAB -XX:NewSize=128m -XX:MaxNewSize=128m - XX:MaxTenuringThreshold=0 -XX:SurvivorRatio=1024 - XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=40 - XX:MaxGCPauseMillis=1000 -XX:InitiatingHeapOccupancyPercent=50 - XX:+UseCompressedOops -XX:ParallelGCThreads=8 -XX:ConcGCThreads=8 - XX:+DisableExplicitGC -Djava.security.egd=file:/dev/./urandom"

EXPOSE 8080
ENTRYPOINT ["./entrypoint.sh"]
# Prefer quoted-word form.  But if you need a shell to process the
# command line, use unquoted form; don't explicitly "sh -c".
CMD ["java", "-jar", "app.jar"]
HEALTHCHECK CMD curl --fail -k https://localhost:8080/status || exit 1

(我总是更喜欢CMD而不是ENTRYPOINT:这种包装模式非常有用且无处不在,以至于更好使其可用,并且 docker run --rm -it imagename sh 要获得交互式调试外壳,如果不必重写入口点,则要容易得多例外是,如果我正在构建 FROM暂存器映像,那么除了运行捆绑的二进制文件外,实际上什么也做不了,但这是一个例外。)

(I always prefer CMD to ENTRYPOINT: this wrapper pattern is useful and ubiquitous enough that it's better to have it available, and it's much easier to docker run --rm -it imagename sh to get an interactive debugging shell if you don't have to override the entrypoint to do it. The exception is if I'm building a FROM scratch image where it's literally impossible to do anything other than run the bundled binary, but that's an exception.)

(还要注意,从Java 8的修补程序版本开始,较新的JVM可以选择遵循容器的内存限制,从而导致 JAVA_OPTS较小设置;请参见 openjdk映像文档。)

(Also note that newer JVMs, starting with a patch release of Java 8, have options to honor the container's memory limits, which leads to a much smaller JAVA_OPTS setting; see "Make JVM respect CPU and RAM limits" on the openjdk image documentation.)

这篇关于在运行时将带有docker-compose.yml的ENV变量传递给Dockerfile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆