Custom Apps

How to Deploy a Docker Compose Stack on a VPS

Bring your own compose file, keep the database off the public network, and let Impreza put HTTPS in front of the service you choose. One naming rule makes it work.

A real app is rarely one container. It is a web service, a database, maybe a worker and a cache. Impreza takes a full docker-compose file as a deployment: you own the compose, the agent runs it on your VPS, and the platform’s reverse proxy issues HTTPS for the service you point it at. There is exactly one rule the proxy needs you to follow, and this guide starts with it.

What you get

  • Your compose file, unchanged in spirit: services, volumes, networks and limits stay yours
  • HTTPS on the service you expose, on your domain or a free imprezaapps.com subdomain
  • Private services stay private: the database never gets a public port
  • The same lifecycle as any deployment: logs, redeploy in place, a .onion mirror if you want one

The one rule: name the public container

The reverse proxy reaches your container by its name on a shared Docker network called impreza-proxy. Your compose must give the public service a fixed name built from the deployment id, and join that network. Everything else is normal compose.

services:
  app:
    image: ghcr.io/yourorg/yourapp:1.2.3
    container_name: ${DEPLOYMENT_ID}-app
    restart: unless-stopped
    networks:
      - default
      - impreza-proxy
    environment:
      DOMAIN_URL: ${DOMAIN_URL}
networks:
  impreza-proxy:
    external: true

The matching route in the deployment tells the proxy where to send traffic:

{ "upstream": "{deployment_id}-app:80", "match_var": "domain" }

Without the container_name line, Compose invents a name like project-app-1, the proxy cannot find the container, and every request answers 502. The platform now rejects a manifest that misses it, with a message naming the exact line to add.

Deploy it

Write the compose with the naming rule

Give the public service container_name: ${DEPLOYMENT_ID}-<suffix> and both networks. Leave internal services such as the database on the default network only, with no ports: published. They talk to the app by service name, as usual.

Pass configuration as variables

Reference secrets as ${VAR} in the compose. The variables you pass at deploy time are written to a .env next to the compose, and three are always present: DOMAIN_URL, DEPLOYMENT_ID and HOST_PORT. Nothing sensitive needs to live in the file itself.

Set limits inside the compose

In manifest mode the platform does not apply its CPU and memory defaults; your compose is the source of truth. Use the service-level cpus: and mem_limit: keys so one container cannot starve the host.

Create the deployment

From My Apps in Advanced view, the CLI, or your AI agent, create a custom deployment in manifest mode with the compose content, the route for the public service, and the domain, or leave the domain empty for a free subdomain. The agent brings the stack up with docker compose.

Check it and iterate

When the status turns to running, open the URL. If something is off, read the logs from the card or your agent. To ship a change, redeploy in place: the deployment id, the domain and the URL stay the same.

Keep the database off the proxy network

Only the service that should receive HTTPS traffic joins impreza-proxy. A database on that network, or with a published port, is reachable from the internet. Keep it on the default network and give it a container_name of its own only to avoid collisions.

A worked example: WordPress plus MariaDB

Two services. wp gets container_name: ${DEPLOYMENT_ID}-wp, both networks and the route {deployment_id}-wp:80. db runs mariadb:11 on the default network with MARIADB_PASSWORD: ${WP_DB_PASS}, and the password arrives as a deploy variable, not in the file. The full example is in the manifest section of the docs.

Volumes and Tor

Declare volumes in the compose as you always do; the platform does not add its own in manifest mode. Any custom deployment can publish a .onion mirror alongside the clearnet hostname, or run onion-only.

Start now

Get an offshore VPS with the agent preselected, read the manifest routing contract at docs.imprezahost.com, or start simpler with deploy a Docker app to an offshore VPS.

Ready to build privacy-first?

No KYC, no email required, crypto payment. Deploy an offshore server in minutes, or do it all by chat with the Impreza agent.