Skip to main content

Automating Docker Compose and Systemd Services in Linux

Recently, I completed a Go backend project. After building it according to my server’s system and architecture and uploading the binary file to the server, I discovered that if I closed the current Terminal window after running the program, it would stop. This is different from when I containerized the project with Docker and deployed it to the server; I could use docker compose up -d to keep the program running in the background.

After a series of explorations and trial and error, I used Systemd to manage the program’s automatic restart and stop. Here is the recorded process:

On the Linux server, go to the /etc/systemd/system directory:

cd /etc/systemd/system

Then create a .service file, such as automate-my-go-program.service, with the following content:

[Unit]
Description=Description of the program
After=network.target # Ensures our service starts only after the network is up and running

[Service]
ExecStart=/path/of/your/go/program # Location of the Go executable
WorkingDirectory=/path/of/your/program/working/dir # Your program's working directory
Restart=always
Environment=PORT=4000 # This and the next three are environment variables used by my program
Environment=DB_URL=some-url-content
Environment=JWT_SECRET=some-secret-content
Environment=SERVE_MODE=production

[Install]
WantedBy=multi-user.target

Save the file and exit, then run the following series of commands.

Reload systemd

sudo systemctl daemon-reload

Enable the program to start automatically at boot

sudo systemctl enable automate-my-go-program.service

Start the service

sudo systemctl start automate-my-go-program.service

This way, the program will run in the background and start automatically when the system reboots.


After solving this issue, I continued to use a similar method to solve the problem of Docker services not starting automatically after a reboot. Too lazy to describe, so I’ll just record the content:

[Unit]
Description=Start my Docker service
Requires=docker.service
After=docker.service

[Service]
Type=oneshot # Indicates that ExecStart is executed only once
RemainAfterExit=yes # Indicates that the service remains active after the ExecStart command is executed
WorkingDirectory=/path/of/your/program/working/dir # Your program's working directory
ExecStart=/usr/bin/docker compose start # Use the absolute path to locate the docker executable
ExecStop=/usr/bin/docker compose stop # If you use docker-compose, change the location to /usr/local/bin/docker-compose
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Happy Coding.