An Idiosyncratic Blog

🧟‍♂️ How to keep a Docker container alive

Published on
·
2 minutes read

Docker is a great tool. It helps you build software with consistent environment across all platforms, so that you don't have to worry about 'It works on my machine' issues. Simply put, Docker provides capabilities to create an Operating System without a User Interface. You can do everything that you normally do on an OS, like running servers, installing packages, even browse the internet, but using just the command prompt. In Docker terms, it's called an image.

Running an instance of a Docker image, is known as a container. You can run multiple container of the same image.

Before you continue, make sure you install docker using the recommended steps for your operating system.

A basic NodeJS application Dockerfile would look something like this:

FROM node:10-alpine
WORKDIR /home/node/app
COPY ./my-app ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "app.js" ]

The app works as expected when running using node app.js directly on the terminal, but fails when running using Docker. In such cases, we usually peek at logs to figure out what went wrong. So we print the logs,

$ docker logs --tail=50 <container id>

Uh-oh! No logs. I've faced scenarios where there were no logs, so the above command was as useless as red lights in Grand Theft Auto. What if I enter into the container using docker exec command and debug what's wrong? To do that, the container should be running. Catch-22!

Here are a couple of ways I found to keep the container running, and be able to inspect what's going on in the container.

Do not try this on prod

Obviously the techniques below are intended for development only. If you're using these to keep the container alive in prod, even though the main process has exited, what is wrong with you!?

When using a Dockerfile, any one of these options should do the trick.

ENTRYPOINT ["tail", "-f", "/dev/null"]
CMD ["tail", "-f", "/dev/null"]
CMD ["sleep", "infinity"]

With a docker-compose.yml file,

version: '3'
services:
  app:
    image: node:10-alpine
    tty: true

Use the entrypoint option in the compose file which to override the CMD from the Dockerfile.

Another option is to use command option and specify the same commands which were used in Dockerfile above.

version: '3'
services:
  app:
    image: node:10-alpine
    command: tail -F /dev/null

Now the containers are always running, use docker exec to enter the container and debug the program.