3 min read

Systemd and Docker Compose: A Dynamic Duo for Efficient Deployments

Docker-compose utility gives flexibility to deploy simple applications. You can make it robust by integrating it with systemd services.
Systemd and Docker Compose: A Dynamic Duo for Efficient Deployments

Docker Compose is like a handy tool for putting together simple apps. It lets you start a bunch of connected parts (we call them containers) all at once, creating a single app. It's pretty easy to use and set up.

But for really big and complicated apps, there are other tools like Docker Swarm or Kubernetes that might work better. They're like supercharged versions, with extra features and power, perfect for the big leagues of software.


Table fo contents

Introduction

Docker Compose makes it super easy to set up simple applications. But there's a little catch: when the server restarts, the Docker containers don't start on their own. No worries, though! We can fix this by creating a custom systemd service. Let's start from the beginning to understand how.

What is systemd service?

A systemd service is a script or executable that is managed by the systemd process, which controls the behavior and status of these underlying services.

  • Handy & Simple to operate: Handling services is simple and easy as they can be used as system component instead of decoupled program.
  • Start Automatically: They can be set up to begin working as soon as the computer starts up, which is super convenient.
  • Quick Fixes: If something goes wrong, they can quickly get back to work without causing too much trouble.

Steps to Create systemd Service

To create systemd service we need to write a service file which will execute command or script in case of start, stop and restart actions.

So in case of docker-compose application we need to have docker-compose.yml file which has definition of all the services and then using docker-compose up -d  command we can give start action for the service, similarly for stop we can use docker-compose stop command.

Let's see step by step:

  • Write docker-compose.yml file with all services/components, below is the django app example taken from docker documentation.
version: "3.9"
   
services:
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
Example from docs.docker.com
  • For testing purpose you can bring the application up by using docker-compose up command, additionally we can have -d flag for running application as daemon
# will bring up all services in docker-compose.yml
docker-compose up -d

# pass yml file with -f flag
docker-compose up -f application.yml
  • Once, application is working correctly we can have service for this application by writing service file and placing it in /etc/systemd/system directory
  • Create file /etc/systemd/system/myapp.service with below content - note ExecStart and ExecStop directives - each will be used as starting and stopping command for the service respectively
[Unit]
Description=Service for myapp
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
WorkingDirectory=/root/bootvar
Environment=COMPOSE_HTTP_TIMEOUT=600
ExecStart=/usr/bin/env /usr/bin/docker-compose -f /root/bootvar/docker-compose.yml up -d
ExecStop=/usr/bin/env /usr/bin/docker-compose -f /root/bootvar/docker-compose.yml stop
StandardOutput=syslog
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
/etc/systemd/system/myapp.service
  • You can set environment variables using Environment directive or pass variables from a file
  • Once file is created you need to reload all system services using systemctl daemon-reload command
  • Now you have created myapp service, start the service using systemctl start myapp which will execute command/script defined in ExecStart
  • If you want to start your service whenever your server reboots then you need to enable it using systemctl enable myapp command which will ensure whenever your server boots up myapp service will be started
# will enable service to start at server bootup
systemctl enable myapp

# start service ( Executes ExecStart command )
systemctl start myapp

This way you can make sure your docker-compose service stays up and running after every server restart.

Conclusion

To turn a correctly working application into a service, you can write a service file and place it in the /etc/systemd/system directory. The service file, named myapp.service, should contain the starting and stopping commands for the service, specified in the ExecStart and ExecStop directives, respectively.

With a custom systemd service, the application can be automatically started when the server is restarted, overcoming the limitation of Docker Compose's lack of automatic start on reboot.