> For the complete documentation index, see [llms.txt](https://docs.syntho.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.syntho.ai/deploy-syntho/deploy-syntho-using-docker.md).

# Docker Compose

Run the full Syntho stack on a single machine using Docker Compose.

<details>

<summary>What Docker Compose deploys</summary>

The Compose bundle runs the full stack on one host:

* Frontend (UI)
* Backend
* Core API
* Ray
* PostgreSQL (metadata)
* Redis

Some bundles let you point to external PostgreSQL/Redis instead.

</details>

<details>

<summary>Offline deployment</summary>

Offline deployments require the steps below. You need to stage artifacts on a connected machine first.

1. **Stage the compose bundle**

   You cannot fetch templates from GitHub on the offline host.

   1. Download or clone the `deployment-tools` repo.
   2. Copy the `docker-compose/` folder (including `postgres/`) to the offline host.
2. **Stage container images**

   The offline host cannot pull images from the Syntho registry. There are two alternatives:

   * **Recommended:** mirror images into an internal registry reachable by the offline host. Then update image references in `docker-compose.yaml` to the internal registry hostname.
   * **Alternative:** `docker save` / `docker load` images as tarballs.

   Practical flow for tarballs:

   1. Log in to the Syntho registry.
   2. Pull the images for the `APPLICATION_VERSION` you will deploy.
   3. Export them:

```bash
docker save -o syntho-images.tar \
  <image-1>:<tag> <image-2>:<tag> <image-n>:<tag>
```

4. Transfer `syntho-images.tar` to the offline host.
5. Import them on the offline host:

```bash
docker load -i syntho-images.tar
```

3. **Registry authentication step changes**
   * If you load images locally, skip registry login on the offline host.
   * If you use an internal registry, log in to that registry instead.

{% hint style="info" %}
Upgrades are the same procedure. Repeat the staging step for the new `APPLICATION_VERSION`.
{% endhint %}

</details>

### Deploy

{% stepper %}
{% step %}
**Prerequisites**

Make sure you meet the [prerequisites](/deploy-syntho/deploy-syntho-using-docker/prerequisites.md) before deploying.
{% endstep %}

{% step %}
**Get the Docker Compose templates**

Use the templates from the `deployment-tools` repository:

* [Docker Compose templates](https://github.com/syntho-ai/deployment-tools/tree/main/docker-compose)

Key files in that folder:

* [`.env` (template)](https://github.com/syntho-ai/deployment-tools/blob/main/docker-compose/.env)
* [`docker-compose.yaml`](https://github.com/syntho-ai/deployment-tools/blob/main/docker-compose/docker-compose.yaml)

Keep `.env` and `docker-compose.yaml` in the same directory.

Also keep the [`postgres/`](https://github.com/syntho-ai/deployment-tools/tree/main/docker-compose/postgres) folder next to them. It contains the init script that creates the required databases.
{% endstep %}

{% step %}
**Authenticate to the container registry**

Use the registry host and credentials provided by Syntho to login with:

```bash
docker login syntho.azurecr.io -u <USERNAME> -p <PASSWORD>
```

{% hint style="info" %}
Ensure that `syntho.azurecr.io` is added to your firewall allowlist to enable image pulls
{% endhint %}
{% endstep %}

{% step %}
**Configure `.env`**

Edit `.env` in the same directory as `docker-compose.yaml`.

Set at least:

* `APPLICATION_VERSION`: Syntho version to deploy.
* `LICENSE_KEY`: your Syntho license key.
* `SECRET_KEY`: secret used by Syntho security mechanisms.
* `USER_EMAIL`: email for the initial admin user.
* `USER_PASSWORD`: password for the initial admin user.
* `DB_PASSWORD`: password for the bundled PostgreSQL (required by `docker-compose.yaml`).

{% hint style="info" %}
The default Compose bundle assumes `DB_USER=syntho`. Set `DB_PASSWORD` yourself.
{% endhint %}

Generate a `SECRET_KEY` (if needed, Syntho will provide one as well):

```bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
```

{% hint style="warning" %}
Rotate secret keys carefully.
{% endhint %}

Syntho uses secret keys for sessions and encryption.

Changing keys can break sessions.

It can also make previously stored encrypted values unreadable.

Plan key rotation:

1. Back up PostgreSQL metadata databases.
2. Stop traffic and running jobs.
3. Rotate keys.
4. Restart services.
5. Verify login and basic workflows.

If you are unsure what do do, ask Syntho Support.

<details>

<summary>UI URL, ports, and HTTPS</summary>

By default UI is exposed on port `3000` and the API on `8000`.

If you terminate TLS in a reverse proxy, ensure:

* The UI is configured for `https`.
* Secure cookies are enabled when using HTTPS.

```bash
FRONTEND_DOMAIN=<hostname-or-ip>
FRONTEND_PROTOCOL=http   # set to https when using TLS
SECURE_COOKIES=False     # set to True when using https
FRONTEND_PORT=3000
BACKEND_PORT=8000
```

</details>

<details>

<summary>Ray CPU and memory sizing</summary>

Configure Ray's resource allocation in `.env`:

```bash
RAY_CPUS=8
RAY_MEMORY=32G
```

These are the bundle's defaults. Size them for your workload and leave host resources for the other services, including PostgreSQL and Redis. See [Deployment overview](/deploy-syntho/introduction.md#hardware-requirements) for host sizing.

</details>

Apply changes to `.env` with `docker compose up -d`, which recreates affected containers. A plain `docker compose restart` does not apply changed environment or resource settings. Plan resource changes for a maintenance window because container recreation can interrupt jobs.
{% endstep %}

{% step %}
**Start Syntho**

```bash
docker compose up -d
```

{% endstep %}

{% step %}
**Verify deployment**

Check containers status with:

```bash
docker compose ps
```

Open the UI:

* `<FRONTEND_PROTOCOL>://<FRONTEND_DOMAIN>:<FRONTEND_PORT>`

Use the admin credentials you configured in `.env`.

{% hint style="info" %}
The `FRONTEND_DOMAIN` / `FRONTEND_PORT` can be found in the `.env`
{% endhint %}

If this does not work, see [Troubleshooting](/deploy-syntho/deploy-syntho-using-docker/troubleshooting.md).
{% endstep %}

{% step %}
**Back up PostgreSQL**

[Back up PostgreSQL](/deploy-syntho/deploy-syntho-using-docker/back-up-postgresql.md) Syntho application databases before first use to validate the process.
{% endstep %}
{% endstepper %}

### Redis persistence and sizing

The bundled Redis service (`queue`) stores queued tasks and ongoing job logs. Job logs remain in Redis until their final archive is saved in PostgreSQL. Size Redis for all unarchived jobs, including long-running jobs and archive retries, as well as queues and other application data.

Redis uses an **Append-Only File (AOF)** in the `queue-data` named volume mounted at `/data`. Writes are flushed to disk approximately every second (`appendfsync everysec`), including during AOF rewrites. Redis reloads this data after a restart when the same volume is reused. The `noeviction` policy prevents memory pressure from silently evicting queue or log keys; when the memory budget is reached, Redis rejects writes instead.

Configure these optional variables in the deployment's `.env`:

| Variable               | Default | Purpose                                                                 |
| ---------------------- | ------- | ----------------------------------------------------------------------- |
| `REDIS_MAXMEMORY`      | `512mb` | Redis memory budget for all application data; not total process memory  |
| `REDIS_MEMORY_LIMIT`   | `2g`    | Container memory limit, including process overhead and rewrite headroom |
| `REDIS_MEMORY_REQUEST` | `512m`  | Container memory reservation                                            |
| `REDIS_CPU_LIMIT`      | `1`     | CPU limit in cores                                                      |
| `REDIS_CPU_REQUEST`    | `0.1`   | CPU reservation in cores                                                |
| `REDIS_START_PERIOD`   | `30m`   | Healthcheck startup grace while Redis loads persisted data              |

These defaults are starting points, not a guarantee of sufficient capacity for your workload. Keep reservations at or below limits, and leave substantial memory headroom above `REDIS_MAXMEMORY`: AOF rewrites can approach twice the dataset's memory usage, plus overhead. Increasing disk space does not increase the amount of log data Redis can hold in memory.

The healthcheck requires an exact `PONG` response; Redis is not healthy while loading data. Increase `REDIS_START_PERIOD` if loading needs more time. Compose healthchecks report health status but do not themselves restart unhealthy containers. The queue's `restart: unless-stopped` policy restarts an exited process or starts it after a Docker daemon restart unless it was intentionally stopped.

The named volume uses the Docker host's storage; there is no separate 1Gi volume-size setting. Provision and monitor host disk space for the existing AOF, rewritten files, concurrent writes, and any RDB snapshots. AOF files can grow beyond the in-memory dataset size. Reuse the same Compose project and volume when recreating containers.

{% hint style="warning" %}
Persistence is not high availability or a backup. A crash can lose roughly the most recent second of writes with `everysec`; storage failures can lose more. The volume does not follow the deployment to another host. Volume deletion, `docker compose down -v`, or host/disk loss can destroy queued tasks and unarchived logs. Protect persistent storage independently.
{% endhint %}

For monitoring commands, see [Redis health and capacity](/deploy-syntho/deploy-syntho-using-docker/operations.md#redis-health-and-capacity). If you use external Redis, configure equivalent persistence, memory headroom, and a `noeviction` policy on that service; the Compose settings do not configure external Redis.

### Next steps

* Day-to-day commands: [Operations](/deploy-syntho/deploy-syntho-using-docker/operations.md)
* Upgrade procedure: [Upgrade](/deploy-syntho/deploy-syntho-using-docker/upgrade.md)
* Common issues: [Troubleshooting](/deploy-syntho/deploy-syntho-using-docker/troubleshooting.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.syntho.ai/deploy-syntho/deploy-syntho-using-docker.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
