Introduction
Hey! If you’ve already followed my guide on deploying Next.js to AWS ECR using Kamal 2.4, you’re in the right place. If not, you might want to check that out first before diving in here.
Let’s set the stage.
Imagine your team manages multiple applications—each with its own staging and production environment. Sounds familiar?
Here’s a typical setup:
Company Setup:
-
App 1: Marketing Site
- Production Server
- Staging Server
-
App 2: Service 1
- Production Server
- Staging Server
-
App 3: Service 2
- Production Server
- Staging Server
As you can guess, all those servers start racking up costs fast. But there’s a smarter way to handle staging environments—and that’s what we’ll cover here.
Why Consolidate Staging Environments?
Running a separate staging server for each app is like giving every roommate their own apartment—it’s nice, but overkill. What if they could all just share a well-organized house?
By consolidating staging environments onto a single server, you cut down on infrastructure costs and simplify management. Plus, you make better use of your server’s resources, instead of leaving them sitting idle.
Of course, there are trade-offs. Apps will share CPU and memory, and if the server goes down, all your staging apps go with it. But for many teams, especially smaller ones, the benefits outweigh the risks.
Before You Start: A Quick Checklist
Before moving all your staging apps to one server, make sure:
- Your server has enough CPU, RAM, and disk space to comfortably support multiple apps.
- You don’t cram together resource-heavy services that could clash.
- You’re using a tool like Kamal (formerly MRSK) to handle deployments cleanly.
Deploying Multiple Next.js Apps to One Server (with Docker + Kamal)
We'll use Docker to containerize each app and Kamal to deploy them onto a single staging server.
Here’s how to do it step-by-step:
1. Dockerize Each App
Make sure every app has a valid Dockerfile
in its root directory. This is what Kamal will use to build your app into a container.
2. Configure Kamal for Each App
In each app’s repository, update the config/deploy.staging.yml
(or .env
equivalent) so all apps point to the same staging server—but with different ports.
Example Configs:
App 1: Marketing Site
service: app-1
image: example/web-app
servers:
web:
- 0.0.0.0 # Your staging server IP
proxy:
ssl: false
host: stagingmarketing.example.com
app_port: 3000
healthcheck:
path: /
interval: 3
timeout: 30
App 2: Service 1
service: app-2
image: example/web-app-2
servers:
web:
- 0.0.0.0
proxy:
ssl: false
host: staging-service-1.example.com
app_port: 3001
healthcheck:
path: /
interval: 3
timeout: 30
App 3: Service 2
service: app-3
image: example/web-app-3
servers:
web:
- 0.0.0.0
proxy:
ssl: false
host: staging-service-2.example.com
app_port: 3002
healthcheck:
path: /
interval: 3
timeout: 30
How It All Comes Together
Think of your server like a building, and each app as a different apartment inside. Everyone shares the same address (IP), but has their own door (port) and mailbox (domain).
By assigning different ports and subdomains, Kamal keeps everything isolated and easy to manage. You still get individual health checks, separate logs, and independent deployments—just without the headache of spinning up separate servers for each app.
Final Thoughts
Consolidating your staging environments is one of those small moves that pays off quickly—especially when you’re juggling multiple projects. Kamal makes the deployment process clean, and with Docker handling your app containers, it's both flexible and scalable.
Just be mindful of your server's capacity and isolate noisy apps when needed. Otherwise, you're set.
Have questions or want to see this in action with real infra? Hit me up or drop a comment.
Top comments (0)