Recipe: Add a service to Compose
Recipes
Add a containerized service to your local stack as an isolated overlay. The core stack stays light; opt-in tools get their own resource budgets.
20 min
Estimated duration
Compose
Engine
Opt-in
Overlay Model
Add a new container to the stack as an overlay. A WITH_<NAME>=1 flag turns it on without changing the base file. Same model the observability, GlitchTip, Bull Board, and Mailpit overlays use.
Worked example below: adding Meilisearch as an opt-in search engine, exposed on a dev hostname and behind Basic Auth in prod.
Prereqs
Section titled “Prereqs”- A working local stack.
- Read Profiles & overlays for the convention
./dev.shandcompose-up.shfollow.
-
Create the overlay file. In
infra/compose/compose/:docker-compose.meilisearch.yml services:meilisearch:image: getmeili/meilisearch:v1.10restart: unless-stoppedenvironment:MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?MEILI_MASTER_KEY is required}MEILI_NO_ANALYTICS: "true"volumes:- meilisearch_data:/meili_datanetworks:- backenddeploy:resources:limits:cpus: "${MEILI_LIMITS_CPUS:-0.5}"memory: ${MEILI_LIMITS_MEMORY:-512M}reservations:cpus: "${MEILI_RESERVATIONS_CPUS:-0.1}"memory: ${MEILI_RESERVATIONS_MEMORY:-128M}volumes:meilisearch_data:The env-var-with-default pattern matches the rest of the stack (see Resource limits).
-
Wire the overlay into
dev.sh. The orchestrator already understandsWITH_<NAME>=1flags. Add the file to thecaseblock:Terminal window # in compose/dev.shif [ "${WITH_MEILISEARCH:-0}" = "1" ]; thenCOMPOSE_FILES+=( "-f" "compose/docker-compose.meilisearch.yml" )fi -
Add a dev-only labels overlay if you want a friendly hostname. Mirror the pattern in
docker-compose.development-labels.yml:docker-compose.meilisearch-dev-labels.yml services:meilisearch:labels:traefik.enable: "true"traefik.http.routers.meilisearch.rule: Host(`meilisearch.localhost`)traefik.http.services.meilisearch.loadbalancer.server.port: "7700"Add a parallel
meilisearch-prod-labels.ymlfor HTTPS + Basic Auth in production, following the GlitchTip prod overlay as the reference shape. -
Document the new flag in
compose/.env.example:Terminal window # Meilisearch overlay (WITH_MEILISEARCH=1)MEILI_MASTER_KEY= -
Boot it:
Terminal window WITH_MEILISEARCH=1 ./scripts/compose-up.sh
Verify
Section titled “Verify”docker compose psshows themeilisearchcontainer in the running list alongside the base stack.- The volume
meilisearch_dataexists:docker volume ls | grep meilisearch. - The dev URL responds:
curl http://meilisearch.localhost/health. - Flags compose:
WITH_MEILISEARCH=1 WITH_OBSERVABILITY=1 ./scripts/compose-up.shbrings up both overlays cleanly. - Stopping cleanly preserves data:
./scripts/compose-down.shthen re-up; the index is still there.
What changes in code
Section titled “What changes in code”infra/compose/compose/docker-compose.meilisearch.yml: new (the service).infra/compose/compose/docker-compose.meilisearch-dev-labels.yml: new (Traefik routing in dev).infra/compose/compose/docker-compose.meilisearch-prod-labels.yml: new (HTTPS + BasicAuth in prod).infra/compose/compose/dev.sh: one newifblock for theWITH_MEILISEARCH=1flag.infra/compose/compose/.env.example: new env stanza.
No changes to docker-compose.yml. That’s the point of the overlay model: the base never grows, opt-in services live in their own files.
Related
Section titled “Related”- Profiles & overlays; how flags compose over the base stack.
- Resource limits; the per-service budget convention.
- Secrets; how env values reach containers safely.
- Infra template overview; the source map for compose files.