Better-TS-Stack
Modules

Docker Module

Node.js 24 containers with Docker Compose v2

The Docker option creates Dockerfile, docker-compose.yml, and .dockerignore. Docker Desktop or Docker Engine with Compose v2 must be running.

Build and run

npm run docker:build
npm run docker:up
npm run docker:logs
npm run docker:down

These scripts use docker build and docker compose. All framework images use Node.js 24 Alpine, a build stage, and a non-root runtime user. Express runs dist/index.js; Next.js runs its standalone server.js output; TanStack Start runs srvx against the Vite dist/server/server.js handler (with npm ci --omit=dev so the production-only srvx runtime dependency is available). For Prisma projects, the generated client is copied from the build stage into the production image. Build errors stop the image build.

The image build installs dependencies with npm, regardless of the package manager selected for local development. Commit a package-lock.json to use npm ci in Docker; otherwise the image uses npm install.

Prisma clients are generated during the build. Placeholder PostgreSQL and MongoDB URLs are used only during the build; it does not connect to a database or run migrations. Configure the real DATABASE_URL at runtime and apply migrations separately.

Environment and databases

Compose loads the generated .env file through env_file and sets NODE_ENV=production. Replace local connection URLs with addresses reachable from the container. localhost inside a container refers to that container, not your host database. Use a database service name on a shared Docker network, or the appropriate host address.

The generated Compose file defines only the application service. Add database services or connect an external database as needed. Authentication secrets are generated per project; configure production secrets and BETTER_AUTH_URL for the deployed address.

.env is excluded from the image build context. Public build-time variables needed by your own Next.js code must be passed explicitly during the build. Never embed production secrets into a Dockerfile.

On this page