Running MedExpertMatch Stack as a System Service (Ubuntu 24.04)¶
This guide explains how to run the full Docker Compose stack (PostgreSQL, application with embedded docs at /docs) as a systemd service on Ubuntu 24.04. When the service is enabled, it auto-starts on reboot; you can manage it with systemctl.
Prerequisites¶
- Ubuntu 24.04 (or compatible)
- Docker Engine and Docker Compose v2 installed
- Project cloned or copied to the host (e.g.
/home/berdachuk/projects-ai/med-expert-match-ce)
Ensure Docker is installed and your user can run Docker (e.g. in the docker group). The systemd service runs as root and uses the system Docker daemon.
1. Build the Stack (one-time or after code changes)¶
From the project directory:
Optional: build without cache for a clean build: docker compose build --no-cache.
2. Install the Systemd Unit¶
Copy the service file and reload systemd:
sudo cp /home/berdachuk/projects-ai/med-expert-match-ce/scripts/medexpertmatch-stack.service /etc/systemd/system/
sudo systemctl daemon-reload
Apply on this host (Ubuntu 24.04, project at default path)¶
Run these in order (you will be prompted for your password):
sudo cp /home/berdachuk/projects-ai/med-expert-match-ce/scripts/medexpertmatch-stack.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable medexpertmatch-stack # enables auto-start on reboot
sudo systemctl start medexpertmatch-stack
sudo systemctl status medexpertmatch-stack
After enable, the stack will start automatically after every reboot. If the stack was already running via docker compose up -d, you can stop it first with docker compose down in the project directory, then start it via the service so systemd manages it.
Using a different project path¶
If the project is not at /home/berdachuk/projects-ai/med-expert-match-ce, edit the unit before copying:
Change the WorkingDirectory= line to your project path, then run sudo systemctl daemon-reload.
3. Enable and Start the Service¶
Enable the service so it starts on boot:
Start the stack now (without rebooting):
Check status:
Containers should be running. Verify:
- App:
curl -s http://localhost:8094/actuator/health - Docs:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8094/docs/
4. Service Commands Reference¶
| Action | Command |
|---|---|
| Start stack | sudo systemctl start medexpertmatch-stack |
| Stop stack | sudo systemctl stop medexpertmatch-stack |
| Restart stack | sudo systemctl restart medexpertmatch-stack |
| Status | sudo systemctl status medexpertmatch-stack |
| Enable on boot (auto-start on reboot) | sudo systemctl enable medexpertmatch-stack |
| Disable on boot | sudo systemctl disable medexpertmatch-stack |
| View logs | journalctl -u medexpertmatch-stack -f |
When the service is enabled, it auto-starts after every reboot. After start, the unit runs docker compose up -d and exits; containers keep running under Docker. After stop, the unit runs docker compose down and removes the containers (data in the volume is preserved).
5. Where Database Data Is Stored (Host)¶
PostgreSQL data is stored in a Docker named volume. On the host filesystem it is located at:
- Volume name (Compose):
medexpertmatch-postgres-data - Full volume name (Docker):
med-expert-match-ce_medexpertmatch-postgres-data(project name + volume name) - Path on host:
/var/lib/docker/volumes/med-expert-match-ce_medexpertmatch-postgres-data/_data
To list volumes: docker volume ls | grep medexpertmatch.
To inspect (shows Mountpoint): docker volume inspect med-expert-match-ce_medexpertmatch-postgres-data.
6. Permissions When Running as a Service¶
- The systemd unit runs as root. It executes
docker compose up -danddocker compose down, so Docker has full access to its data directories. - The volume
/var/lib/docker/volumes/.../_datais created and owned by root (Docker daemon). The PostgreSQL process inside the container runs as userpostgres(inside the container) and writes files into this volume; ownership of files inside_datais as seen inside the container (e.g. UID 999 for postgres). - Do not change ownership or permissions of
/var/lib/docker/volumes/med-expert-match-ce_medexpertmatch-postgres-dataor_data. Docker and the postgres container manage them. Changing permissions can prevent the container from starting or cause data corruption. - If you need to back up the database:
- Prefer
pg_dumpfrom inside the container or from the host using the exposed port (e.g.pg_dump -h localhost -p 5433 -U medexpertmatch medexpertmatch). - If you copy the volume directory, use root:
sudo tar -czf backup.tar.gz -C /var/lib/docker/volumes/med-expert-match-ce_medexpertmatch-postgres-data _data. Restore with care; ensure the stack is stopped and permissions are not altered. - If the stack was previously run by a non-root user (e.g. your user in the docker group), the volume is still created by the Docker daemon (root). Switching to the systemd service does not require any permission changes; the same volume is used.
7. After Updating the Project¶
After pulling code or changing images:
- Rebuild if needed:
docker compose build(orbuild --no-cache). - Restart the service so it recreates containers with the new images:
sudo systemctl restart medexpertmatch-stack
Database data in the volume persists across restarts and rebuilds.
8. Troubleshooting¶
- Containers do not start: Run
docker compose up -dmanually from the project directory and checkdocker compose logs. Fix any build or config errors, thensudo systemctl restart medexpertmatch-stack. - Permission denied on volume: Do not chown/chmod the volume. Ensure no other process has changed ownership of
/var/lib/docker/volumes/med-expert-match-ce_medexpertmatch-postgres-data. If it was modified, restore from backup or re-init the database (volume remove and fresh start; data will be lost). - Service fails to start: Check
journalctl -u medexpertmatch-stack -n 50. Ensure Docker is running (systemctl status docker) andWorkingDirectoryin the unit points to the correct project path.