Authors – All

If you have a few years of experience in the DevOps ecosystem, and you're interested in sharing that experience with the community, have a look at our Contribution Guidelines.

1. Introduction

Docker is a tool that makes it easier to create, deploy, and run apps. It helps us bundle and run apps inside isolated environments known as containers. Thus, containers are small and have all we need to run them.

Further, the containers can run in any environment. This results in fast software delivery and avoids the common “it works on my computer” problem. We start services in containers by listing commands to run at start-up.

In this tutorial, we’ll look at how to auto-start services in a Docker container.

2. Using Dockerfile

Dockerfile contains a set of commands that Docker runs to build an image. Docker executes the instructions on a base Docker image. To that end, the base image serves as the starting point for a custom image. Dockerfile contains commands that are run on the base image to create the desired app image.

We define the services to auto-run on launch using a start-up script. Generally, that script includes configs, setup tasks, or service commands. We use the ENTRYPOINT or CMD instructions to start a service from a Dockerfile. Let’s see an example.

Firstly, we create a simple Dockerfile for a Spring Boot app:

FROM gradle:jdk13 AS build
COPY --chown=gradle:gradle . /home/gradle/project
WORKDIR /home/gradle/project
CMD ["gradle", "migrateLocal", "clean", "bootRun", "--info", "--no-daemon"]

The COPY command copies files and directories. In this case, it moves the contents of the current directory into the Docker images directory. Next, the WORKDIR command sets the working directory for the following commands. Lastly, the CMD command specifies the default command to run on the Docker container. Here, it runs the gradle command migrateLocal, clean, bootRun.

Secondly, let’s build the container:

$ docker build api
Building api
Step 1/4 : FROM gradle:jdk13 AS build
jdk13: Pulling from library/gradle
Digest: sha256:5c97028e6418d720ba5c669d9ccc3623ba332f2887fa37d342e38ca40336bc61
Status: Downloaded newer image for gradle:jdk13
 ---> 2678064c31a2
Step 2/4 : COPY --chown=gradle:gradle . /home/gradle/project
 ---> 20706d98f062
Step 3/4 : WORKDIR /home/gradle/project
 ---> Running in dc21d77656b8
Removing intermediate container dc21d77656b8
 ---> f45a39dcd905
Step 4/4 : CMD ["gradle", "migrateLocal", "clean", "bootRun", "--info", "--no-daemon"]
 ---> Running in a1a9a2aab156
Removing intermediate container a1a9a2aab156
 ---> fe6a70d28e4e
Successfully built fe6a70d28e4e
Successfully tagged localhost:5000/spring-boot-api:v1

This Dockerfile builds an image that runs a gradle-based app. It then runs the migrateLocal, clean, and bootRun commands. We’re passing the –info and –no-daemon options to run in non-daemon mode. As a result, we can log more detailed data about the whole process. When the container builds, the commands from the Dockerfile are auto-started.

3. Using Docker Compose

Docker Compose is a tool that lets us manage and run many containers in one file. Docker Compose allows us to define the services we want in a container via the docker-compose.yaml file.

First, let’s create a docker-compose.yaml file and add two services, postgresql and adminer, with an auto-restart policy:

version: '3.5'

services:
  postgresql: 
    image: postgres:9.6.6
    ports: 
    - 9932:5432 
    expose: 
    - "5432" 
    environment: 
    -  POSTGRES_PASSWORD=pass 
    restart: always 
    volumes: 
    - /data:/var/lib/postgresql/data
    
  adminer:
    image: adminer
    restart: always
    ports:
    - "8888:8080"

We set the RESTART option to always. This means Docker auto-starts the service if it stops or crashes. Also, we can customize the RESTART behavior by setting a different value. For instance, changing it to on-failure will only restart the services when they fail.

Next, let’s build and run the services:

$ docker-compose up -d
Creating network "adminer_default" with the default driver
Creating adminer_postgresql_1 ... done
Creating adminer_adminer_1    ... done

The -d flag runs docker-compose in detached mode. This means that the services are running in the background.

Finally, let’s check if the containers are up and running:

$ docker-compose ps
        Name                      Command               State           Ports
--------------------------------------------------------------------------------------
adminer_adminer_1      entrypoint.sh php -S [::]: ...   Up      0.0.0.0:8888->8080/tcp
adminer_postgresql_1   docker-entrypoint.sh postgres    Up      0.0.0.0:9932->5432/tcp

The ps subcommand shows our containers are up and running. However, if any container fails, docker-compose will auto-restart them.

4. Conclusion

In this article, we discuss a few ways to auto-start a service in a Docker container. Additionally, new Docker tools are coming up that can help us get the same results. Thus, it’s important to consider the need for and familiarity with available tools.

Authors – All

If you have a few years of experience in the DevOps ecosystem, and you're interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.