Skip to content

Docker Compose Override

dde configures Docker Compose projects through two complementary mechanisms:

  1. Persistent modifications to the project’s docker-compose.yml during project:init (via DockerComposeModifier)
  2. A temporary runtime override file generated during project:up (via DockerComposeManager::generateOverride())

Persistent Compose Modifications (project:init)

Section titled “Persistent Compose Modifications (project:init)”

The DockerComposeModifier class modifies the project’s actual docker-compose.yml during project:init. These are one-time changes committed to the repository.

All project containers are attached to the shared dde Docker network:

networks:
default:
name: dde
external: true

Generated by DockerComposeModifier::addNetwork().

Routing labels are added to web services so Traefik can route HTTP/HTTPS traffic:

services:
web:
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.myproject-test-web.rule=Host(`myproject.test`)'
- 'traefik.http.routers.myproject-test-web-tls.rule=Host(`myproject.test`)'
- 'traefik.http.routers.myproject-test-web-tls.tls=true'

If the compose file contains VIRTUAL_HOST and/or VIRTUAL_PORT environment variables (v1 format), they are consumed and converted to Traefik labels. The environment variables are then removed.

If a VIRTUAL_PORT is specified, a load balancer port label is also added:

- 'traefik.http.services.myproject-test-web.loadbalancer.server.port=8080'

Generated by DockerComposeModifier::addTraefikLabels().

The SSH agent socket is mounted into containers so SSH keys are available:

services:
web:
volumes:
- dde_ssh-agent_socket-dir:/tmp/ssh-agent:ro
volumes:
dde_ssh-agent_socket-dir:
external: true

Generated by DockerComposeModifier::addSshAgentVolume(). Old v1-format volume names are automatically migrated.

When the compose file defines a database service (mariadb or postgres), the modifier automatically adds DATABASE_URL to the main container:

services:
web:
environment:
- DATABASE_URL=mysql://root:root@mariadb:3306/myproject

Similarly, if a mailpit service is present:

services:
web:
environment:
- MAILER_DSN=smtp://mailpit:1025

These are only added if the variables are not already defined in the service environment or in the project’s .env / .env.dev files. Generated by DockerComposeModifier::addServiceEnvironment().

Legacy DDE_UID and DDE_GID build args from v1 are cleaned up by DockerComposeModifier::removeV1BuildArgs().

During project:up, DockerComposeManager::generateOverride() creates a temporary override file that layers runtime configuration on top of the project’s compose file without modifying it.

The override replaces the entrypoint with the dde entrypoint and mounts adapter scripts:

services:
web:
entrypoint: ['/dde/entrypoint.sh']
command: ['/original/entrypoint.sh', 'original-cmd']
volumes:
- /path/to/resources/entrypoint.sh:/dde/entrypoint.sh:ro
- /path/to/resources/adapters:/dde/adapters:ro

The original entrypoint and CMD from the Docker image are preserved as the command, so exec "$@" in the dde entrypoint chains to the original startup sequence.

If the project has custom adapters in .dde/adapters/, they are also mounted:

- /path/to/project/.dde/adapters:/dde/adapters-project:ro

The override passes the host user context and optional shell preference:

services:
web:
environment:
DDE_UID: "1000"
DDE_GID: "1000"
DDE_SHELL: "zsh"

The external SSH-Agent volume is declared at the top level:

volumes:
dde_ssh-agent_socket-dir:
external: true

If a dev layer was built (see Dev Layer Builder), the override replaces the service image with the dev layer image tag:

services:
web:
image: dde-myproject:dev

All services get a dde.managed=true label for identification:

services:
web:
labels:
- 'dde.managed=true'

When running in a git worktree, additional Traefik router labels are generated for the worktree hostname (e.g. myproject-feature.test).

The runtime override file is:

  1. Generated before docker compose up by DockerComposeManager::generateOverride()
  2. Applied as a second -f argument: docker compose -f docker-compose.yml -f override.yml up -d
  3. Removed after docker compose up completes (in a finally block to ensure cleanup)

This approach keeps the project’s compose file unmodified at runtime.