Managing Multiple Docker Compose Apps as Systemd Services on Ubuntu
While working with multiple project and then having multiple docker-compose.yml per project everytime I faced issues
like
- Stop Old docker-compose service
- Data miss management if forgot to remove some service
- Setting up data for different service
- Some time accidentally removing data for other service
- Different networks to communicate within docker setup was a headche
So If you are running several applications (like PostgreSQL, Redis, or Nginx) using individual Docker Compose files, managing them manually can become a headache. You want them to start automatically on boot, stop gracefully to prevent data corruption, and run with high performance.
In this guide, we’ll set up a Template Systemd Service that allows you to manage any number of .yml files as native Ubuntu services.
The Goal
- One Service to Rule Them All: Use a single template for multiple apps.
- Host Networking: Direct port access for maximum performance.
- Data Persistence: Ensure databases keep their data after a reboot.
- Native Integration: Use
systemctlto start, stop, and check logs.
1. Organize Your Files
First, place all your Docker Compose files in a central directory, such as /opt/docker. Name them clearly based on the application.
1/opt/docker/
2├── postgres.yml
3├── redis.yml
4└── nginx.yml
2. Create the Magic Template
We will use a systemd "Template Unit." The @ symbol in the filename allows us to pass the application name as a variable.
Create the file: sudo nano /etc/systemd/system/docker-compose@.service
Paste this configuration:
1[Unit]
2Description=Docker Compose Service for %i
3Requires=docker.service
4After=docker.service
5
6[Service]
7Type=oneshot
8RemainAfterExit=yes
9WorkingDirectory=/opt/docker
10
11# %i is the variable passed from the command line
12ExecStart=/usr/bin/docker compose -f %i.yml up -d
13ExecStop=/usr/bin/docker compose -f %i.yml down
14
15[Install]
16WantedBy=multi-user.target
Why these settings?
-
Type=oneshot & RemainAfterExit=yes: Docker Compose starts the containers and exits. These settings tell systemd to keep the service marked as "Active" so it can track the status.
-
ExecStop: Ensures that when you shut down the server,
docker compose downis called, saving your database state safely.
3. Prepare Your Docker Compose Files
To ensure your apps run on the host network and save data properly, your .yml files should follow this pattern:
1name: postgres
2services:
3 postgres:
4 network_mode: "host"
5 image: "postgres:18.1-alpine3.23"
6 environment:
7 - 'POSTGRES_USER=postgres'
8 - 'POSTGRES_PASSWORD=postgres'
9 - 'POSTGRES_DB=postgres'
10 volumes:
11 - ./pgdata:/var/lib/postgresql/data/
4. Enable and Start
Now for the best part. To start your PostgreSQL service, you simply "instantiate" the template by adding the filename (without .yml) after the @:
1# Reload systemd to recognize changes
2sudo systemctl daemon-reload
3
4# Start and enable Postgres
5sudo systemctl enable --now docker-compose@postgres
5. Useful Management Commands
Service Management Reference
Use these commands to manage your Docker Compose applications through systemd. Replace @postgres with your specific service name (e.g., @redis, @nginx) as needed.
| Action | Command |
|---|---|
| Check Status | systemctl status docker-compose@postgres |
| View Live Logs | journalctl -u docker-compose@postgres -f |
| Restart App | systemctl restart docker-compose@postgres |
| Stop App | systemctl stop docker-compose@postgres |
Tip: Adding the
-fflag to thejournalctlcommand allows you to "follow" the logs in real-time, which is perfect for debugging startup issues.
Example
1sudo journalctl -u docker-compose@postgres.service -f