在Dockerfile中覆盖inheritance的CMD并不总是工作?
我在派生的Dockerfile中覆盖CMD时遇到了一些不一致的行为。
基本的Dockerfile看起来像这样:
FROM myVeryBaseImage ENV WEBAPP_CONTEXT=my-app WORKDIR /opt/${WEBAPP_CONTEXT} COPY app/*.jar ./${WEBAPP_CONTEXT}.jar COPY baseconfig/* ./config/${WEBAPP_CONTEXT}/ CMD java -jar ${WEBAPP_CONTEXT}.jar --Dspring.profiles.active=docker
这个基础图像是由另一个团队提供的,很难改变它。 我现在正在编写一堆容器,我想要多次运行相同的应用程序,但使用不同的configuration。
所以我想我会延长图像复制一些更多的configuration到它并运行一个不同的弹簧configuration文件:
FROM baseImage COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ CMD java -jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=${PROFILE}
在docker-compose.yml中:
myapp-foo: build: ./myapp-custom image: myapp-custom environment: PROFILE: foo volumes: - /opt/my-app/foo:/opt/my-app myapp-bar: image: myapp-custom environment: PROFILE: bar volumes: - /opt/my-app/bar:/opt/my-app
我希望有两个容器运行,分别使用application-foo.properties
和application-bar.properties
。
看起来,虽然,都使用appplication-docker.properties,即在基础Dockerfile中定义的docker
configuration文件。
如果我完全改变派生的Dockerfile中的CMD,它将起作用:
CMD echo "${PROFILE}"
输出分别是“foo”和“bar”。 任何提示可能会发生什么?
我的版本是:
docker-compose version 1.8.1, build 878cff1 Docker version 1.12.3, build 6b644ec
更新:
在@ blackibiza的build议之后,我将派生的Dockerfile更改为
FROM baseImage COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ ENTRYPOINT /opt/jdk1.8.0_102/bin/java CMD ["-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"]
没有docker-compose的东西,只是为了看看派生的图像是怎么样的。 我从java获得错误消息,试图运行容器。 检查图像给出以下内容:
$ docker inspect --format='{{.Config.Cmd}} {{.Config.Entrypoint}}' testapp [-jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=french] [/bin/sh -c /opt/jdk1.8.0_102/bin/java]
所以它仍然试图执行/bin/sh
而不是java。 这看起来不像我从文档中预期的那样。
Update2:使用CMD的JSON数组语法触发另一个问题:
FROM baseImage COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ CMD ["java", "-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"]
不会扩展${WEBAPP_CONTEXT}
的使用,从而导致错误
Error: Unable to access jarfile ${WEBAPP_CONTEXT}.jar
你正在寻找的是入口点的覆盖。 如Docker参考中所述 ,
如果你想在没有shell的情况下运行你的程序,那么你必须把这个命令作为一个JSON数组来表示,并给出可执行文件的完整path。 这个数组forms是CMD的首选格式。 任何附加参数都必须在数组中分别表示为string:
从 Ubuntu的
CMD [“/ usr / bin / wc”,“ – help”]
如果您希望您的容器每次都运行相同的可执行文件,则应考虑将入口点与CMD结合使用。 见进入点。
而使用Composer,你可以重写CMD参数,如下所述 :
db: command: '-d' ports: - 5432:5432
你应该定义一个入口点,这是你的情况:
ENTRYPOINT java CMD ["-jar", "${WEBAPP_CONTEXT}.jar"]
在你的具体情况下,我会主张将shell作为入口点,并用脚本覆盖CMD,如:
ENTRYPOINT /bin/sh CMD ["./script.sh"]
并在您撰写的YML:
command: './script2.sh'
更新(根据更改的问题):
它缺less的是variables的定义。 在这种情况下,我build议使用ARG而不是ENV来构build传入永久值的容器:
docker build -t your_image:your_version --build-arg WEBAPP_CONTEXT=your_context .
在构build时获得价值替代。 ARG的优点是可以inheritance您的孩子的形象
不要复制和粘贴错误的Java命令。 如果它位于.jar
文件之后,则不会识别-Dspring.profile.active
参数。
修复CMD线
CMD java -jar -Dspring.profiles.active=${PROFILE} ${WEBAPP_CONTEXT}.jar
一切都很好。
另请参见“ 在spring引导中从命令行设置活动configuration文件和configuration位置 ”