AEM and Docker Compose for Local Orchestration
Running Adobe Experience Manager locally becomes unwieldy when Author, Publish, Dispatcher and supporting services live in separate installations. AEM and Docker Compose orchestration places those components in one declarative network, giving developers repeatable startup order, shared endpoints and isolated dependencies.
This pattern suits AEM 6.x environments used for development and proof-of-concept work. AEM as a Cloud Service is a managed service and cannot be self-hosted in a Compose stack, so cloud projects should use authorised local mocks or SDK tooling instead. The patterns here apply where licensed AEM artefacts are available.
CIRCUIT’s 2015 and 2016 Chicago conference archive remains a valuable source for AEM architecture, workflows and integration ideas. Its sessions provide context for why developers separated authoring, delivery and caching long before container orchestration became common.
Why Local Orchestration Matters
Orchestration is valuable only when each tier has a clear boundary. The local stack should reproduce how content moves, not pretend to be a production data centre. Comparing the roles prevents teams from assigning replication, rendering or cache invalidation to the wrong service.
| Component | Main responsibility | Local endpoint | Essential check |
|---|---|---|---|
| Author | Creates, edits, versions and packages content | http://localhost:4502 |
Authoring UI and package deployment |
| Publish | Receives replicated content and serves it to delivery services | http://localhost:4503 |
Published paths return expected assets |
| Dispatcher | Caches responses, rewrites URLs and applies delivery controls | http://localhost:8080 |
Cache hit, flush and header behaviour |
Compose then supplies the connective tissue: service discovery, dependency conditions, environment variables and persistent storage. The result is a workstation environment that starts with docker compose up -d and remains easy to reset when a package, fixture or schema changes.
Designing the Compose Stack
Begin with a deliberately small topology: one Author, one Publish, Dispatcher and the databases each instance needs. Add services only when a developer can name the dependency they remove. A reverse proxy, mail catcher or debugging tool can sit behind a Compose profile so the core stack stays understandable.
Express shared settings in environment variables and keep a checked-in .env.example without real credentials. Use named volumes for AEM repositories, package storage and database files, while mounting configuration read-only. Health checks and startup delays should reflect actual AEM boot time rather than an arbitrary sleep.
Keep frontend code outside the AEM container and rebuild it separately or through a dedicated build service. Reusable content components reduce the need to duplicate whole pages; the archived explanation of AEM Experience Fragments shows how shared fragments can cross site boundaries while remaining governed in Author.
Running Author and Publish
AEM 6.x instances still require suitable Java, licence files and database configuration. Build the Author and Publish images from the licensed distribution, then pin image digests and Java parameters rather than relying on floating tags. A first boot can take several minutes, so readiness checks should query a meaningful AEM path and allow enough time for Oak indexes and bundles to settle.
Author and Publish need persistent repositories and carefully matched database schemas. MongoDB or an external relational store can serve as the Oak persistence layer, depending on the supported AEM release and deployment profile. Never point two production-like instances at the same working data directory, and use separate schemas or databases for clean isolation.
Replication is the critical path between the tiers. Configure the Author publish agent to target the Publish hostname from inside the Compose network, then verify that a test page appears on Publish. Synchronisation checks expose missing Sling jobs, broken dispatcher rules or package problems earlier, especially when several developers start with different local content.
Dispatcher and Local Routing
Dispatcher should consume published content while keeping the AEM Publish service private. Point its farm configuration at the Publish service name, not the author’s host, and map only the Dispatcher port to the workstation. This mirrors common delivery architecture and prevents a developer from accidentally testing unpublished content through the cache layer.
Cache behaviour needs a deliberate local workflow. Publish changes should invalidate the relevant paths, while an administrative flush should remain restricted and environment-specific. Test both a cold request and a repeated request: the first should populate the cache, and the second should demonstrate that Dispatcher is serving the expected response without repeatedly contacting Publish.
Local domains and host headers can expose configuration errors that localhost hides. Use predictable names such as publish.localhost and dispatcher.localhost, map them to loopback, and align Dispatcher virtual hosts, rewrite rules and allowed hosts. Keep CORS settings narrow, and load-test representative assets rather than relying on a single page request.
Data, Configuration, and Secrets
Name volumes after their purpose, not after a developer or ticket. Back up authored packages and seeded database fixtures before destructive tests, and provide a reset path that restores known state. Read-only mounts suit Dispatcher configuration and static frontend files; mutable AEM repositories need writable volumes with sensible ownership.
Keep licences, passwords and access tokens out of committed YAML and images. Supply them through local environment files or a secrets manager, and exclude sensitive files from version control. Synthetic data is safer for demonstrations, but teams still need to understand that the Australian Privacy Act 1988 and the Notifiable Data Breaches scheme can apply when real personal information enters Australian systems.
Multilingual content adds another shared concern for Australian brands and government agencies. AEM translation services provide a useful pattern for connecting translation workflows, locales and permissions. In the local stack, test language negotiation and fallback content without duplicating every fragment manually.
Supporting Distributed Australian Teams
Teams spread across Sydney, Melbourne and Brisbane must account for different working hours. Brisbane remains on AEST while Sydney and Melbourne shift to AEDT, and Adelaide sits another half-hour away, so replicated content can look out of sequence when logs use container defaults. Set TZ, include timestamps in health output and record which Australian timezone each runbook assumes.
Developers commonly connect from trains, shared offices, customer sites and cafés, where corporate VPN latency or filtered hotel Wi-Fi can interrupt downloads. Cached container layers and lightweight seed content make a local stack more resilient, while a documented offline demo path protects workshops when every device must start at once. Practical exchange is valuable through the xtextcon community.
The Australian market includes large Adobe consultancies, enterprise programmes and long-running AEM estates, so reusable runbooks can move between projects. Use Australian English, spell out unfamiliar abbreviations and distinguish local development settings from production controls. Capturing these conventions in the repository reduces cognitive load when colleagues join from different cities or partner organisations.
Start With a Repeatable Local Environment
Before assembling the stack, check the conference FAQ for access to CIRCUIT recordings and supporting event information. Use the archived sessions to reinforce service boundaries, then define one acceptance path: create a page in Author, replicate it to Publish, request it through Dispatcher and confirm a cache hit.
Treat the first clean-machine run as the acceptance test. Include a documented Java version, image digests, database versions, ports, volumes, seed packages and startup commands. Exercise service failure, cache flush and repository reset before sharing the environment, since those operational tests often reveal more than a successful homepage check.
Create the Compose project today with the core stack, sample content and a repeatable demonstration script. Run it on a clean workstation, record startup order and package the evidence with the team handoff. Turn that successful path into the foundation for integrations, automated tests and future microservice experiments.