我正在将Tomcat应用程序部署到Docker上,并且目前正在运行,但前提是我初始化了一些配置并在启动容器后手动运行了它。
我的Dockerfile的简化版本如下:
FROM tomcat:9.0.10-jre8
COPY setEnv.sh /usr/local/tomcat/bin
RUN chmod +x /usr/local/tomcat/bin/setEnv.sh
ADD application.war /usr/local/tomcat/webapps/
RUN /usr/local/tomcat/bin/setEnv.sh # set $JAVA_OPTS
CMD /usr/local/tomcat/bin/startup.sh # start Tomcat application
我用以下容器启动容器
docker run -ti -p 8080:8080 --rm --name app app-image
但是当我启动容器时,什么也没有发生,容器就退出了。我尝试改用-d标记,但没有帮助。
我可以运行它的唯一方法是运行:
docker run -ti -p 8080:8080 --rm --name app app-image bash
当打开外壳脚本时,$ JAVA_OPTS为空,因此我必须手动运行setEnv.sh,然后在手动运行startup.sh之后,我的应用程序成功部署到了Docker。
但是显然这不是理想的选择,因为我不想每次都必须手动运行setEnv.sh。但是,如果我能够通过Dockerfile运行setEnv.sh以便在运行时设置$ JAVA_OPTS,那应该可以解决我的问题。
要进行此项工作,我需要在此处进行哪些更改?我的Dockerfile或我的容器运行方式有问题吗?
答案 0 :(得分:2)
之所以不起作用(但当您运行bash中描述的步骤时起作用)的原因是,Dockerfile的每个步骤都运行一个独立的进程-在步骤之间不共享环境。
如果需要在Dockerfile中设置环境变量,请按常规方法进行would be using the ENV
directive。这样,您可以执行以下操作来设置环境变量:
ENV JAVA_OPTS="-..."
您还可以同时设置多个:
ENV JAVA_OPTS="-..." OTHER_VAR="..."
如果您的脚本必须进行一些处理以找出要设置的正确环境变量,那么我认为最好的选择是更改startup.sh
脚本以调用或获取另一个脚本来获取正确的值。如果您无法更改startup.sh
,则可以创建一个包装脚本,该脚本在调用startup.sh
之前设置环境变量。
编辑:为实现包装脚本,我将执行以下操作:
#! /bin/sh
set -e
/usr/local/tomcat/bin/setEnv.sh # Call this however you did in your bash session where it worked
/usr/local/tomcat/bin/startup.sh "$@"
这将调用setEnv.sh
来设置环境变量,然后调用startup.sh
(传递可能已传递的任何参数)。
答案 1 :(得分:1)
如果选项更具动态性,这是入口点脚本的典型用法。您可以编写一个脚本,该脚本在容器启动时运行,并从Dockerfile获得CMD
或在docker run
命令末尾作为参数传递的任何内容。在这种情况下,这将非常简单:
#!/bin/sh
# Load in the environment variables
# ("." is the same as "source", but works in all POSIX shells)
. /usr/local/tomcat/bin/setEnv.sh
# Run the CMD (keeping it as pid 1)
exec "$@"
然后您可以将其包含在Dockerfile中
FROM tomcat:9.0.10-jre8
COPY setEnv.sh entrypoint.sh /usr/local/tomcat/bin/
RUN chmod +x /usr/local/tomcat/bin/entrypoint.sh
COPY application.war /usr/local/tomcat/webapps/
ENTRYPOINT ["/usr/local/tomcat/bin/entrypoint.sh"]
CMD ["/usr/local/tomcat/bin/startup.sh"]
此方法的另一个重要之处是,如果您认为图像中可能有问题,则可以按照通常的方式在新容器中安装壳
docker run --rm -it myimage sh
,无需尝试记住--entrypoint
的语法,并且仍然可以进行首次设置。 (它将运行入口点脚本,该脚本将设置环境变量,然后设置exec sh
。)