Deploying Weaverse Themes with Docker
For production storefronts, use Shopify Oxygen — it is the officially supported target for Hydrogen. Docker is a good fit for development, testing, review apps, and infrastructure you must control yourself.
Quick Flow
1
Add a Dockerfile and .dockerignore
Multi-stage build;
.dockerignore must exclude .env*.2
Build the image with no secrets in it
docker build -t my-storefront .3
Supply configuration at run time
docker run --env-file .env -p 3000:3000 my-storefront4
Deploy
fly secrets set ... then fly deploy (or the equivalent for your platform).How it works
The container runsnpm run start, which is shopify hydrogen preview — a Node-based simulation of the Oxygen Workers runtime. Two consequences matter:
- Runtime differences. Worker-specific behavior, caching, and performance characteristics are simulated, not identical to Oxygen. Validate anything runtime-sensitive before relying on it.
- Network binding. The preview server binds to
localhostby default, which is unreachable from outside the container. It has to listen on0.0.0.0for the container to serve traffic.
Security rules
Concretely:- Add
.env*to.dockerignoreso env files never enter the build context. - Do not use
ENVor build args for tokens, API keys, orSESSION_SECRET. - Pass configuration at container start:
--env-file,-e, your orchestrator’s secret store, orfly secrets. - Rotate any credential that has already been committed to an image or to Git.
Prerequisites
- Docker (latest stable version)
- Node.js — the Pilot theme requires
>=22.12.0 - Fly.io CLI if you are following the Fly example
- A Weaverse theme project that builds locally (
npm run buildsucceeds)
Configuration Files
1. .dockerignore
Create this first, so the build context never contains secrets or junk:
.dockerignore
2. Dockerfile
Dockerfile
npm run start runs shopify hydrogen preview, which lives in @shopify/cli — a dev dependency. That is why the production stage copies the full node_modules from the build stage rather than running npm ci --omit=dev.3. Environment variables
Keep a local.env for development (it is already in the theme’s .gitignore), and use .env.example as the reference list of variables your theme reads:
.env
Cloud Deployment (Fly.io)
1. fly.toml
fly.toml
2. Set secrets
Fly secrets are encrypted at rest and injected into the machine’s environment at run time:3. Deploy
--set-secrets, Kubernetes Secret + envFrom, Render/Railway environment settings. All of them inject variables into the process environment, which is exactly what the container expects.
Troubleshooting
Container starts but nothing responds on the mapped port The host binding patch did not apply. Check the build log for theWARNING: no workerd host binding patched line and re-check the CLI file layout for your @shopify/cli version.
Build failures
Confirm the Node version in the base image satisfies the theme’s engines.node (>=22.12.0), that npm run build succeeds locally, and that Docker has enough memory allocated.
Missing configuration at run time
Check the values actually reached the container: docker exec <container> printenv | sort, or fly ssh console -C printenv. Variable names are case-sensitive.
Weaverse Studio preview does not load
Verify WEAVERSE_PROJECT_ID is set in the running environment and that the deployed URL is registered on your Weaverse project. See Preview Errors.
Limitations and Considerations
- Runtime simulation —
shopify hydrogen previewapproximates the Workers runtime in Node. Not every Worker API or performance characteristic matches Oxygen. - Image size — the production stage ships the full
node_modulesbecause the preview server is part of the Shopify CLI. - Operational ownership — scaling, TLS, log retention, and monitoring are yours to configure. Oxygen handles these for you.
Related
- Deploy to Oxygen — the recommended production path
- Deploy to Cloudflare Workers
- Custom Domain and DNS
- Shopify: Self-hosting Hydrogen