Docker Compose
Generate a docker-compose.yml from typed service definitions, reading environment variables for deployment-specific overrides.
Source
examples/docker-compose/types.rank
pub ServiceDef = Object {
image: string,
ports?: [string],
environment: Object { ...: string },
depends_on?: [string],
restart: string,
}
pub NetworkDef = Object {
driver: string,
}
pub VolumeDef = Object {
driver: string,
}
pub Compose = Object {
version: string,
services: Object { ...: ServiceDef },
networks?: Object { ...: NetworkDef },
volumes?: Object { ...: VolumeDef },
}
examples/docker-compose/main.rank
/// Generates a Docker Compose file from typed service definitions.
/// Shows Env inputs for environment-specific overrides, the `with` patch
/// pattern for dev vs prod, and Emit::manifest to emit a YAML artifact.
use std::Env
use std::Emit
use std::Path
use root::types::{ Compose, ServiceDef }
SysEnv = Object {
COMPOSE_ENV?: string,
DB_PASSWORD?: string,
...: string,
}
env = Env<SysEnv> {}
compose_env = env.COMPOSE_ENV ?? `dev`
db_password = env.DB_PASSWORD ?? `changeme`
is_prod = compose_env == `prod`
base_api: ServiceDef = {
image: `my-org/api:latest`,
ports: [`8080:8080`],
environment: {
NODE_ENV: compose_env,
DB_HOST: `db`,
DB_PASSWORD: db_password,
},
depends_on: [`db`],
restart: `on-failure`,
}
api: ServiceDef = is_prod
? base_api with { restart: `always` }
: base_api with { environment: base_api.environment with { DEBUG: `true` } }
db: ServiceDef = {
image: `postgres:16`,
environment: {
POSTGRES_PASSWORD: db_password,
POSTGRES_DB: `app`,
},
restart: `always`,
}
compose: Compose = {
version: `3.9`,
services: { api, db },
networks: {
default: { driver: `bridge` },
},
volumes: {
pgdata: { driver: `local` },
},
}
pub main = || Emit::manifest({
entries: [
{
path: Path::join([`docker-compose.yml`]),
format: `yaml`,
value: compose,
},
]
})
Output
# docker-compose.yml (with COMPOSE_ENV=dev)
version: "3.9"
services:
api:
image: my-org/api:latest
ports:
- "8080:8080"
environment:
NODE_ENV: dev
DB_HOST: db
DB_PASSWORD: changeme
DEBUG: "true"
depends_on:
- db
restart: on-failure
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: changeme
POSTGRES_DB: app
restart: always
networks:
default:
driver: bridge
volumes:
pgdata:
driver: local
Key concepts
std::Env— reads environment variables at compile time into a typed schema. Optional fields use??for defaults.- Multi-file modules —
types.rankexports shared type definitions; this example uses the canonical absolute formroot::types. In a normal project source tree, a nearby sibling import can also usesuper::types. withpatch —base_api with { restart: \always` }merges without mutatingbase_api`.Emit::manifest(...)— emits one or more named artifacts. The file path and format are part of the descriptor.
Run it
COMPOSE_ENV=prod DB_PASSWORD=secret rank examples/docker-compose