【问题标题】:How can I initialize a Docker container with the result of running a shell script?如何使用运行 shell 脚本的结果初始化 Docker 容器?
【发布时间】:2018-07-25 18:16:25
【问题描述】:

我正在将 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

当 shell 脚本打开时,$JAVA_OPTS 是空的,所以我必须手动运行 setEnv.sh,然后在手动运行 startup.sh 后,我的应用程序成功部署到 Docker 上。

显然这并不理想,因为我不想每次都手动运行 setEnv.sh。但是,如果我能够通过 Dockerfile 运行 setEnv.sh 以便在运行时设置 $JAVA_OPTS,那应该可以解决我的问题。

我需要在此处进行哪些更改才能使其正常工作?是我的 Dockerfile 问题还是我运行容器的方式有问题?

【问题讨论】:

    标签: docker tomcat containers dockerfile


    【解决方案1】:

    这不起作用的原因(但在运行 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(传递可能已传递的任何参数)。

    【讨论】:

    • 是的,我确实需要使用单独的 setEnv.sh 脚本,但为两者编写包装脚本是个好主意。不过,我如何在 Dockerfile 或 docker run 命令中实现它?在步骤之间不共享环境的相同问题是否仍然适用?理想情况下,我只想启动容器并立即调用包装脚本,初始化 $JAVA_OPTS 并运行启动脚本。
    【解决方案2】:

    如果选项更加动态,这是入口点脚本的典型用途。您可以编写一个在容器启动时运行的脚本,并从 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"]
    

    关于这种方法的另一个重要的事情是,如果您认为图像中可能有问题,您可以按照通常的方式在新容器中获取 shell

    docker run --rm -it myimage sh
    

    无需尝试记住--entrypoint 的语法,仍然可以进行首次设置。 (它将运行入口点脚本,该脚本将设置环境变量,然后设置exec sh。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-20
      • 2015-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多