docker-compose stacks

Bring a whole stack in one go: deploy a directory that has a docker-compose file, and every service in the file becomes a service in the project.

Deploy one

In the directory with the compose file, run the command from + Create → Your code (or the same command in CI). It prints what it will create, then sends the code:

Project: shop
  + web: new service, built from web/Dockerfile, with an address
  + db: new service, image postgres:17, private
  + cache: new service, image redis:7, private

Push again later and the services that are there get the new code; a service you added to the file is created; an image: you changed is switched. Services you removed from the file are left alone: delete them in the dashboard. Settings you changed in the dashboard (variables, scaling, domains) stay: after the first push the compose file decides what exists and what it's built from, not how it's configured.

--service <name> deploys just one service of the file; --group <name> shows the new services as one group on the canvas.

Profiles

Services in profiles: come as docker compose up brings them: only when one of their profiles is deployed. --profile production deploys the file's services without a profile and those in production; several go comma-separated (--profile production,init). Without --profile, the plan says which services were left out, and in which profiles. A service named with --service comes whatever its profiles.

For well-known apps there may already be a one-click deploy: the same idea, ready-made.

How the file is read

In the compose fileOn Alf
build:A service built from your code (Dockerfile and context as given, relative to the compose file).
image:A service running that image.
ports:A public service with an address; the container port is used. HTTPS ends at the edge, so when the file publishes 80 and 443, it's 80.
ports: only on 127.0.0.1Private: the file keeps it to its own machine. alf connect reaches it from yours.
no ports:A private service, reachable as name:port inside the project.
environment:Variables, when the service is created (move passwords to secrets afterwards).
named volumes:Volumes that keep their data across deploys.
a database's image (postgres, mysql, mariadb, mongo, redis and the like) or data directory, on a volumeBacked up from the start, as a database made here is: a snapshot a day, the last week of them, and a copy off the server.
profiles:Left out unless one of its profiles is deployed (see above).
anchors and <<: *defaultsMerged, as compose does.
command:, entrypoint:Kept.
deploy.replicasInstances.
mem_limit, deploy.resources.limits.memoryIts size: the smallest with at least that much memory. Without one it's s (512 MB).
label smartalfred.public: "false"Private even with ports:.
labels smartalfred.always_on, smartalfred.health_pathNever sleeps; the path that says it's ready.
label smartalfred.static: <folder> (or "true")A static site: that folder of the built image is served from the edge, and nothing runs. "true": the image's own LABEL smartalfred.static names the folder.
label smartalfred.spa: "true"A static site in SPA mode: paths that aren't files get index.html.

Private services (databases and the like) are created first, so they're up when the apps start. Services keep their compose names, so DATABASE_URL=postgres://…@db:5432/app keeps working.

There's no host environment here, and no .env file is read: ${VAR:-default} takes its default (which may hold variables of its own), and ${VAR}, $VAR, ${VAR:?…} and ${VAR:+…} are empty. An image left without its tag or its name that way (app:${VERSION}) is refused before anything is made, naming the variable: write the tag into the file, or give it a default. Anything else the file uses that Alf can't do (bind mounts, a build context outside the code) is listed as a warning in the plan.

A bind mount of a folder of your project that the app writes to (./data:/app/data) becomes a volume of the same name, so what's written there is kept across deploys. It starts empty: what's in the folder on your machine isn't copied. The project itself (./), single files and read-only mounts are code and configuration: put them in the image instead. Paths outside the project (/var/run/docker.sock) are skipped.

What isn't done here

The plan names each of these once, with the services that use it: