From f2a50cf035535db827cbc8738a4fb4eb22a0b1b5 Mon Sep 17 00:00:00 2001 From: Andrey Cheptsov Date: Sun, 14 Jun 2026 19:41:56 +0200 Subject: [PATCH] Add Docker Compose for a Postgres-backed server with SSH proxy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add docker/server/docker-compose.yml to run the dstack server with PostgreSQL and the SSH proxy locally — a production-like setup for trying or testing on one machine. `docker compose up` brings up Postgres + server (:3000) + SSH proxy (:30022); the proxy host key is generated by a one-shot init service, and credentials/token default for local use and are overridable via DSTACK_* env vars. Document it in docker/server/README.md (also the Docker Hub description) and link it from the server deployment guide. Co-Authored-By: Claude Opus 4.8 (1M context) --- docker/server/README.md | 21 +++++++ docker/server/docker-compose.yml | 73 +++++++++++++++++++++++++ mkdocs/docs/guides/server-deployment.md | 6 ++ 3 files changed, 100 insertions(+) create mode 100644 docker/server/docker-compose.yml diff --git a/docker/server/README.md b/docker/server/README.md index 611dbe6cac..2c91a4e152 100644 --- a/docker/server/README.md +++ b/docker/server/README.md @@ -22,6 +22,27 @@ The admin user token is 'bbae0f28-d3dd-4820-bf61-8f4bb40815da' For more details on server configuration options, see the [server deployment](https://dstack.ai/docs/guides/server-deployment.md) guide. +### Run with PostgreSQL and the SSH proxy + +In production, the `dstack` server is usually run with +[PostgreSQL](https://dstack.ai/docs/guides/server-deployment#postgresql) instead of the default +SQLite, and with the [SSH proxy](https://dstack.ai/docs/guides/server-deployment#ssh-proxy). The +[`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml) +runs that combination locally, so you can try or test a production-like server on your own machine. +A full production deployment would also configure external +[logs storage](https://dstack.ai/docs/guides/server-deployment#logs-storage) and +[file storage](https://dstack.ai/docs/guides/server-deployment#file-storage). + +```shell +docker compose -f docker/server/docker-compose.yml up +``` + +This starts PostgreSQL, the `dstack` server at `http://localhost:3000`, and the SSH proxy at +`localhost:30022`. The admin token is printed to the logs (`docker compose logs server`). + +To access the server from the CLI, add it as a project with `dstack project add`, using the +admin token from the logs (see [Set up the CLI](#set-up-the-cli) below). + ## Set up the CLI To point the CLI to the `dstack` server, configure it diff --git a/docker/server/docker-compose.yml b/docker/server/docker-compose.yml new file mode 100644 index 0000000000..529271059c --- /dev/null +++ b/docker/server/docker-compose.yml @@ -0,0 +1,73 @@ +name: dstack + +services: + postgres: + image: postgres:16 + restart: unless-stopped + environment: + POSTGRES_USER: ${DSTACK_POSTGRES_USER:-dstack} + POSTGRES_PASSWORD: ${DSTACK_POSTGRES_PASSWORD:-dstack} + POSTGRES_DB: ${DSTACK_POSTGRES_DB:-dstack} + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 5s + timeout: 5s + retries: 10 + + server: + image: dstackai/dstack:latest # multi-arch — no platform override needed + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + environment: + DSTACK_DATABASE_URL: postgresql+asyncpg://${DSTACK_POSTGRES_USER:-dstack}:${DSTACK_POSTGRES_PASSWORD:-dstack}@postgres:5432/${DSTACK_POSTGRES_DB:-dstack} + DSTACK_SERVER_LOG_FORMAT: rich # human-readable console logs (image defaults to json) + # Shared secret between the server and the SSH proxy. The default works locally; + # override with a real secret for non-local deployments. + DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token} + # Address clients use to reach the SSH proxy. `localhost:30022` is correct for a + # client on the same host; use a publicly reachable address for multi-host setups. + DSTACK_SERVER_SSHPROXY_ADDRESS: localhost:30022 + volumes: + - server-data:/root/.dstack/server # config.yml + run logs (Postgres holds the rest) + ports: + - "3000:3000" + + # One-shot init: generates the SSH proxy's host key into a shared volume so no manual + # ssh-keygen is needed. The proxy refuses to start without a host key. + sshproxy-keygen: + image: alpine:3 + command: + - sh + - -c + - | + apk add --no-cache openssh-keygen >/dev/null + [ -f /keys/host_key ] || ssh-keygen -t ed25519 -f /keys/host_key -N "" -C dstack-sshproxy + volumes: + - sshproxy-keys:/keys + + sshproxy: + image: dstackai/sshproxy:latest + platform: linux/amd64 # image is amd64-only; emulated on Apple Silicon + restart: unless-stopped + depends_on: + sshproxy-keygen: + condition: service_completed_successfully + server: + condition: service_started + environment: + DSTACK_SSHPROXY_API_URL: http://server:3000 + DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token} + command: ["--host-key", "/keys/host_key"] + volumes: + - sshproxy-keys:/keys + ports: + - "30022:30022" + +volumes: + postgres-data: + server-data: + sshproxy-keys: diff --git a/mkdocs/docs/guides/server-deployment.md b/mkdocs/docs/guides/server-deployment.md index 5a82ac8bc7..07f1c798db 100644 --- a/mkdocs/docs/guides/server-deployment.md +++ b/mkdocs/docs/guides/server-deployment.md @@ -165,6 +165,9 @@ If you're using a smaller DB instance, you may need to set lower `DSTACK_DB_POOL If you encounter errors, please [submit an issue](https://github.com/dstackai/dstack/issues/new/choose). +> For a local setup running PostgreSQL and the [SSH proxy](#ssh-proxy) together, see the example +> [`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml). + ## Logs storage By default, `dstack` stores workload logs locally in `~/.dstack/server/projects//logs`. @@ -370,6 +373,9 @@ To enable SSH proxy integration on the `dstack` server side, set the following e * `DSTACK_SSHPROXY_API_TOKEN` – a token used to authenticate SSH proxy API requests, must be the same value as when deploying `dstack-sshproxy`. * `DSTACK_SERVER_SSHPROXY_ADDRESS` – an address where SSH proxy is available to `dstack` users, in the `HOSTNAME[:PORT]` form, where `HOSTNAME` is a domain name or an IP address, and `PORT`, if not specified, defaults to 22. +> For a local setup running [PostgreSQL](#postgresql) and the SSH proxy together, see the example +> [`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml). + ## Encryption By default, `dstack` stores data in plaintext. To enforce encryption, you