Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions docker-compose.local-email.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Local Email Services for Development
#
# Usage:
# docker-compose -f docker-compose.local-email.yml up -d
#
# Services:
# - mailpit (SMTP: 1025, Web UI: 8025)
# - constructive-admin-server (3002)
# - send-email-link (8082)
# - knative-job-service (8080)
#
# Prerequisites:
# - PostgreSQL running with constructive database
# - Network: constructive-net (created by docker-compose.yml)
# - Build image first: docker build -t constructive:dev .

services:
# Mailpit - Local email testing (replaces Mailgun)
mailpit:
container_name: mailpit
image: axllent/mailpit:latest
ports:
- "1025:1025" # SMTP
- "8025:8025" # Web UI
networks:
- constructive-net

# Admin GraphQL Server (internal, header-based routing)
constructive-admin-server:
container_name: constructive-admin-server
image: constructive:dev
entrypoint: ["constructive", "server", "--host", "0.0.0.0", "--port", "3000", "--origin", "*"]
Comment on lines +29 to +32
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compose file pins container_name for constructive-admin-server (and also send-email-link / knative-job-service below). Because these names are also used in docker-compose.jobs.yml, running both stacks (or reusing containers across projects) will fail with container-name conflicts. Consider removing container_name so Compose can namespace by project, or prefix these names (e.g., local-email-...) and update internal URLs accordingly.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added extra_hosts: ["host.docker.internal:host-gateway"] to support Linux Docker Engine.

macOS/Windows Docker Desktop will ignore this setting (already has built-in support), so no impact on existing usage.

extra_hosts:
- "host.docker.internal:host-gateway"
environment:
NODE_ENV: development
PORT: "3000"
SERVER_HOST: "0.0.0.0"
SERVER_TRUST_PROXY: "true"
SERVER_ORIGIN: "*"
SERVER_STRICT_AUTH: "false"
# Postgres - use host.docker.internal to connect to local postgres
PGHOST: host.docker.internal
Comment on lines +42 to +43
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PGHOST: host.docker.internal is not resolvable by default on many Linux Docker setups (and differs from the repo’s other compose stacks which use the postgres service name on constructive-net). If this stack is meant to work with the postgres container started by docker-compose.yml, set PGHOST to postgres; if it’s meant to connect to a host-installed Postgres, add the required extra_hosts: ["host.docker.internal:host-gateway"] (or document the Docker Desktop requirement).

Suggested change
# Postgres - use host.docker.internal to connect to local postgres
PGHOST: host.docker.internal
# Postgres - use postgres service on constructive-net
PGHOST: postgres

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added extra_hosts: ["host.docker.internal:host-gateway"] to support Linux Docker Engine.

macOS/Windows Docker Desktop will ignore this setting (already has built-in support), so no impact on existing usage.

PGPORT: "5432"
PGUSER: ${PGUSER:-postgres}
PGPASSWORD: ${PGPASSWORD:-password}
PGDATABASE: constructive
# API configuration
API_ENABLE_SERVICES: "true"
API_IS_PUBLIC: "false"
API_EXPOSED_SCHEMAS: "metaschema_public,services_public,constructive_auth_public"
API_META_SCHEMAS: "metaschema_public,services_public,metaschema_modules_public,constructive_auth_public"
API_ANON_ROLE: "administrator"
API_ROLE_NAME: "administrator"
ports:
- "3002:3000"
networks:
- constructive-net

# Send email link function (uses SMTP to Mailpit)
send-email-link:
container_name: send-email-link
image: constructive:dev
entrypoint: ["node", "functions/send-email-link/dist/index.js"]
depends_on:
- mailpit
- constructive-admin-server
environment:
NODE_ENV: development
PORT: "8080"
LOG_LEVEL: info
# GraphQL endpoints
GRAPHQL_URL: "http://constructive-admin-server:3000/graphql"
META_GRAPHQL_URL: "http://constructive-admin-server:3000/graphql"
GRAPHQL_API_NAME: "private"
# SMTP configuration (Mailpit)
EMAIL_SEND_USE_SMTP: "true"
SMTP_HOST: mailpit
SMTP_PORT: "1025"
SMTP_FROM: "noreply@localhost"
# Local app port for email links
LOCAL_APP_PORT: "3011"
ALLOW_LOCALHOST: "true"
SEND_EMAIL_LINK_DRY_RUN: "false"
ports:
- "8082:8080"
networks:
- constructive-net

# Job service (polls app_jobs, triggers send-email-link)
knative-job-service:
container_name: knative-job-service
image: constructive:dev
entrypoint: ["node", "jobs/knative-job-service/dist/run.js"]
depends_on:
- send-email-link
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
NODE_ENV: development
# Postgres - use host.docker.internal to connect to local postgres
PGHOST: host.docker.internal
PGPORT: "5432"
PGUSER: ${PGUSER:-postgres}
PGPASSWORD: ${PGPASSWORD:-password}
PGDATABASE: constructive
Comment on lines +101 to +106
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above: PGHOST: host.docker.internal can break on Linux and is inconsistent with the docker-compose.yml Postgres container workflow. Consider using PGHOST=postgres when relying on the shared constructive-net, or add an extra_hosts mapping for host.docker.internal if connecting to host Postgres is intentional.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added extra_hosts: ["host.docker.internal:host-gateway"] to support Linux Docker Engine.

macOS/Windows Docker Desktop will ignore this setting (already has built-in support), so no impact on existing usage.

JOBS_SCHEMA: app_jobs
# Worker config
JOBS_SUPPORT_ANY: "true"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JOBS_SUPPORT_ANY is set to "true" while JOBS_SUPPORTED is also set. When JOBS_SUPPORT_ANY is true, the knative job worker/scheduler will poll for and attempt to execute all task identifiers in app_jobs (ignoring the supported list), which can cause repeated failures if other job types exist. Set JOBS_SUPPORT_ANY to "false" here to ensure only send-email-link is processed (matching the intent of this compose file).

Suggested change
JOBS_SUPPORT_ANY: "true"
JOBS_SUPPORT_ANY: "false"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding JOBS_SUPPORT_ANY = true:

Keeping it as true is intentional for extensibility. When adding new job services in the future (e.g., send-sms), we only need to update INTERNAL_GATEWAY_DEVELOPMENT_MAP - no need to maintain two separate configs.

If an unconfigured job type appears in app_jobs, the error serves as a reminder to add the gateway mapping.

JOBS_SUPPORTED: "send-email-link"
HOSTNAME: "local-worker"
# Callback server
INTERNAL_JOBS_CALLBACK_PORT: "8080"
INTERNAL_JOBS_CALLBACK_URL: "http://knative-job-service:8080/callback"
JOBS_CALLBACK_HOST: "knative-job-service"
# Function gateway
INTERNAL_GATEWAY_URL: "http://send-email-link:8080"
INTERNAL_GATEWAY_DEVELOPMENT_MAP: '{"send-email-link":"http://send-email-link:8080"}'
ports:
- "8080:8080"
networks:
- constructive-net

networks:
constructive-net:
external: true
name: constructive-net
Loading