Skip to content

Instantly share code, notes, and snippets.

@mosquito
Last active May 22, 2024 17:17
Show Gist options
  • Save mosquito/b23e1c1e5723a7fd9e6568e5cf91180f to your computer and use it in GitHub Desktop.
Save mosquito/b23e1c1e5723a7fd9e6568e5cf91180f to your computer and use it in GitHub Desktop.
Add doker-compose as a systemd unit

Docker compose as a systemd unit

Create file /etc/systemd/system/docker-compose@.service. SystemD calling binaries using an absolute path. In my case is prefixed by /usr/local/bin, you should use paths specific for your environment.

[Unit]
Description=%i service with docker compose
PartOf=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=true
WorkingDirectory=/etc/docker/compose/%i
ExecStart=/usr/local/bin/docker-compose up -d --remove-orphans
ExecStop=/usr/local/bin/docker-compose down

[Install]
WantedBy=multi-user.target

Place your docker-compose.yml into /etc/docker/compose/myservice and call

systemctl start docker-compose@myservice

Docker cleanup timer with system

Create /etc/systemd/system/docker-cleanup.timer with this content:

[Unit]
Description=Docker cleanup timer

[Timer]
OnUnitInactiveSec=12h

[Install]
WantedBy=timers.target

And service file /etc/systemd/system/docker-cleanup.service:

[Unit]
Description=Docker cleanup
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
WorkingDirectory=/tmp
User=root
Group=root
ExecStart=/usr/bin/docker system prune -af

[Install]
WantedBy=multi-user.target

run systemctl enable docker-cleanup.timer for enabling the timer

JournalD support

Just add the following line to the /etc/docker/daemon.json:

{
    ...
    "log-driver": "journald",
    ...
}

And restart your docker service.

@parisni
Copy link

parisni commented May 16, 2021

what about systemd security parameters such ? :

PrivateTmp=yes
UMask=077
NoNewPrivileges=yes
NotifyAccess=yes
PrivateMounts=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
ProtectProc=yes
ProtectHome=true
ProtectSystem=full
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=true
RestrictRealtime=true
SystemCallArchitectures=native
User=<the user>
Group=<the group>

@mosquito
Copy link
Author

@parisni It looks great, but this is not applicable to docker-compose. This is the python script that establishes a connection with the docker daemon, and executes everything that has been described in YAML through the Docker API. Docker, in turn, executes commands from the root user, and all the above restrictions will not be applied.

@gnat
Copy link

gnat commented May 17, 2021

Also this was required for me to get systemctl --user enable docker-compose@blah to work on Ubuntu 20.04 server (load on reboot).

[Install]
WantedBy=default.target

default.target should be an alias for multi-user.target, but apparently not in my situation.

@parisni
Copy link

parisni commented May 18, 2021

and all the above restrictions will not be applied.

well my experimentations have shown that some of them have impact: for example, if I turn off Notify then the docker-compose does not start up

@whistler
Copy link

Would it be better to remove -d after docker-compose up so logs get saved by systemctl?

@mosquito
Copy link
Author

Would it be better to remove -d after docker-compose up so logs get saved by systemctl?

The better way is the docker starts writing all logs to the journald

@chkpnt
Copy link

chkpnt commented Oct 4, 2021

I'm using WantedBy=docker.service so that the service is started when docker itself is (re)started.

@bigntallmike
Copy link

This is great but as said in the docker forums, "docker system prune is not safe to be used in production."

@so-jelly
Copy link

so-jelly commented May 1, 2022

@chkpnt I recommend using

PartOf=docker.service

PartOf=

Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or restarts the units listed here, the action is propagated to this unit. Note that this is a one-way dependency — changes to this unit do not affect the listed units.

@dcd-arnold
Copy link

The better way is the docker starts writing all logs to the journald

@mosquito can you explain why?

@mosquito
Copy link
Author

@dcd-arnold It's simple, at the time of writing this note, the docker daemon storage all container logs in plain JSON files in the /var/lib/docker, which quite often grew to a rather indecent size if you do not does something for control them separately. Now the question is, why do you have to monitor this separately if there is already a daemon in the operating system that can effectively read/write/compress/sign structured log records? Thus, transferring responsibility for all logs to the JournalD level allows them to be efficiently stored, rotated, and read using journalctl filters (e.g. CONTAINER_ID or CONTAINER_NAME).

@mosquito
Copy link
Author

@so-jelly fixed thank you.

@dcd-arnold
Copy link

It's simple, at the time of writing this note, the docker daemon storage all container logs in plain JSON files in the /var/lib/docker, which quite often grew to a rather indecent size if you do not does something for control them separately. Now the question is, why do you have to monitor this separately if there is already a daemon in the operating system that can effectively read/write/compress/sign structured log records? Thus, transferring responsibility for all logs to the JournalD level allows them to be efficiently stored, rotated, and read using journalctl filters (e.g. CONTAINER_ID or CONTAINER_NAME).

@mosquito But docker-compose would not run in background, hence pushing its stdout to systemd, which is build to take such data in and store it. What am i missing here?

@mosquito
Copy link
Author

@dcd-arnold but /usr/local/bin/docker-compose up -d ... in the ExecStart=

@dcd-arnold
Copy link

@mosquito That was the original question:

Would it be better to remove -d after docker-compose up so logs get saved by systemctl?

If you omit -d, docker-compose pushes its stdout to systemd to do with it as it sees fit.

@mosquito
Copy link
Author

@dcd-arnold if you omit something from this recipe, you have to resolve following troubles :-).

@dcd-arnold
Copy link

@mosquito @dcd-arnold if you omit something from this recipe, you have to resolve following troubles :-).

sure thing.

@jest
Copy link

jest commented Jun 7, 2022

@dcd-arnold moreover, having docker-compose printing logs on stdout doesn't stop Docker daemon from saving logs. So you would end up using twice as much space -- once in Docker daemon and once in systemd -- as required for your logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment