deploy-docker
This page shows how to get Docker files for the shell and each remote. It is optional. mfeflow never builds or runs an image; the files are yours to change or delete.
What you get
One image recipe for every app, built once and run in every environment.
docker/Dockerfile: a build stage on Node 24 and an nginx runtime stage.--build-arg APP=<name>picks the app. Both base images are pinned by digest.docker/nginx.shell.confanddocker/nginx.remote.conf: the cache rules, the fallback toindex.html(shell only) and CORS (remotes only).docker/40-mfe-config.sh: runs before nginx starts and copiesruntime-config.$MFE_ENV.jsoninto place.compose.yaml: the shell and every remote locally, on the ports frommfeflow.json.k8s/mfe.yaml: a ConfigMap, Deployment and Service for the shell..dockerignoreanddocs/docker.md.
When to use it
Use it when you run on Kubernetes, a VM or your own network. If you deploy to a CDN or a static host, you do not need it. The Deploy overview compares the options.
Add it
What changed:
The feature has no options and adds no dependencies. It reads the apps in mfeflow.json once, to write compose.yaml. A remote you add later needs its own block there.
Use it
Build the shell and a remote from the repository root. The build needs a pnpm-lock.yaml:
Run the same shell image as staging, then as production:
MFE_ENV=qa stops the container with no runtime config for MFE_ENV=qa and a list of the files it does have.
A remote needs the origins of the shells that may load it, as SHELL_ORIGINS. For everything at once on your machine:
Configure it
There are no install options. These are read when the container starts:
How it works
nginx runs every script in /docker-entrypoint.d before it starts. The start script writes only under /tmp, so the root filesystem can be read-only. The shell serves /config/runtime-config.json from that copy, or from a ConfigMap mounted at /tmp/mfe-runtime.
A remote image holds its files once and answers on two paths: /mfe/<name>/<version>/ cached for a year, and the same files at / that are revalidated. Any other /mfe/ path is a 404.
Gotchas
- Bump a remote's version for every release. The versioned path is cached for a year.
- Compression is gzip. The nginx image has no brotli module.
- Node 25 and later no longer ship corepack. The Dockerfile builds on Node 24.
- Do not mount a single file from a ConfigMap with
subPath. It never receives updates. Mount the directory. HEALTHCHECKuses busyboxwget, which the alpine image has. Kubernetes ignores it and uses the probes ink8s/mfe.yaml.
Reference
See Deploy with Docker for the same setup written by hand, and One build, three platforms.