Running Docker Compose as a systemd Service: A Comprehensive Guide
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.
Managing Docker containers efficiently is crucial for seamless application deployment. Integrating Docker Compose with systemd allows for automatic startup and robust process management of your containerized applications. In this guide, we'll walk you through setting up Docker Compose as a systemd service, ensuring your applications are resilient and easy to manage.
Why Use systemd with Docker Compose?
Systemd is the init system for many Linux distributions, responsible for managing system services during boot and runtime. By creating a systemd service for your Docker Compose applications, you can:
- Ensure Automatic Startup: Your Docker containers will start automatically on system boot.
- Simplify Management: Utilize systemd commands to control your Docker services.
- Enhance Reliability: Systemd monitors services and can restart them upon failure.
Prerequisites
Before proceeding, ensure you have:
- A Linux system with systemd (e.g., Ubuntu 20.04).
- Docker and Docker Compose installed.
- A Docker Compose YAML file (
docker-compose.yml
) defining your services.
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.
- Automatic Startup: Ensure that your Docker containers start automatically when the system boots.
- Unified Management: Use familiar systemctl commands to manage your Docker Compose applications.
- Enhanced Reliability: Leverage systemd's process management capabilities to monitor and restart services as needed.
- Handy & Simple to operate: Handling services is simple and easy as they can be used as system component instead of decoupled program.
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 - noteExecStart
andExecStop
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 usingsystemctl start myapp
which will execute command/script defined inExecStart
- 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 upmyapp
service will be started - Adjust the
WorkingDirectory
to the location of yourdocker-compose.yml
. - Ensure the
ExecStart
andExecStop
paths point to your Docker Compose binary.
# 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.
Best Practices
- Environment Variables: If your application requires environment variables, define them within the
docker-compose.yml
or specify them in the systemd service file using theEnvironment
directive. - User Permissions: If running Docker as a non-root user, specify the
User
directive in the[Service]
section of the systemd service file. - Timeouts: Adjust
TimeoutStartSec
and other timeout settings as needed to ensure that services have adequate time to start and stop. - Logging: Redirect logs to syslog or a specific file by configuring the
StandardOutput
andStandardError
directives.
Troubleshooting
- Permission Issues: Ensure the user running the systemd service has the necessary permissions to manage Docker.
- Path Errors: Verify that the paths to
docker-compose
and your working directory are correct. - Service Not Starting on Boot: Confirm that the service is enabled and that there are no errors in the service file syntax.
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.
Frequently Asked Questions (FAQs)
1. Why should I use systemd instead of docker-compose up -d
?
Using systemd ensures that your Docker Compose services automatically restart on reboot, can be monitored, and follow a structured logging mechanism.
2. How do I check if my systemd service for Docker Compose is running correctly?
You can use the following command to check the status:
sudo systemctl status my-docker-compose
If there's an issue, logs can be checked using:
journalctl -u my-docker-compose --no-pager --lines=50
3. What happens if a container crashes?
If you've set the restart
policy in your docker-compose.yml
to always
or unless-stopped
, systemd will restart the container automatically when it crashes.
4. Can I run multiple Docker Compose projects with systemd?
Yes, but each project should have a separate systemd service file. Ensure each service file points to the correct docker-compose.yml
location.
5. How can I update my Docker Compose service without stopping the entire systemd service?
You can update containers and reload systemd as follows:
cd /path/to/your/docker-compose
docker-compose pull
docker-compose up -d
sudo systemctl daemon-reload
sudo systemctl restart myapp
6. How can I ensure my Docker Compose service starts on boot?
Enable the service to start at boot using:
sudo systemctl enable myapp
7. Does systemd support logging for Docker Compose services?
Yes, systemd captures logs for your services. View logs using:
journalctl -u my-docker-compose -f