Flavors
Flavors allow you to define different configurations for different environments (development, staging, production) using JSON Patch (RFC 6902). Instead of duplicating configuration, you define a base config and patches that modify it.
How Flavors Work
Section titled “How Flavors Work”- EMB loads your base configuration
- When you specify a flavor with
--flavor, EMB applies the patches - The patched configuration is used for the operation
Defining Flavors
Section titled “Defining Flavors”Project-Level Flavors
Section titled “Project-Level Flavors”Define flavors at the project level to affect global settings:
env: DOCKER_TAG: ${env:DOCKER_TAG:-latest}
flavors: production: patches: - op: replace path: /env/DOCKER_TAG value: ${env:DOCKER_TAG}-productionComponent-Level Flavors
Section titled “Component-Level Flavors”Define flavors within a component to change its build settings:
resources: image: type: docker/image params: target: development
flavors: production: patches: - op: replace path: /resources/image/params/target value: productionJSON Patch Operations
Section titled “JSON Patch Operations”Flavors use JSON Patch RFC 6902. Common operations:
Replace
Section titled “Replace”Change an existing value:
patches: - op: replace path: /resources/image/params/target value: productionAdd a new property:
patches: - op: add path: /resources/image/params/buildArgs/DEBUG value: "false"Remove
Section titled “Remove”Remove a property:
patches: - op: remove path: /resources/image/params/buildArgs/DEBUGUsing Flavors
Section titled “Using Flavors”Run Services with a Flavor
Section titled “Run Services with a Flavor”emb up --flavor productionRun Tasks with a Flavor
Section titled “Run Tasks with a Flavor”emb run test --flavor productionExample: Multi-Stage Docker Builds
Section titled “Example: Multi-Stage Docker Builds”A common pattern is using flavors for multi-stage Docker builds:
# DockerfileFROM node:20 AS baseWORKDIR /appCOPY package*.json ./
FROM base AS developmentRUN npm installCOPY . .CMD ["npm", "run", "dev"]
FROM base AS productionRUN npm ci --only=productionCOPY . .CMD ["npm", "start"]resources: image: type: docker/image params: target: development
flavors: production: patches: - op: replace path: /resources/image/params/target value: productionNow:
emb upbuilds and runs the development stageemb up --flavor productionbuilds and runs the production stage
You can also build resources explicitly with emb resources build --flavor production.
Flavor Inheritance
Section titled “Flavor Inheritance”When both project-level and component-level flavors with the same name exist, both are applied:
- Project-level patches are applied first
- Component-level patches are applied second
This allows you to:
- Set global environment changes at project level
- Set component-specific build changes at component level
Viewing Flavor Configuration
Section titled “Viewing Flavor Configuration”To see what configuration a flavor produces:
emb config print --flavor productionThis shows the fully resolved configuration after applying flavor patches.
Rebuild Policies
Section titled “Rebuild Policies”Beyond JSON Patch, flavors can set a defaults.rebuildPolicy that changes
how EMB decides whether a resource needs a rebuild. Today this applies to
docker/image resources.
The common case: in dev, source is bind-mounted into containers via
docker-compose.devel.yml, so rebuilding the image on every source change
is pointless — the container already sees the new code. You only want a
rebuild when image-shaping files change (Dockerfile, package.json,
lockfiles, system-package lists).
Set a flavor-wide policy under defaults.rebuildPolicy['docker/image']:
flavors: dev: defaults: rebuildPolicy: docker/image: strategy: watch-paths paths: - Dockerfile - package.json
prod: {} # absent → falls back to the builtin 'auto' strategyThree strategies are available:
| Strategy | Rebuilds when | Typical use |
|---|---|---|
auto (default) | any git-tracked file in the docker context changed | CI, production |
always | every invocation | images fetching external content at build time |
watch-paths | one of the listed paths changed | dev with bind-mounted source |
Overriding at the resource level
Section titled “Overriding at the resource level”A resource’s own rebuildTrigger wins against any flavor-level default:
resources: image: type: docker/image rebuildTrigger: strategy: always # wins even when --flavor dev sets watch-pathsSee the full precedence and path semantics in the
configuration reference.
A runnable example lives under examples/rebuild-triggers/.