Foundry logo Foundry Docker guide

Default Docker workflow

The default docker-compose.yml is meant for local development. It keeps the source tree bind-mounted into the container so code, themes, and content edits are reflected immediately.

sh scripts/docker-init.sh
docker compose up -d --build

That setup:

  • bind-mounts the project root into /app
  • keeps data/ and public/ on named Docker volumes
  • uses content/config/site.docker.yaml as the config overlay
  • reads local Docker secrets from .env when present
  • can bootstrap a local .env with scripts/docker-init.sh

Local secret bootstrap

scripts/docker-init.sh creates a local .env file if one does not exist and fills in:

  • FOUNDRY_PUBLISH_ADDR
  • FOUNDRY_ADMIN_SESSION_SECRET
  • FOUNDRY_ADMIN_TOTP_SECRET_KEY

Those values are for local Docker convenience. They are not the production deployment path.

Production-oriented Docker workflow

The stricter setup lives in docker-compose.prod.yml. Use it when you want a safer immutable-style container shape instead of a source-mounted development container.

export FOUNDRY_ADMIN_SESSION_SECRET="$(openssl rand -hex 32)"
export FOUNDRY_ADMIN_TOTP_SECRET_KEY="$(openssl rand -base64 32)"
docker compose -f docker-compose.prod.yml up -d --build

That setup:

  • requires explicit session and TOTP secrets
  • runs with a read-only root filesystem
  • uses tmpfs for /tmp
  • drops Linux capabilities
  • enables no-new-privileges
  • uses named volumes for content/, themes/, plugins/, data/, and public/
  • uses content/config/site.docker.prod.yaml as the config overlay

Important config overlays

  • content/config/site.docker.yaml: development-oriented Docker defaults like local base URL and live reload enabled.
  • content/config/site.docker.prod.yaml: production-shaped Docker defaults like disabled live reload, disabled debug surfaces, and explicit production environment labeling.

Before using the production overlay, set content/config/site.docker.prod.yaml base_url to the real HTTPS origin for the deployment.

Operational notes

  • Set strong values for FOUNDRY_ADMIN_SESSION_SECRET and FOUNDRY_ADMIN_TOTP_SECRET_KEY in production.
  • Keep the production admin behind HTTPS so secure cookies behave correctly.
  • The default Docker setup is convenient for development, but the production compose file is the right base for a real deployment.
  • The Dockerfile creates runtime directories inside the image; generated output belongs on the writable public/ volume, not in the image layer.

Published GitHub Container Registry images

Release tags publish two OCI images to ghcr.io/sphireinc:

  • ghcr.io/sphireinc/foundry-runtime runs Foundry as a long-lived server.
  • ghcr.io/sphireinc/foundry-static-runtime builds a checked-out Foundry site mounted at /repo.

Use the static image with the invoking user's UID and GID so the generated public/ files remain writable on the host:

docker run --rm \
  --user "$(id -u):$(id -g)" \
  --mount "type=bind,src=$PWD,dst=/repo" \
  --workdir /repo \
  ghcr.io/sphireinc/foundry-static-runtime:latest \
  foundry build

The workflow checks the registry and refuses to overwrite an existing versioned release tag. The latest tag is updated for convenience. Both images publish linux/amd64 and linux/arm64 variants. They are built with OCI source, version, revision, and creation-date labels so GitHub can associate them with this repository.

If a release fails after publishing only one versioned image, delete any versioned tags created by that partial run in GHCR before retrying, or use a new release version. Versioned tags are never overwritten.

GitHub creates a newly published package as private. An organization or repository administrator must change both package visibility settings to Public before unauthenticated pulls will work.

Related docs

Container provenance and updates

Image tags and source release tags are distinct. Embedded commit, build date, platform, and modification state identify the binary; Foundry cannot infer the registry digest inside the container. Pull and recreate images through deployment tooling. See build identity and update guidance.