How to use Docker Compose

Define and run a multi-container application on TurboStack with Docker Compose - a compose.yaml file, publishing through Nginx, and keeping the stack running.

Docker Compose lets you describe a multi-container application - for example an app plus its database - in a single compose.yaml file and start it with one command. On TurboStack the modern docker compose (v2) is available once Docker is enabled, and TurboStack still reverse-proxies public traffic to your app through Nginx.

Use Compose instead of a single docker run when your app is more than one container, or when you want its configuration version-controlled in a file.

1. Enable Docker for the application

Turn on Docker under Configure application > Technologies > Docker (see Configure Docker). Every system user with Docker enabled is added to the docker group and can run the docker and docker compose commands over SSH.

2. Write a compose.yaml

Create a compose.yaml in your application directory (for example ~/app). Publish only the front-facing port, and bind it to localhost so it is reachable only through Nginx; internal services (such as a database) need no published ports because containers reach each other by service name on the Compose network.

services:
  web:
    image: your-image:1.2
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"   # published to localhost; Nginx proxies to this
    environment:
      DATABASE_URL: "postgres://appuser@db:5432/appdb"
    depends_on:
      - db

  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_USER: appuser
      POSTGRES_DB: appdb
      POSTGRES_PASSWORD: change-me
    volumes:
      - db-data:/var/lib/postgresql/data
    # no ports: only reachable by other services (here, "web") on the Compose network

volumes:
  db-data:
  • Pin image tags (your-image:1.2, postgres:17) rather than latest, so deployments are reproducible.

  • restart: unless-stopped brings a container back after a crash or a server reboot.

  • Keep data you need to survive a container rebuild in a named volume (db-data above), never in the container's writable layer.

  • Store secrets in an .env file next to the compose file (Compose reads it automatically) rather than committing them.

3. Start and manage the stack

Run these from the directory that holds compose.yaml:

docker compose up -d      # create and start everything, in the background
docker compose ps         # what is running
docker compose logs -f    # follow the logs (Ctrl+C to stop watching)
docker compose pull       # fetch newer images...
docker compose up -d      # ...then re-create containers with them
docker compose down       # stop and remove the containers (keeps named volumes)

4. Publish it through TurboStack

Point the reverse proxy at the port you published so Nginx serves the app on your domain with HTTPS:

docker_enabled: true
proxy_enabled: true
proxy_upstream_port: 8080   # the host port published by the web service

Publish the change to apply it.

Keep the stack running

restart: unless-stopped already restarts your containers after a crash or reboot. To manage the whole stack as one service - so it is guaranteed to launch and you can start and stop it cleanly - wrap it in a user systemd service. Create ~/.config/systemd/user/myapp.service:

[Unit]
Description=My Compose app
After=network-online.target
StartLimitIntervalSec=0

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=%h/app
ExecStart=docker compose up -d
ExecStop=docker compose down
Restart=on-failure
RestartSec=15s

[Install]
WantedBy=default.target
systemctl --user enable --now myapp.service
systemctl --user status myapp.service

TurboStack keeps user services running after you log out, so the stack survives reboots. For the systemd --user basics, see Run with a process manager.