docker-compose
system startup
automation
devops
container management

How to run docker-compose up -d at system start up?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Running docker compose up -d automatically at boot is a common requirement for self-hosted services and internal tools. The reliable way to do this on Linux is a systemd unit that starts after Docker and network availability. You can also use cron @reboot, but systemd gives better ordering, restart behavior, and observability.

Use a Dedicated systemd Service

A systemd service lets you define startup dependencies, working directory, and stop behavior in one place. This is the preferred approach for long-term maintenance.

Create a unit file:

bash
sudo nano /etc/systemd/system/myapp-compose.service

Example unit:

ini
1[Unit]
2Description=MyApp Docker Compose Stack
3Requires=docker.service
4After=docker.service network-online.target
5Wants=network-online.target
6
7[Service]
8Type=oneshot
9RemainAfterExit=yes
10WorkingDirectory=/opt/myapp
11ExecStart=/usr/bin/docker compose up -d
12ExecStop=/usr/bin/docker compose down
13TimeoutStartSec=0
14
15[Install]
16WantedBy=multi-user.target

Then enable and start:

bash
1sudo systemctl daemon-reload
2sudo systemctl enable myapp-compose.service
3sudo systemctl start myapp-compose.service
4sudo systemctl status myapp-compose.service

This ensures your stack starts at boot and can be managed through normal service commands.

Choose the Correct Compose Command Path

Many failures come from mismatched binary paths. Modern setups often use docker compose plugin, while older setups use standalone docker-compose.

Check what exists:

bash
which docker
which docker-compose
docker compose version

If your server only has the standalone binary, unit file commands should use /usr/local/bin/docker-compose or whichever path is actually installed.

A safe check before enabling startup automation is to run the exact startup command manually from the same directory:

bash
cd /opt/myapp
/usr/bin/docker compose up -d

If this command fails manually, the unit will fail too.

Rootless and Per-User Service Option

If Docker runs rootless under a specific user, use a user-level service instead of system-wide service.

Create user unit:

bash
mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/myapp-compose.service

User unit example:

ini
1[Unit]
2Description=MyApp Compose Stack (User)
3After=default.target
4
5[Service]
6Type=oneshot
7RemainAfterExit=yes
8WorkingDirectory=/home/dev/myapp
9ExecStart=/usr/bin/docker compose up -d
10ExecStop=/usr/bin/docker compose down
11
12[Install]
13WantedBy=default.target

Enable for user session:

bash
systemctl --user daemon-reload
systemctl --user enable myapp-compose.service
systemctl --user start myapp-compose.service

If you need this to run without active login, enable user lingering:

bash
sudo loginctl enable-linger dev

cron @reboot as a Minimal Alternative

cron can run a command at startup with less setup, but it is weaker for dependency management and logs.

bash
crontab -e

Add:

bash
@reboot cd /opt/myapp && /usr/bin/docker compose up -d >> /var/log/myapp-compose.log 2>&1

This can work for simple setups. The tradeoff is poorer lifecycle control compared with systemd.

Validation and Troubleshooting Workflow

After configuration, test reboot behavior explicitly.

bash
sudo reboot

After host returns:

bash
sudo systemctl status myapp-compose.service
docker ps
docker compose -f /opt/myapp/docker-compose.yml ps

If service failed, inspect logs:

bash
journalctl -u myapp-compose.service -b --no-pager

Useful diagnostics:

  • verify WorkingDirectory contains the compose file
  • verify compose file references images and volumes that exist
  • verify Docker daemon is healthy at startup
  • verify network dependencies are available if services require external systems

Common Pitfalls

A common pitfall is using the wrong compose binary path. Service starts but command fails immediately.

Another issue is missing WorkingDirectory, which causes compose to run from root directory and fail to find docker-compose.yml.

Many teams also omit After=docker.service, leading to race conditions where service runs before Docker is ready.

Using cron @reboot without log redirection is another frequent problem. Failures then look silent because output is discarded.

Finally, avoid running destructive ExecStop behavior for stacks that should persist across transient service restarts unless that shutdown is truly desired.

Summary

  • systemd is the best default for running Compose at startup.
  • Define startup ordering with Docker and network targets.
  • Validate binary path and working directory before enabling boot automation.
  • Use user-level services for rootless Docker workflows.
  • Keep a clear troubleshooting path with journalctl and post-reboot checks.

Course illustration
Course illustration

All Rights Reserved.