Docker Compose for Developers
1. Overview
EMS ships two kinds of Docker Compose usage:
-
Per-service local dependencies — a MySQL + GreenMail stack that admin-service and portals talk to during
mvn spring-boot:runon the host. Developers with Java tooling install admin-service or registration-portal locally, then run a Compose stack for the databases and SMTP. -
Gateway-only dev for frontend-first developers — an image that runs the portal’s Spring Boot gateway + pre-built Angular SPA against a dev admin-service deployed elsewhere (usually the shared dev cluster), so a Angular developer can work on the SPA without installing Java, Maven, or admin-service.
This page describes both. Neither replaces the Kubernetes-based deployment in CI or production; both are developer-only.
See also: Running the Backend Locally.
2. Stack 1: Local Dependencies
Location: admin-service/src/main/docker/ and registration-portal/src/main/docker/ (JHipster convention).
Typical contents:
# admin-service/src/main/docker/mysql.yml
services:
mysql:
image: mysql:8.0
container_name: ems-mysql-dev
environment:
- MYSQL_USER=event-membership
- MYSQL_PASSWORD=
- MYSQL_DATABASE=event_admin_service
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
ports: ['3306:3306']
volumes:
- ems-mysql-data:/var/lib/mysql
command: >
mysqld --lower_case_table_names=1
--skip-mysqlx
--character_set_server=utf8mb4
--explicit_defaults_for_timestamp
volumes:
ems-mysql-data:
Start:
cd admin-service
docker compose -f src/main/docker/mysql.yml up -d
./mvnw
The ./mvnw picks up application-dev.yml which points at localhost:3306. Profile gets auto-activated via the Maven docker-compose profile (see Maven POM Conventions).
2.1. GreenMail for SMTP
# admin-service/src/main/docker/greenmail.yml
services:
greenmail:
image: greenmail/standalone:2.1.0
container_name: ems-greenmail-dev
ports:
- '3025:3025' # SMTP
- '3110:3110' # POP3
- '3143:3143' # IMAP
- '3465:3465' # SMTPS
- '3993:3993' # IMAPS
- '3995:3995' # POP3S
- '8080:8080' # Web UI (browse inbox)
environment:
- GREENMAIL_OPTS=-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 [email protected]:dev
See development/greenmail-email-server.adoc for the standing doc.
2.2. MailHog alternative
MailHog is lighter and has a prettier UI. If GreenMail’s footprint is a concern on dev laptops, substitute:
mailhog:
image: mailhog/mailhog:latest
ports: ['1025:1025', '8025:8025']
Application-dev.yml adjusts SMTP to localhost:1025. Either works; GreenMail is more feature-complete (IMAP for automated tests); MailHog is the lazier dev option.
2.3. Keycloak for OIDC dev
When testing OIDC locally (admin-portal will need this frequently once WS5 starts):
keycloak:
image: quay.io/keycloak/keycloak:24.0
command: start-dev
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
ports: ['8180:8080']
volumes:
- ./keycloak-realm-dev.json:/opt/keycloak/data/import/realm.json:ro
Realm export file (keycloak-realm-dev.json) pre-seeded with an admin-portal-dev client registration and a few test users. Commit the realm file to admin-portal/src/main/docker/ so docker compose up produces a working OIDC setup on first try.
registration-portal’s existing application-oidc-dev.yml targets this Keycloak; admin-portal will point at the same one.
3. Stack 2: Gateway-Only Dev for Frontend Developers
Goal: enable a frontend developer with only Node installed (no Java, no Maven, no IDE) to clone the portal repo, npm install, npm start, and see a working SPA backed by a shared dev admin-service.
Mechanism:
-
Portal publishes a pre-built Docker image containing the Spring Boot gateway without the Angular bundle — the gateway serves a placeholder
index.htmlat/but proxies/services/admin-service/**to the configured admin-service URL and handles OIDC + session + API-key injection. -
Angular
npm startrunsng serveon port 4200 (or BrowserSync on 9000) with a proxy config targeting the gateway container’s port 12506. -
The browser hits
localhost:9000/services/admin-service/api/…, BrowserSync proxies tolocalhost:12506/services/admin-service/api/…, the gateway proxies to the shared dev admin-service with the right headers.
# admin-portal/src/main/docker/dev-gateway.yml
services:
gateway-only:
image: docker.io/christhonie/event-admin-portal:latest
environment:
- SPRING_PROFILES_ACTIVE=dev
- APPLICATION_ADMIN_SERVICE_URL=https://dev-event-admin-service.idealogic.co.za
- APPLICATION_ADMIN_SERVICE_API_KEY=${DEV_ADMIN_SERVICE_API_KEY}
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_ISSUER_URI=https://keycloak-dev.idealogic.co.za/realms/admin-portal-dev
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENT_ID=admin-portal-dev
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENT_SECRET=${DEV_OIDC_CLIENT_SECRET}
ports:
- '12506:12506'
The frontend developer then:
git clone admin-portal && cd admin-portal/src/main/webapp
npm install
# in another terminal:
docker compose -f ../../docker/dev-gateway.yml up -d
npm start # ng serve with proxy.conf.js pointing at :12506
3.1. Proxy config for Angular dev server
admin-portal/src/main/webapp/webpack/proxy.conf.js routes the right paths to the gateway container:
module.exports = function ({ tls }) {
const protocol = tls ? 'https' : 'http';
return [
{
context: ['/services', '/api', '/oauth2', '/login', '/logout', '/management'],
target: `${protocol}://localhost:12506`,
secure: false,
changeOrigin: true,
},
];
};
Everything not starting with those prefixes (i.e. the SPA itself) is served by ng serve.
4. Caveats
4.1. Dev data
The shared dev admin-service has shared data. Frontend devs share a tenant pool; changes made in one browser are visible to all. Acceptable for UI development; not acceptable for end-to-end flow testing where clean state matters. For that, run admin-service locally (Stack 1) with an empty MySQL.
4.2. OIDC flow in gateway-only stack
The OIDC redirect from Keycloak to the gateway needs a reachable callback. localhost:12506 works if Keycloak is also running locally; if Keycloak is on a shared dev cluster, it must be configured to accept localhost:12506 as a redirect URI. Add http://localhost:12506/login/oauth2/code/keycloak to the client’s valid-redirect-URIs list.
5. What About Running Everything in Compose
A "full stack" Compose (admin-service + MySQL + portal + Keycloak + GreenMail) would replace the Kubernetes-based dev cluster for fully-local workflows. We don’t ship one today. Reasons:
-
admin-service has Liquibase migrations that take minutes against a clean database; users will kill containers before they’re ready.
-
Keeping a Compose file in sync with admin-service’s config changes is a maintenance burden that has burned us before.
-
Developers who need a real environment use
idl-xnl-jhb-rc01(shared dev cluster) via ArgoCD.
If a concrete pain point emerges (e.g. offline development during travel), revisit. Do not add a full-stack Compose pre-emptively.
6. Reference
| File | Role |
|---|---|
|
Local MySQL for admin-service dev |
|
Local GreenMail for SMTP testing |
|
Portal-side Compose files (if any) |
|
Standing doc for GreenMail usage |
|
End-to-end local backend setup |