Run the command in the Docker container only on first run

I have a Docker image that uses Script ( /bin/bash /init.sh ) as an Entrypoint. I would like to execute this Script only on the first start of the container. It should be omitted when containers restart or start again after a docker daemon crashes.

Is there a way to do this with the docker itself or do it if you need to do some validation in a script?

+7
docker
source share
3 answers

The entry point for the docker container tells the docker daemon that it needs to be started when you want to "start" this particular container. Ask the question "what should the container run when it starts a second time?" or "what should the container run after rebooting?"

It is likely that what you are doing follows the same approach you use with the old school initialization mechanisms. Your script "installs" the necessary scripts, and you run your application as a systemd / upstart service, right? If you do this, you should change this to a more "documented" definition.

The entry point for this container should be a script that actually launches your application, rather than configuring it. Let's say you need to install java to run your application. Therefore, in the dockerfile you install the base container to install all the things you need:

 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"] 

Our containers in the company I'm working on, before running the real application in the init.sh script, they extract the configs from the consul (instead of providing a mount point and placing configurations inside the host or embed them in the container). Thus, the script will look something like this:

 #!/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 

One piece of advice I can give you is (in my very short experience with containers) to handle your containers as if they were stateless after they were provided (all the commands that you ran before the entry point).

+9
source share

I wanted to do the same in a Windows container. This can be achieved using the task scheduler on windows. The Linux equivalent for the Scheduler task is cron. You can use this in your case. To do this, edit the docker file and add the following line to the end

 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 

This creates a task called myTask that launches it ONSTART, and the task itself is to execute a powershell script placed in "c: \ app \ myTask.ps1".

This myTask.ps1 script will do whatever initialization is needed to start the container. Make sure that you delete this task after it succeeds or run it every time you run it. To remove it, you can use the following command at the end of myTask.ps1 script.

 schtasks /Delete /TN myTask /F 
+1
source share

I had to do this, and I finished creating docker run -d , which just created a separate container, and ran bash (in the background), and then docker exec , which performed the necessary initialization. here is an example

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

Now, when I restart the container, I can just do

 docker start myContainer docker attach myContainer 

This may not be perfect, but works fine for me.

0
source share

All Articles