73

I have docker container with installed and configured software.

There is no any programm supposed to be started/runned all the time.

What I want - its ability to start some command depending on external events. like:

docker exec mysupercont /path/to/mycommand -bla -for

and

docker exec mysupercont /path/to/myothercommand 

But "exec" impossible when container is stopped, and also this container have some "working" data inside, which used for that commands, so I can't use

docker run ...

each time, because it recreate container from image and destroy my data.

What is the "right" and the "best" way to keep such container runned? Which command I can start inside?

2
  • This is a very well explained question. See another similar post here.
    – Grant Li
    Feb 4, 2016 at 16:29
  • 6
    docker run -d --name=name container tail -f /dev/null Jul 17, 2017 at 8:27

5 Answers 5

71

You do not need to perform each time docker run.

docker run is actually a sequence of two commands: "create" and "start".

When you run the container, you must specify the "-it":

-i, --interactive=false Keep STDIN open even if not attached
-t, --tty=false Allocate a pseudo-TTY

Example:

docker run -it debian:stable bash

After the work was completed command specified at startup (in my example bash). For example, you perform the "exit". Container stops:

CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS                     PORTS               NAMES
1329c99a831b        debian:stable              "bash"                 51 seconds ago      Exited (0) 1 seconds ago                       goofy_bardeen

Now you can start it again

docker start 1329c99a831b

The container is started and again executes the command "bash".
Connect to this session "bash" with the command

docker attach 1329c99a831b

To sum up: you have to understand the difference between the run and start container.
Besides, look at the documentation for the role of parameters "-i t" and "-d" for the "Run"

5
  • 1
    aha, i understand this. Question was: I have nothing to run inside container, but i need to keep it in "run" state So your answer is - use bash to keep container in running state? Jan 27, 2015 at 9:01
  • Yes.The process that you specified at run time must be running to the container continued to work. The simplest example is bash. Perhaps you will be the easiest way to start the container with the "-d" and connect to it as needed using the docker attach ID. Get out of this session without ending bash, you can use CTRL-p CTRL-q
    – MSemochkin
    Jan 27, 2015 at 13:30
  • Process that you specify during of the container run receives the PID 1. Accordingly, the container simply can not work without it ☺
    – MSemochkin
    Jan 27, 2015 at 18:28
  • My experience with start and attach (or start with -ai) is that the prompt and interactive editing of your command line doesn't show. EG the tty isn't rendering or echoing.
    – dlamblin
    Aug 2, 2015 at 23:44
  • 1
    This is nifty. Note that if you want to start the container in the background without having to manually start it again (say if you're running a web service), use '-itd' parameters, and CTRL-p CTRL-q to detach without stopping the container.
    – taranaki
    Feb 23, 2017 at 1:26
31

Since you mentioned periodic tasks and you are probably using something like cron because of the way you want to use docker exec, I have just the medicine for you. At least I ended up doing something like this.

  1. Dockerfile

    FROM <some base>
    CMD tail -f /dev/null
    
  2. Run with the usual docker run -d .... (I used docker-compose)

  3. Setup host machines crontab, for example:

    * * * * * docker exec mysupercont foo >> /var/log/foo.log 2>&1
    * * * * * docker exec mysupercont bar >> /var/log/bar.log 2>&1
    

I find this solution nice as we get to rely on the ancient and proven crontab in a pretty default linux environment, while Docker handles your business logic's more exotic deps and environment variables. You can also set some limits if your periodic tasks get stuck & have memory leaks or whatever.

2
  • ingenious! works great.
    – scravy
    Nov 16, 2020 at 3:35
  • this is actually really clever !
    – pyrsmk
    Apr 15, 2022 at 13:50
16

Tail will still causes some file operations from time to time.

Sleep Forever, without any side effects

# Ah, ha, ha, ha, stayin' alive...
while :; do :; done & kill -STOP $! && wait $!

How it works

while :;           # Run an endless loop,
do :;              # of do nothing,
done &             # as background task.
kill -STOP $!      # Stop the background task.
wait $!            # Wait forever, because background task process has been stopped.
8
  • 1
    hard to understand what its doing. why not just sleep 3650d
    – Pieter
    Aug 21, 2019 at 23:58
  • 1
    You're right, sleep would probably work as good as my solution, however sleep will time out eventually :-D PS: I will add some comments, to make my solution easy to understand.
    – qoomon
    Aug 23, 2019 at 5:45
  • how about $! is reused by others?
    – user565230
    Mar 23, 2020 at 16:22
  • 2
    LOL this hack worked :p Oct 24, 2020 at 18:34
  • 1
    IMO its better than "tail -F /dev/null" because when I go to stop the container it responds to the SIGTERM and stops immediately. While using the tail command, you may notice it seems to ignore the request to be stopped, so then Docker has to resort to using force stop it after so many seconds.
    – b01
    Aug 7, 2021 at 1:57
11

This whole business of whether or not you can start a stopped container, is dependant on how the container was originally created, i.e. run. If you ran a command that ended, or you exit an interactive command, e.g. bash, you can't start, restart or exec the stopped container. All you can do is remove it. It's junk.

But taranaki's last comment, use '-itd', seems to be what the docker ordered.

The container keeps running, and you can exec whatever you want, and you can stop, start or restart the container. Of course, this is just a preliminary finding based on the alpine image. Note, if you attach to the container, it will stop when you exit, but you can start it again.

3
  • 5
    +1 "seems to be what the docker ordered" :-) Mar 29, 2018 at 5:19
  • Ditto :D I'm stealing this.
    – grefly
    Aug 14, 2020 at 16:06
  • So if you run docker run -itd myspercont /bin/bash, then the docker image keeps running on the background and also react properly (and quickly) on docker stop - in some other solutions docker waits for timeout during stop attempt and then it is killed.
    – eNca
    Mar 23, 2021 at 7:12
2

I've used all of the proposed solutions here myself, but all of them do not handle SIGTERM signals coming from the Docker daemon when it wants to shut down the container (e.g. docker stop $containername).

So I propose the following:

FROM base:image
# ...
CMD sh -c 'trap "exit" TERM; while true; do sleep 1; done'

It is basically a short shell script that first intercepts ("traps") SIGTERM signals and then goes to sleep for a second in an infinite loop.

I mainly use it together with docker-compose and ofelia to supply side-car containers to backup some other service in another container (e.g. MariaDB databases).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .