仅在第一次启动时在Docker Container中运行命令

时间:2016-06-15 13:23:21

标签: docker

我有一个Docker Image,它使用脚本(/bin/bash /init.sh)作为入口点。我想只在第一次启动容器时执行此脚本。在docker守护程序崩溃后重新启动或重新启动容器时应该省略它。

有没有办法用docker本身做这个,或者如果必须在脚本中实现某种检查呢?

4 个答案:

答案 0 :(得分:11)

docker容器的入口点告诉docker守护程序当你想要运行"那个特定的容器。让我们问问题"容器第二次启动时应该运行什么?"或者"重新启动后容器应该运行什么?"

或许,你正在做的是采用与你做的相同的方法"老派"供应机制。你的脚本是"安装"所需的脚本,您将运行您的应用程序作为systemd / upstart服务,对吧?如果你这样做,你应该把它改成更多" dockerized"定义。

该容器的入口点应该是实际启动应用程序而不是设置的脚本。让我们说你需要安装java才能运行你的应用程序。所以在dockerfile中你设置了基本容器来安装你需要的所有东西:

FROM alpine:edge

RUN apk --update upgrade && apk add openjdk8-jre-base
RUN mkdir -p /opt/your_app/ && adduser -HD userapp

ADD target/your_app.jar /opt/your_app/your-app.jar
ADD scripts/init.sh /opt/your_app/init.sh

USER userapp
EXPOSE 8081

CMD ["/bin/bash", "/opt/your_app/init.sh"]

我们工作的公司的容器,在init.sh脚本中运行实际应用程序之前,他们从consul获取配置(而不是提供挂载点并将配置放在主机内或将它们嵌入到容器中)。所以脚本看起来像:

#!/bin/bash

echo "Downloading config from consul..."
confd -onetime -backend consul -node $CONSUL_URL -prefix /cfgs/$CONSUL_APP/$CONSUL_ENV_NAME
echo "Launching your-app..."
java -jar /opt/your_app/your-app.jar

我可以给你的一个建议是(在我使用容器时非常短暂的经验)将容器视为配置后的无状态(在入口点之前运行的所有命令)。

答案 1 :(得分:7)

我有同样的问题,这里有一个简单的程序(即解决方法)来解决它:

第1步:

创建一个包含以下代码的“myStartupScript.sh”脚本:

CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER"
if [ ! -e $CONTAINER_ALREADY_STARTED ]; then
    touch $CONTAINER_ALREADY_STARTED
    echo "-- First container startup --"
    # YOUR_JUST_ONCE_LOGIC_HERE
else
    echo "-- Not first container startup --"
fi

第2步:

仅在第一次启动容器时,将“#YOUR_JUST_ONCE_LOGIC_HERE”行替换为您要执行的代码

第3步:

将scritpt设置为Dockerfile的入口点:

ENTRYPOINT ["/myStartupScript.sh"]

总之,逻辑非常简单,它检查文件系统中是否存在特定文件;如果没有,它会创建它并执行你曾经的代码。下次启动容器时,文件位于文件系统中,因此代码不会执行。

答案 2 :(得分:2)

我必须这样做,最后我做了一个docker run -d,它刚刚创建了一个分离的容器并启动了bash(在后台),然后是docker exec,它做了必要的初始化。这是一个例子

docker run -itd --name=myContainer myImage /bin/bash
docker exec -it myContainer /bin/bash -c /init.sh

现在,当我重新启动容器时,我可以做到

docker start myContainer
docker attach myContainer

这可能不太理想但对我来说很好。

答案 3 :(得分:1)

我想在Windows容器上做同样的事情。它可以在Windows上使用任务调度程序来实现。任务Scheduler的Linux等价物是cron。你可以在你的情况下使用它。要执行此操作,请编辑dockerfile并在末尾添加以下行

WORKDIR /app 
COPY myTask.ps1 . 
RUN schtasks /Create /TN myTask /SC ONSTART /TR "c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe C:\app\myTask.ps1" /ru SYSTEM

这创建一个名为myTask的任务运行它的ONSTART,并且它自己的任务是执行位于" c:\ app \ myTask.ps1"的

此myTask.ps1脚本将执行您在容器启动时需要执行的任何初始化。确保在成功执行后删除此任务,否则它将在每次启动时运行。要删除它,可以在myTask.ps1脚本的末尾使用以下命令。

schtasks /Delete /TN myTask /F