Skip to main content

Monorepo builds

Deploy separate services from one repository with explicit root directories, Docker contexts, and automatic-deployment filters.

Share
Last updated on September 23, 2026
On this page

Deploy each independently operated application in a repository as a separate Bex service. Give it its own build/start commands, configuration, and deployment policy. A shared repository does not make services share environment variables or scale together.

Runnable shared-package sample

bash
curl -fsSLO https://bex.co/examples/shared-package-monorepo-latest.zip
curl -fsSLO https://bex.co/examples/shared-package-monorepo-latest.zip.sha256
shasum -a 256 -c shared-package-monorepo-latest.zip.sha256
unzip shared-package-monorepo-latest.zip
cd shared-package-monorepo
npm install
npm run start:api
npm run start:worker-api
npm test
npm run rehearse

See also shared-package-monorepo README for Docker/Blueprint details. The archive includes a complete two-service Node workspace with a shared package, root lockfile, Dockerfiles built from the repository root, and a Blueprint whose filters include packages/shared/** and package-lock.json while ignoring docs/**.

Each service returns its own service identity plus sharedMessage / sharedVersion from the workspace package. npm run rehearse prints an explanatory push-deploy matrix checked against upstream filter composition (Bex d0f17feb3ece1ce20c8c85384e8ee68ff4b2e1d3); it is not live hosted evidence. Push the same scenarios from a repository you own after connecting Git and applying the Blueprint — inspect per-service deploy history and / responses.

Choose the service root

rootDir selects the directory used for a service's build. Omit it to use the repository root. A self-contained Node.js app under apps/api can use:

yaml
services:
  - type: web
    name: api
    runtime: node
    repo: https://github.com/acme/monorepo
    rootDir: apps/api
    buildCommand: npm ci
    startCommand: npm start
    autoDeployTrigger: commit
    buildFilter:
      paths:
        - apps/api/**
      ignoredPaths:
        - apps/api/docs/**

This assumes apps/api contains its own package manifest and lockfile, and its start command listens on 0.0.0.0:$PORT. Replace the example repository and commands. Validate using the Blueprint guide before applying.

Native commands execute in the built application's working directory. Adjust build/start commands and static publish paths when changing the root. A package that relies on a root-level workspace lockfile or sibling package may need to build from the repository root instead, using package-manager workspace commands. Do not solve missing files with ../ traversal in a configured root path.

Dockerfile and build context

Bex resolves the Dockerfile relative to rootDir. By default, the Docker build context is also that directory. An explicit dockerContext selects a context relative to the repository root, independently of rootDir.

For shared source, keeping the service root at the repository root makes the relationship clear:

yaml
services:
  - type: web
    name: api
    runtime: docker
    repo: https://github.com/acme/monorepo
    dockerfilePath: apps/api/Dockerfile
    dockerContext: .
    autoDeployTrigger: commit
    buildFilter:
      paths:
        - apps/api/**
        - packages/shared/**
        - package-lock.json

Write Dockerfile COPY paths relative to that build context, and check .dockerignore. A path to the Dockerfile does not make its containing directory the context. See Docker deployments for registry and image requirements.

Decide which pushes deploy

Bex checks the tracked repository/branch, auto-deploy setting, changed files under rootDir, and buildFilter. Build-filter globs are repository-relative:

  • With included paths, a changed file must match one of them.
  • An ignoredPaths match excludes that file even if an include also matches.
  • With no included paths, changes are eligible unless ignored.

Root-directory and build-filter checks both apply. Adding a sibling package to a filter does not bypass a narrow rootDir gate. If shared-code changes must redeploy a service, use a root and filter combination that admits them, such as the repository-root Docker example above. Include relevant lockfiles and shared configuration as well as application source.

If a webhook carries no changed-path information, Bex currently allows the path-filter checks to pass; filters are not a strict guarantee against deployment.

Filters control push-triggered deployments, not access to files or authorization. An explicit manual deploy is a separate operation. Do not use filters to enforce a release approval policy; Bex does not implement checksPass CI gating.

Verify and troubleshoot

Test an application change, an ignored documentation change, and a shared-library change in a non-production branch/workspace. Check which service deploys and which commit it builds.

For a missing file, inspect the root, context, Dockerfile path, lockfile placement, and ignore rules. For a missing deployment, inspect branch and auto-deploy settings, webhook delivery, root matching, and filters. For an unexpected service restart, also check Blueprint sync and configuration changes. Build logs distinguish a source-path failure from an application startup failure.

Was this page helpful?

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex