Pass ENV variable with docker-compose.yml at runtime to Dockerfile

巧了我就是萌 提交于 2020-07-10 08:34:25

问题


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:

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

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

回答1:


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.

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. 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.

Your shell script might look like this:

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

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

(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.)

(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.)



来源:https://stackoverflow.com/questions/53974736/pass-env-variable-with-docker-compose-yml-at-runtime-to-dockerfile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!