Start a process when the container starts

When you are working in a development container, you may want to execute a command or start something each time the container starts. The easiest way to do this is using the postStartCommand property in devcontainer.json. For example, if you wanted to run yarn install every time you connected to the container to keep dependencies up to date, you could add the following:

"postStartCommand": "yarn install"

Video: Run npm install when a container is created



In other cases, you may want to start up a process and leave it running. This can be accomplished by using nohup and putting the process into the background using &. For example:

"postStartCommand": "nohup bash -c 'your-command-here &'"

Video: Run 'npm start' whenever the container is started



Those familiar with Linux may expect to be able to use the systemctl command to start and stop background services managed by something called systemd. Unfortunately, systemd has overhead and is generally not used in containers as a result.

In many cases, there is a command you can run instead (for example, sshd). And on Debian/Ubuntu, there are often scripts under /etc/init.d that you can run directly.

"postStartCommand": "/etc/init.d/ssh start"

These systems also include a service command that will use systemctl or /etc/init.d scripts based on what is installed.

"postStartCommand": "service ssh start"

Video: Start SSH service in a container

Adding startup commands to the Docker image instead

While postStartCommand is convenient and allows you to execute commands in your source tree, you can also add these steps instead to a Dockerfile using a custom ENTRYPOINT or CMD.

When referencing a Dockerfile in devcontainer.json, the default entrypoint and command is overridden. First, disable this behavior using the overrrideCommand property.

"overrideCommand": false

The overrideCommand property defaults to true because many images will immediately exit if a command is not specified. Instead, we will need to handle this in our Dockerfile.

Next, consider this Dockerfile:

FROM mcr.microsoft.com/vscode/devcontainers/base:0-focal

COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "sleep", "infinity"' ]

The CMD here makes sure the container stays running by default. Keeping your startup steps in the ENTRYPOINT allows you to safely override the command when using docker run with your image or using Docker Compose. This resolves to the following:

/docker-entrypoint.sh sleep infinity

Next, create a docker-entrypoint.sh script:

#!/usr/env bash

echo "Hello from our entrypoint!"

exec "$@"

Anything you execute in this file will then fire each time the container starts. However, it's important to include the last exec "$@" line since this is what will cause the command sleep infinity in our example to fire.

Finally, if you are using Docker Compose, be sure that neither the entrypoint nor command properties are set for your container.