Filesystem Layout
MultiDocker keeps nothing in your project directories beyond the files you already committed. Its own state lives in two well-defined trees: one for the CLI, one for the app.
The repository
Section titled “The repository”If you’re running from a clone, the tool itself is laid out like this:
multi-docker/├── bin/mdocker CLI entry point (one large bash script)├── lib/common.sh Shared bash lib (paths, config, registry, compose, port-check)├── edge/ Traefik + Mailcatcher + dnsmasq + docker-socket-proxy│ ├── compose.yml│ ├── traefik/{traefik.yml, dynamic/{tls.yml, serverstransports.yml}}│ └── docker-proxy/{nginx.conf, nginx.main.conf}├── engine/ Generators + per-project subsystems│ ├── detect.sh Profile heuristic│ ├── render.sh Project override generator│ ├── render-edge.sh Edge override generator│ ├── terminal.sh tmux session manager│ ├── git.sh Git snapshot│ ├── share.sh Public demo tunnel│ ├── profiles/*.yml Override templates│ ├── shopware/*.sh Shopware verbs│ └── db/*.sh DB dialect detection + dump/restore/shell/open├── scripts/ Setup scripts (TLS, DNS, network, doctor)└── macos-app/ SwiftUI front-endCLI state: ~/.config/multi-docker/
Section titled “CLI state: ~/.config/multi-docker/”Everything the standalone CLI creates lives here:
~/.config/multi-docker/├── config.env BASE_DOMAINS, EDGE_NETWORK, optional EDITOR_CMD/EXEC_SHELL├── registry.json Known projects (the source of truth)├── overrides/│ ├── <name>.override.yml profile-rendered override│ ├── <name>.ports.yml port-conflict resolution (if any)│ └── edge.override.yml multi-domain edge override├── certs/│ ├── wildcard.pem│ ├── wildcard-key.pem│ └── ca/{rootCA.pem, rootCA-key.pem} mkcert CA — never commit this├── snapshots/│ └── <project>/<service>-<ts>.sql.gz + <service>-latest symlink└── state/ └── tunnels/<project>__<host>.{json,log} ephemeral share tunnelsApp state: ~/.multidocker/
Section titled “App state: ~/.multidocker/”The macOS app uses its own directory and its own runtime copy of the tool:
~/.multidocker/├── bin/mdocker wrapper that resolves the "current" runtime├── runtime/│ └── <version>/ extracted runtime (bin, lib, engine, scripts, edge)├── current → runtime/<v> symlink updated on install├── config/ the app's config dir (registry, overrides, certs, …)├── preferences/preferences.json├── state/{wizard.json, .migrated-*}└── logs/console-YYYY-MM.log rotating JSONL console logWhy certs live in the config directory
Section titled “Why certs live in the config directory”The mkcert CA and wildcard cert live under config/certs/, deliberately outside the
app’s runtime/<version>/ folder:
Older installs kept certs under edge/certs/; that path still exists for migration
(ensure_certs_dir), but the live store is now the config directory.
Changing the base domain regenerates the derived files
Section titled “Changing the base domain regenerates the derived files”Because overrides and certs are derived from the registry and config, changing the base
domain via mdocker config set BASE_DOMAIN <new> regenerates the certificate, the resolver,
every project override and the edge stack automatically. See
Changing the Base Domain.
Cookie settings
We only use statistics tools if you allow it. Necessary storage keeps this site working; everything else is off until you decide.
Stores your choice from this dialog in your browser (localStorage). No cookie, no transfer to third parties.
Google Analytics 4 via Google Tag Manager, to measure how the site is used. Loaded only after you allow it.