Using "tail -f /dev/null" to keep container up fails unexpectedly Using "tail -f /dev/null" to keep container up fails unexpectedly docker docker

Using "tail -f /dev/null" to keep container up fails unexpectedly


Here is better way to keep the container running

sleep infinity


Once in some of mine testing environments /dev/null was a regular file somehow - maybe it is the case as well?

Otherwise I'd do echo EXIT CODE=$? as the second echo and dance from there.Additionally for testing - maybe try replacing tail with long sleep and then exec the tail command via docker exec and see if you can reproduce the same behavior.


To answer your question under what circumstances tail -f /dev/null might finish and therefore continue to the next line in something like a shell script:

/dev/null (as with everything in Linux) is a file. When executing tail onto any file, the file must be opened using a filedescriptor. It's not that tail -f /dev/null terminates because it's finished (it won't ever finish), it terminates because of interference with the filedescriptor which can happen due to a number of reasons, however, inside the container itself there is (most likely) nothing else happening that would interfere with the filedescriptor.

Since docker containers are just a somewhat fancy overlay of so called Linux namespaces all the processes that run inside a container (even if it is inside a separate PID namespace) actually run on your host.So for some reason your host is interfering with your filedescriptor.

To check for open filedescriptors created by a process you can execute the following command:

$ sudo ls -la /proc/<pid>/fd

You will see certain numbers in the output:

  • 0 stands for standard input.
  • 1 stands for standard output.
  • 2 stands for standard error.

The rest are files that are being opened by the process.

<pid> is the id of the process you want to look at. When running tail -f /dev/null as the entrypoint inside a container it is most likely going to have the pid 1 inside the container. In order to find the pid on your host machine you can simply grep for it like so:

$ sudo ps aux | grep 'tail -f /dev/null'

To close the filedescriptor yourself and manually reproduce what would happen in those cases you can use the GNU debugger gdb.Simply attach the debugger to the pid you found earlier:

$ sudo gdb attach <pid>

Now you can go ahead and choose which filedescriptor you want to close (most likely it is going to be number 3 since the process does not open any other files):

(gdb) call (int)close(3)$1 = 0

Now check the logs of your container while leaving the debugger:

(gdb) quit

Depending on your configuration you are likely to see an error coming from tail in the container logs:

tail: error reading '/dev/null': Bad file descriptor

As explained earlier, there is also a filedescriptor for standard error (2).You can repeat the entire process and close both the standard error and the actual filedescriptor during the same debugger session:

(gdb) call (int)close(2)$1 = 0(gdb) call (int)close(3)$2 = 0(gdb) quit

Upon doing so there won't be an error visible in the container logs and in case of a bash script it is going to proceed with the next line.

As to check what exactly is interfering with your filedescriptor you would have to extensively monitor your host system during the moment of the occurrence.