A Docker Compose file describes containers on one host. A Bex render.yaml describes managed services, datastores and disks. Most of a Compose file maps, but host-level features such as bind mounts, networks and start order do not, and moving a file moves no data.
Bex is in active development and its upstream project does not yet recommend production workloads. Begin with a non-production rehearsal and check compatibility and required capabilities before proceeding.
Use the converter
Paste your docker-compose.yml, and optionally the .env its services read,
into the Docker Compose converter. It is
a browser starting point: it drafts a render.yaml by the rules below, lists
every element it could not map with the reason, and checks the draft with the
render.yaml checker. bex blueprints validate
remains the authoritative check. Nothing you paste leaves your browser.
How Compose maps to Bex
| Compose | Bex |
|---|---|
Service with a published TCP port (ports) | Web service; the first TCP port becomes PORT unless it is 3000 |
Service with only expose, or referenced by other services | Private service (pserv) |
| Any other long-running service | Background worker |
| Container port below 1024 | Not mapped: reconfigure the app to listen on $PORT |
| Extra published ports, UDP ports | Not mapped: one HTTP port per service |
build | Docker runtime (dockerContext, dockerfilePath) |
image without build | Image runtime; the image's own command runs |
command, entrypoint | dockerCommand (Docker runtime only) |
environment, env_file | Environment variables; secrets become sync: false |
deploy.replicas | numInstances |
Official postgres image | Bex Postgres, wired with fromDatabase (major 13 or later) |
Official redis or valkey image | Bex Key Value, wired with fromService |
| Named volume used by one service | A disk (paid plan, single instance, choose a size) |
| Shared named volume, bind mount, tmpfs | Not mapped |
HTTP healthcheck on a web service | healthCheckPath |
depends_on, networks, profiles, restart, cap_add, privileged | Not mapped, with the reason |
${VAR} substitution in the Compose file is not evaluated: resolve it and
enter the value yourself.
Ports and PORT
A web service must listen on 0.0.0.0 and the port Bex injects as PORT. The
default container port is 3000, and Bex does not detect ports, so a service that
listens on another port needs PORT set to match
(web services). Tenant containers drop Linux capabilities,
so an app on port 80 or 443 must be reconfigured to an unprivileged port such as
8080 (Docker deploys). Bex routes one HTTP port per
service.
Build or image
A service with build uses the Docker runtime: set dockerContext and
dockerfilePath relative to the repository root, and put dependency
installation in the Dockerfile. A service with only image uses the image
runtime and runs the image's own command; bex refuses dockerCommand and
repository fields on image services. A private registry needs a
registry credential.
Datastores
Containers from the official postgres image become Bex Postgres,
and other services' connection URLs are rewired with fromDatabase. Postgres
majors below 13 are not supported. Containers from the official redis or
valkey images become Bex Key Value, managed Valkey, wired with
fromService and type: keyvalue. The managed datastores start empty: their
container volumes, environment and ports do not carry over. Move data with a
tested transfer, not by copying volumes.
Volumes and disks
A named volume used by one service can become a persistent disk. There is one disk per paid web service, private service or background worker, a service with a disk runs a single instance, and Compose volumes have no size, so choose one. Shared named volumes, bind mounts and tmpfs mounts have no Bex equivalent: bake files into the image or keep shared state in a datastore.
What does not map
Compose depends_on, networks, profiles, restart, cap_add,
privileged and non-HTTP health checks have no Bex setting. Bex services share a
private network, restart automatically, and should retry
connections instead of relying on start order.
Move data and traffic
Rehearse the data transfer and the cutover with steps 4 and 5 of Migrate from Render; they apply to any source host.