Docker Environments
name: Docker Environments category: connect activateOn: docker-environment freedomLevel: high version: 1.0.0 description: > Docker-aware Mémoire operation. Detects Dockerfile, docker-compose.yml, and .devcontainer/ in the project root and adapts the Mémoire pipeline accordingly. Covers Figma bridge port-forwarding, CI/CD headless audits, shared MCP server as a team service, agent worker containers, and devcontainer setup.
1. Auto-Detection
Mémoire activates this Note when any of the following are present in the project root:
| File / Directory | Signals |
|---|---|
Dockerfile | Single-service container build |
docker-compose.yml / docker-compose.yaml | Multi-service orchestration |
compose.yml / compose.yaml | Compose v2 convention |
.devcontainer/devcontainer.json | VS Code / Codespaces dev environment |
.devcontainer/docker-compose.yml | Devcontainer with compose override |
When detected, Mémoire applies these Docker-aware defaults:
- Bridge discovery checks
localhostANDhost.docker.internal - Preview server binds to
0.0.0.0(not127.0.0.1) - Port conflict warnings include Docker port-mapping guidance
memi doctoroutput includes container networking status
2. Figma Bridge in Docker
Problem: Figma plugin runs on the host machine. Mémoire inside a container cannot auto-discover it — localhost inside the container is the container, not the host.
Fix: Forward the bridge port range from host to container.
yaml# docker-compose.yml services: memoire: ports: - "9223-9232:9223-9232" # Figma bridge range
json// .memoire/project.json { "bridge": { "host": "0.0.0.0", "portRange": [9223, 9232] } }
When NOT to use Docker for canvas work: If your primary workflow is Figma canvas operations (design, library, real-time sync), run Mémoire on the host. Port forwarding works but adds latency. Use Docker for CI, MCP, and agent workers.
3. CI/CD Headless Pipeline
Headless-Safe Commands
| Command | Needs Bridge | CI-Safe |
|---|---|---|
memi audit --wcag | No | Yes |
memi spec validate | No | Yes |
memi generate | No | Yes |
memi research synthesize | No | Yes |
memi preview | No | Yes |
memi pull | Yes | No |
memi sync | Yes | No |
memi connect | Yes | No |
Dockerfile (CI Build)
dockerfileFROM node:20-alpine AS base WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --ignore-scripts COPY . . RUN npm run build FROM base AS ci ENV MEMOIRE_HEADLESS=true ENV MEMOIRE_NO_BRIDGE=true ENTRYPOINT ["node", "dist/cli.js"]
docker-compose.yml with Profiles
yamlversion: "3.9" services: # Local dev — bridge enabled, ports forwarded memoire-dev: build: { context: ., target: base } profiles: ["dev"] ports: - "4400:4400" - "4401:4401" - "9223-9232:9223-9232" volumes: [".:/app", "/app/node_modules"] environment: [MEMOIRE_ENV=development] command: ["node", "dist/cli.js", "watch", "--code"] # CI — headless, no bridge memoire-ci: build: { context: ., target: ci } profiles: ["ci"] volumes: [".:/workspace"] working_dir: /workspace environment: [MEMOIRE_HEADLESS=true, MEMOIRE_NO_BRIDGE=true] command: ["node", "dist/cli.js", "audit", "--wcag", "--exit-code"] # MCP server — shared team service memoire-mcp: build: { context: ., target: base } profiles: ["mcp"] ports: ["4402:4402"] environment: [MEMOIRE_MCP_PORT=4402] command: ["node", "dist/cli.js", "mcp", "start"] restart: unless-stopped
Running CI Audits
bash# Run headless WCAG audit docker compose --profile ci run --rm memoire-ci # Validate all specs docker compose --profile ci run --rm memoire-ci \ node dist/cli.js spec validate --all --strict # Dry-run code generation docker compose --profile ci run --rm memoire-ci \ node dist/cli.js generate --dry-run
GitHub Actions
yamlname: Design System CI on: [push, pull_request] jobs: design-audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: WCAG audit run: docker compose --profile ci run --rm memoire-ci - name: Validate specs run: docker compose --profile ci run --rm memoire-ci node dist/cli.js spec validate --all --strict - name: Generate (dry run) run: docker compose --profile ci run --rm memoire-ci node dist/cli.js generate --dry-run
Exit Codes
| Code | Meaning | Gate |
|---|---|---|
0 | All pass | — |
1 | Warnings | Fail with --fail-on-warn |
2 | Errors | Always fails |
3 | Critical violations | Always fails |
Soft policy: gate on 2+. Strict policy: gate on 1+.
4. Shared MCP Server (Team Service)
Problem: Each developer running memi mcp start locally produces divergent design system state.
Fix: Deploy one containerized MCP instance. All Claude Code and Cursor sessions on the team point to it.
dockerfileFROM node:20-alpine WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build VOLUME ["/workspace/.memoire"] EXPOSE 4402 CMD ["node", "dist/cli.js", "mcp", "start", "--port", "4402"]
Claude Code config for each developer — replace localhost with the shared host:
json{ "mcpServers": { "memoire": { "url": "http://memoire.internal:4402/mcp", "transport": "http" } } }
Shared volume for .memoire/ state:
yamlservices: memoire-mcp: volumes: - design-system:/workspace/.memoire command: ["node", "dist/cli.js", "mcp", "start"] volumes: design-system: driver: local driver_opts: type: nfs o: addr=nas.internal,rw device: ":/design-system"
5. Agent Workers as Containers
Each role gets isolated resources, its own restart policy, and no shared process state.
yamlservices: token-engineer: build: . command: ["node", "dist/cli.js", "agent", "spawn", "token-engineer"] environment: [MEMOIRE_AGENT_ROLE=token-engineer] restart: on-failure:3 healthcheck: test: ["CMD", "node", "dist/cli.js", "agent", "status", "--role", "token-engineer", "--json"] interval: 30s timeout: 10s retries: 3 start_period: 15s component-architect: build: . command: ["node", "dist/cli.js", "agent", "spawn", "component-architect"] environment: [MEMOIRE_AGENT_ROLE=component-architect] restart: on-failure:3 accessibility-checker: build: . command: ["node", "dist/cli.js", "agent", "spawn", "accessibility-checker"] environment: [MEMOIRE_AGENT_ROLE=accessibility-checker] restart: on-failure:3 orchestrator: build: . command: ["node", "dist/cli.js", "compose", "--listen"] depends_on: [token-engineer, component-architect, accessibility-checker] restart: unless-stopped
Scale bottleneck roles (the task queue is lock-based — multiple workers are safe):
bashdocker compose up --scale code-generator=3
6. Devcontainer Support
json// .devcontainer/devcontainer.json { "name": "Mémoire Dev", "dockerComposeFile": "docker-compose.yml", "service": "memoire-dev", "workspaceFolder": "/app", "features": { "ghcr.io/devcontainers/features/node:1": { "version": "20" } }, "forwardPorts": [4400, 4401, 9223, 9224, 9225], "postCreateCommand": "npm ci && npm run build", "customizations": { "vscode": { "extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] } }, "remoteEnv": { "FIGMA_ACCESS_TOKEN": "${localEnv:FIGMA_ACCESS_TOKEN}", "MEMOIRE_ENV": "development" } }
remoteEnvforwardsFIGMA_ACCESS_TOKENfrom host shell — set once in.zshrc/.bashrc, never committed.- VS Code auto-forwards ports in
forwardPorts. The Figma plugin connects tolocalhost:9223on the host; VS Code tunnels it into the container transparently.
7. Environment Variables Reference
| Variable | Default | Purpose |
|---|---|---|
MEMOIRE_HEADLESS | false | Disables interactive TUI, uses JSON output |
MEMOIRE_NO_BRIDGE | false | Skips Figma bridge discovery entirely |
MEMOIRE_ENV | development | development, ci, production |
MEMOIRE_MCP_PORT | 4402 | Port for MCP HTTP transport |
MEMOIRE_PREVIEW_PORT | 4400 | Port for preview server |
MEMOIRE_DASHBOARD_PORT | 4401 | Port for dashboard server |
MEMOIRE_BRIDGE_HOST | 0.0.0.0 | Host to bind the WebSocket bridge listener |
MEMOIRE_AGENT_ROLE | general | Role for a spawned agent worker |
FIGMA_ACCESS_TOKEN | — | Figma REST API token (required for memi pull) |
Set in .env for local dev (never commit). Use Docker secrets or CI environment for production.
8. .memoire/project.json Docker Block
json{ "docker": { "enabled": true, "mode": "dev", "bridge": { "host": "0.0.0.0", "portRange": [9223, 9232], "fallbackHost": "host.docker.internal" }, "preview": { "host": "0.0.0.0", "port": 4400 }, "ci": { "headless": true, "noBridge": true, "exitOnAuditError": true, "failOnWarn": false }, "mcp": { "shared": true, "host": "memoire.internal", "port": 4402 } } }
| Field | Default | Description |
|---|---|---|
docker.mode | dev | dev, ci, or mcp |
bridge.fallbackHost | host.docker.internal | Fallback for Docker Desktop on Mac/Win |
ci.failOnWarn | false | Exit non-zero on audit warnings |
mcp.shared | false | Use shared remote MCP server |
9. Anti-Patterns
Never: Run bridge exclusively in Docker for canvas work
Every canvas op adds a port-forward round trip. Run Mémoire on the host for design-heavy sessions.
Never: Use root user in production containers
dockerfile# Bad CMD ["node", "dist/cli.js"] # Good RUN addgroup -S memoire && adduser -S memoire -G memoire USER memoire CMD ["node", "dist/cli.js"]
Never: Bake .memoire/ into the image
Mount it as a volume. Baking it in means every spec change requires a rebuild.
dockerfileVOLUME ["/workspace/.memoire"]
Never: Bind preview server to 127.0.0.1 in containers
Set MEMOIRE_PREVIEW_HOST=0.0.0.0 or configure via .memoire/project.json.
Never: Hardcode FIGMA_ACCESS_TOKEN in docker-compose.yml
yaml# Bad environment: [FIGMA_ACCESS_TOKEN=figd_abc123...] # Good — read from host env environment: [FIGMA_ACCESS_TOKEN=${FIGMA_ACCESS_TOKEN}] # Production — Docker secrets secrets: figma_token: { external: true } services: memoire-mcp: secrets: [figma_token] environment: [FIGMA_ACCESS_TOKEN_FILE=/run/secrets/figma_token]
Never: Skip health checks on agent workers
Dead workers stall the task queue. The heartbeat timeout is 30s. Always add health checks and restart: on-failure.


