Why This Matters
Monorepos are powerful: they centralize your services, enforce code sharing, and simplify versioning. But they also bring challenges:
✅ You don’t want to build/test everything on every commit
✅ You need fast, reproducible builds
✅ You want to containerize changed services only
✅ You must deploy only what’s affected
In 2025, a typical stack might be:
Nx for workspace orchestration
Docker for packaging each service
GitHub Actions for CI/CD pipelines
Let’s build a fully working pipeline, with production-quality code and best practices, from scratch.
Project Setup
Let’s assume you have an Nx workspace like this:
Suppose you have two Node-based microservices (service-a
and service-b
) and a shared library. Each service uses Nx build targets.
Install Nx:
Generate your services (if you want to try this fresh):
Docker Setup for Each Service
In apps/service-a/Dockerfile
:
Repeat the same logic for service-b
by changing the build target.
Why two stages?
This pattern ensures you ship only the built code into your runtime image.
Nx Affected Logic
Nx’s killer feature is the affected
command. It uses a project graph and Git info to detect which services or libs changed.
✅ Build only what changed
✅ Test only what changed
Example:
Building a GitHub Actions Pipeline
Now we’ll create .github/workflows/ci.yml
:
Deployment (Optional but Realistic)
Let’s assume you’re pushing to a Kubernetes cluster. Add another job:
✅ Now you have:
Affected-aware builds
Multi-arch Docker images
Production Kubernetes deployment
Proper Nx caching
Community Questions & Answers
Q: Can I use Turborepo instead of Nx?
Yes, but you’ll lose Nx’s dependency graph. Turborepo is simpler, Nx is better for complex relationships.
Q: Why multi-arch images?
Cloud platforms (GCP, AWS, Azure) increasingly default to arm64
for lower power and cost, so you want linux/amd64,linux/arm64
builds for futureproofing.
Q: How do I preview PRs?
Add a namespace or ephemeral environment logic in the deploy
job with Helm or Kustomize. Example:
Q: Where should secrets live?
Use secrets.GITHUB_TOKEN
for GHCR, and store K8s credentials as a base64-encoded secret in GitHub. Never commit them!
Q: How to do static analysis?
Add a stage before test_and_build
:
Final Best Practices Checklist
✅ Use Nx affected builds to avoid waste
✅ Keep Dockerfiles in sync with dist
output
✅ Publish multi-arch images
✅ Always pin Docker base images
✅ Do static scanning (Trivy, Snyk)
✅ Automate ephemeral environments for PRs
✅ Version-lock your GitHub Actions
✅ Add vulnerability scanning on images
Next-Level Enhancements
Add SBOM generation (
syft
ortrivy
) for your imagesAdd Helm chart versioning tied to Nx affected tags
Integrate GitHub Advanced Security for code scanning
Monitor container runtimes with Falco or eBPF-based policies
Add Slack or Teams notifications on failed jobs
Conclusion
Nx + GitHub Actions + Docker is a battle-tested pattern for monorepos, combining build intelligence, fast caching, and flexible deployments.
By following this 360° pipeline:
✅ You build only what matters
✅ You test only what changed
✅ You deploy only what is needed
…without burning your budget or developer time.
NEVER MISS A THING!
Subscribe and get freshly baked articles. Join the community!
Join the newsletter to receive the latest updates in your inbox.