GrowthBook consists of a NextJS front-end, an ExpressJS API, and a Python stats engine. Everything is bundled together in a single Docker Image.
In addition to the app itself, you will also need a MongoDB instance (or MongoDB compatible database) to store login credentials, cached experiment results, and metadata.
Don’t want to install or host the app yourself?GrowthBook Cloud is a fully managed version that’s free to get started with.
Quick Start
You can use docker compose to get started quickly:
Then, just run docker compose up -d to start everything and view the app at http://localhost:3000
Use of mongo imageThe use of the mongo image within the docker-compose.yml is meant to quickly get a dev or staging environment up and running.
For production you may want to use a more scalable and stable solution (ie. AWS DocumentDB, Google Cloud MongoDB Atlas, Azure Cosmos DB for Mongo, etc.)
We also offer an official Helm chart for deploying GrowthBook on Kubernetes. See the Kubernetes Self-Hosting Guide for more details.
Production
We have a dedicated guide for Self-Hosting GrowthBook in Production that covers best practices for security, scaling, performance, and more.
The latest tag is updated with every commit to the main branch. We run this tag in GrowthBook Cloud, so it’s generally safe for production, but may occasionally have minor bugs.
We periodically create stable release tags (e.g. 4.1.0) if you prefer to have more control over updates. Check out the Releases page on GitHub for a list of releases with detailed release notes.
Lastly, if you need to reference the image for a specific git commit for any reason, you can use the git shorthash tag (e.g. git-41278e9).
Hardened (non-root, shell-less) image
The GrowthBook runtime image is a distroless Docker Hardened Image (DHI): it runs as a non-root user (uid 1000) and contains no shell or package manager. This removes a recurring class of OS-package CVEs.
The published growthbook/growthbook image is an ordinary public image — docker pull needs no special credentials. The notes below cover the operational differences when you run it, plus the one extra step needed if you build the image from source yourself.
Local file uploads must be writable by uid 1000
If you use UPLOAD_METHOD=local, a volume created by an older (root) GrowthBook image contains root-owned files that the non-root process can’t write to. Newly created volumes work automatically; an existing volume needs a one-time ownership fix:
Alternatively, keep running as root by setting user: "0:0" on the service, or switch to s3/google-cloud storage (no local volume needed). On Kubernetes, the Helm chart sets fsGroup: 1000, which handles this for you.
Debugging without a shell
docker exec <container> sh no longer works. To inspect a running container, attach a throwaway debug container that shares its process namespace:
--cap-add=SYS_PTRACE is required to read the target process’s filesystem. Any image with a shell works (busybox, debian); the matching dhi.io/node:<version>-debian12-dev image gives you the same libraries for running the app’s own binaries, though pulling that one needs the login described below. On Kubernetes, use kubectl debug -it <pod> --image=busybox --target=<container>. One-off admin scripts (e.g. encryption-key migration) are run via node directly — see Environment Variables.
Building from source requires docker login dhi.io
Most deployments should use the published growthbook/growthbook image. It’s the same image we run on GrowthBook Cloud, and it needs no DHI account. If you build the Dockerfile yourself (a fork, an internal CI pipeline, or an air-gapped rebuild), log in to dhi.io to avoid this error:
Any free Docker account fixes this. The DHI Community catalog is free under Apache 2.0, with no paid subscription or separate entitlement to provision:
In CI, add a login step before the build. With GitHub Actions:
Registry mirrors and egress allowlists. dhi.io is a distinct registry from docker.io. A pull-through mirror (Artifactory, Harbor, Nexus) configured for Docker Hub does not cover it, and neither does a firewall rule that only permits docker.io / registry-1.docker.io. Add dhi.io as its own upstream remote or allowlisted host.
If you only build from source to layer something on top (a CA certificate or an internal config file), extend the published image instead. This needs no DHI access at all:
Point NODE_EXTRA_CA_CERTS at the certificate rather than dropping it in /usr/local/share/ca-certificates/: the usual update-ca-certificates step needs a shell, which this image doesn’t have, and Node wouldn’t read the system bundle anyway. Node picks the variable up at startup, so it covers the back-end and front-end processes where GrowthBook makes its outbound connections.
If dhi.io is a hard blocker in your environment, open an issue or find us in Slack. We’d like to hear about it.