Sites and applications

Docker Compose sites

A Docker Compose site puts a container stack behind the same nginx, HTTPS and domain handling as every other site. The panel manages the stack; you keep the compose file.

Verified against auraPanel 1.21.3· Last updated 17 September 2026

How a Docker site runs

A Docker Compose site is a reverse-proxy site whose upstream is a container stack. The panel allocates a loopback port, exposes it to your compose file as AURA_PORT, runs docker compose up in the foreground under aurapanel-site-<domain>.service, and proxies the domain to that port with HTTPS. The compose file and a .env live in the site's document root, htdocs/<domain>/docker-compose.yml.

Only administrators can create Docker sites. Docker itself is installed with --docker=yes at install time or later from the Services screen.

Create the site

Sites → Add site → Docker Compose, then choose one of two modes:

  • Single image. Enter the image (for example ghcr.io/example/app:1.4), the container port the application listens on, environment variables as KEY=value lines, and optionally a host port. The panel writes the compose file for you.
  • Compose file. Paste your own YAML. Your web service must publish its port to the panel's loopback port: "127.0.0.1:${AURA_PORT}:<container-port>".
services:
  web:
    image: ghcr.io/example/app:1.4
    ports:
      - "127.0.0.1:${AURA_PORT}:8080"
    env_file: .env
    volumes:
      - ./data:/data
    restart: unless-stopped

Create returns quickly: the image pull runs in the background, and the site shows the panel's placeholder until the stack is up.

Expected result

The domain serves the container over HTTPS. The site's Docker tab shows the containers, and Logs shows docker compose logs.

What the panel enforces

The compose file is checked before anything starts. These are refused, with the message shown:

RefusedMessage
Publishing a port on any address other than 127.0.0.1"service … publishes a port on … — containers may only publish to 127.0.0.1"
No service publishing the proxy port"no service publishes the proxy port — map your web service to 127.0.0.1:${AURA_PORT}:<container-port>"
privileged: true, network_mode: host, pid: hostRefused outright.
Capabilities that allow container escape; bind-mounting / or the Docker socketRefused outright.

Everything else in Compose is yours: multiple services, named volumes, networks, health checks.

Operate the stack

  • Up, Down, Restart, Pull, Recreate from the site's Docker tab. Pull fetches newer images; Recreate applies a changed compose file.
  • Changing the service port re-renders the unit and restarts the stack.
  • Edit docker-compose.yml and .env in the File Browser or over SFTP, then Recreate.
  • Logs: docker compose logs in the Logs tab, plus the unit's journal.

Data and backups

Keep persistent data in a bind mount under the site's document root (./data in the example) rather than a named volume: site backups archive the document root, not Docker named volumes. Deleting a Docker site removes its containers, network, named volumes and images.

Not provided

  • Per-site Docker isolation or rootless Docker: all stacks share the host's Docker daemon, which is why Docker sites are administrator-only.
  • CPU or memory quotas set by the panel; set them in your compose file.
  • Registry credential management; log in with docker login on the host for private images.
  • The Databases and page-cache tabs, which are hidden for Docker sites. Run your database as a service in the stack or use a panel database from another site.

Common messages

"no compose definition (provide an image or a docker-compose.yml)" or "compose file cannot be empty"

The form was submitted without an image or YAML.

The site shows a 502 after creation

The pull is still running, or the container listens on a different port than the one mapped to AURA_PORT. Check the Docker tab and docker compose logs.

"this is not a Docker site"

Docker actions were called on a site of another type.

Try the live demo

A real auraPanel on a real server, shared with everyone. Sign in with the demo account and click around.

Email
demo@goaura.one
Password
demo1234
Open the demo panel ↗

Shared public demo, so please don’t put anything personal in it. More about the demo →

Talk to us

Tell us what you need and how to reach you. A person reads this, not a queue.

We use these details only to reply to you. Privacy

Recent updates

What shipped in the last releases. With automatic updates on, each lands on your server the moment it is published.

  1. v1.21.3
    Framework sites were undetectable, and a restore could silently point the copy at the original's live database.

    DetectApp looked for each application's signature relative to the docroot — but every PHP framework in the registry serves from a subdirectory (DocrootSub: public, webroot, web, pub, docroot) and keeps the file that identifies it one level *above* that. So the Laravel signature searched <project>/public/artisan,…

  2. v1.21.2
    Restarting nginx now blocks the panel and reconnects, instead of showing a notice.

    v1.21.1 stopped the false "HTTP 520" but only put up a toast — and a toast is the wrong affordance when the panel itself is about to go away: the page sat there looking broken while every request failed underneath it.

  3. v1.21.1
    Restarting nginx from Services no longer reports a false failure.

    It showed "Restart failed — HTTP 520". The panel is reverse-proxied *by* nginx, so the request deadlocked against itself: the handler blocked waiting for the restart to finish, while nginx's graceful stop waited for that very request to drain. Neither could proceed until nginx's stop-retry timeout force-killed it,…

  4. v1.21.0
    Per-site X-Frame-Options, fixing page builders that couldn't load their preview.

    Elementor's editor failed with *"Multiple 'X-Frame-Options' headers with conflicting values ('DENY, SAMEORIGIN')"*. The cause is that nginx's add_header appends rather than replaces: when the application also sets the header — a WordPress security plugin, or a CDN transform — the browser received two values,…

  5. v1.20.6
    The multi-database restore refusal now says what is in the backup and what still works.

    It read only "Restoring a multi-database site isn't supported yet", which is a dead end: it named neither the databases involved, nor why one of them is the limit, nor any route forward.

  6. v1.20.5
    Services: cards in a row now match heights.

    Like the settings grid before it, the Services grid pinned each card to its own content height, so a row often showed one card noticeably shorter than the card beside it. Each row now takes the taller card's height and both fill it, and it re-balances as content changes — a runtime installed, a longer service list.

  7. v1.20.4
    Settings: paired cards now match heights.

    Organisation / Panel Domain and auraPanel Updates / Session timeout each sat at their own content height, so a row showed one card visibly shorter than its neighbour. Each row now takes the taller card's height and both fill it — driven by content, not a fixed value, so it still adapts as a card grows (a validation…

  8. v1.20.3
    Settings: Organisation and Panel Domain now share a row too.

    They were full-width blocks stacked above the rest of the page; they now sit side by side in the same two-column grid as the Updates / Session timeout pair, so the top of Settings reads as two tidy rows instead of four stacked bands. Both cards shrink cleanly — the logo drop zone is a fixed 44×44 and the name field…

All releases on GitHub ↗