Guides / Deploy
Compose apps. Deploy a compose project with workers and a database.
A folder with a compose file deploys as that project. The CLI names the services it found:
Deploying crm (compose: web, worker, db) to acmeThe public service
One service gets the app's URL:
- The service with
x-hub: { port: 3000 }, naming the port inside the container. - Otherwise, the only service with
ports, on the container side of its first mapping.
Two services with x-hub.port are refused. A project with neither gets no URL, which suits a worker.
A database
A database is a service in the same file, with its data in a named volume and its password in the app's environment:
services:
web:
build: .
ports: ["8080:3000"]
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
depends_on: [db]
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: app
volumes:
- dbdata:/var/lib/postgresql/data
volumes:
dbdata:Set the password before the first deploy, then open the database when you need it:
hub app crm env set DB_PASSWORD
hub deploy
hub app crm exec --service db -- psql -U app appNamed volumes survive deploys, rollbacks, environment changes, stop and start. hub app crm rm asks whether to delete them. Hub does not back up volumes yet, so keep your own backup of data that matters.
Variables
${NAME} in the file reads the app's environment, set with hub app <name> env set. Hub does not read the .env file in your folder. Services Hub builds get every variable in their environment too; a service that runs a ready image, such as postgres:16-alpine, gets only what the file gives it. See Environment variables.
What Hub changes
portsandcontainer_nameare dropped, with a line in the build log. Hub routes to the public service itself.- Every service gets
restart: unless-stoppedandinit: true, unless it sets them. - Bind mounts inside the app folder become read-only. Keep data in named volumes.
What Hub refuses
The CLI checks the file before it uploads, and Hub checks it again before anything builds. A compose file may not reach outside its own project:
privileged,devices,gpus,sysctls,runtime,cgroup,cgroup_parent,userns_mode, andcap_addother thanNET_BIND_SERVICE.network_modeother thanservice:<name>, andpid,ipcanduts.security_optentries withunconfined,apparmororseccomp,use_api_socket, andvolumes_froma container.- Builds on the host network, privileged builds, build entitlements and SSH.
- External networks and volumes, drivers other than
bridgeandlocal,driver_opts, and networks or volumes with a fixed name. - Any file outside the app folder: bind mounts, build contexts, Dockerfiles, env files, secrets and configs.
extendswith a file andincludeare refused too. - Service names outside
a-z,0-9,.,_and-, and uploads with symbolic or hard links.
If a deploy from GitHub fails on an external network or a missing port, Hub can open a pull request that fixes the file. See Deploy from GitHub.