Best Ways to Host Your React-Based Frontend (Vite, Next.js, Remix) and Backend from One Container

Modern applications often combine a React-based frontend (built with Vite, Next.js, Remix, etc.) and a backend API (Node.js, Python, Java, etc.). In production, the cleanest architecture is usually to deploy frontend and backend as separate services.
But sometimes you want the simplicity of hosting them together in one container — especially for:
-
Small-to-medium apps
-
Internal tools or MVPs
-
Cost-sensitive projects
-
Hosting providers with single-container limitations
In this article, we’ll explore the best ways to host React-based frontends with a backend in a single Docker container, with examples and pros/cons for each method.
Approach 1: Serve Frontend as Static Files via Backend
For Vite or Remix (static export) projects, the frontend can be built into static files and served directly by your backend.
Example: Vite + Express Backend
Dockerfile:
1# Stage 1: Build React app with Vite
2FROM node:18 AS frontend
3WORKDIR /app/frontend
4COPY frontend/ .
5RUN npm install && npm run build
6
7# Stage 2: Backend
8FROM node:18
9WORKDIR /app
10COPY backend/ .
11RUN npm install
12
13# Copy built frontend into backend public folder
14COPY --from=frontend /app/frontend/dist ./public
15CMD ["node", "server.js"]
16
Express server (server.js):
1import express from "express";
2const app = express();
3
4app.use(express.static("public")); // Serve React build
5
6app.get("/api/hello", (req, res) => {
7 res.json({ message: "Hello from backend!" });
8});
9
10app.listen(3000, () => console.log("App running on port 3000"));
✅ Pros
-
Very simple (single process).
-
Works well with Vite/CRA/Remix static builds.
-
Easy CI/CD integration.
❌ Cons
-
Backend takes responsibility for serving static assets → extra load.
-
Not ideal for frameworks needing SSR (Next.js/Remix server mode).
Approach 2: Use Nginx for Frontend + Backend Reverse Proxy
For Next.js (SSR) or Remix (server mode), the backend often needs to run as a Node.js server. A common pattern is to:
-
Use Nginx to serve frontend static files (or reverse proxy SSR routes).
-
Proxy
/api
requests to the backend.
Dockerfile:
1# Stage 1: Build Next.js app
2FROM node:18 AS frontend
3WORKDIR /app
4COPY frontend/ .
5RUN npm install && npm run build
6
7# Stage 2: Backend
8FROM node:18 AS backend
9WORKDIR /app/backend
10COPY backend/ .
11RUN npm install
12
13# Stage 3: Nginx + Backend
14FROM nginx:alpine
15COPY --from=frontend /app/.next /usr/share/nginx/html
16COPY nginx.conf /etc/nginx/conf.d/default.conf
17COPY --from=backend /app/backend /app/backend
18
19WORKDIR /app/backend
20CMD ["sh", "-c", "node server.js & nginx -g 'daemon off;'"]
nginx.conf:
1server {
2 listen 80;
3
4 location / {
5 root /usr/share/nginx/html;
6 index index.html;
7 }
8
9 location /api/ {
10 proxy_pass http://localhost:5000;
11 }
12
✅ Pros
-
Efficient static asset serving with Nginx.
-
Clear separation of frontend vs. backend routes.
-
Great for Next.js or Remix SSR setups.
❌ Cons
-
Two processes in one container (need Supervisor or
&
). -
More complex Dockerfile + nginx.conf setup.
Approach 3: Use Next.js or Remix as Both Frontend + Backend
Frameworks like Next.js and Remix already support API routes. This means you can combine frontend and backend logic in one app, then containerise it.
Dockerfile (Next.js fullstack app):
1FROM node:18
2WORKDIR /app
3COPY . .
4RUN npm install && npm run build
5
6EXPOSE 3000
7CMD ["npm", "start"]
This approach eliminates the need for two separate servers.
✅ Pros
-
One framework handles both frontend and backend.
-
Simplest to containerise.
-
Great for fullstack apps with modest backend needs.
❌ Cons
-
Limited flexibility (harder to migrate backend later).
-
Ties backend tightly to Next.js/Remix.
-
Not suitable for heavy backend workloads.
Approach 4: Multi-Service Setup with Docker Compose
Even if you want “one deployable unit,” it’s often cleaner to use Docker Compose with two services (frontend + backend).
docker-compose.yml:
1version: "3"
2services:
3 frontend:
4 build: ./frontend
5 ports:
6 - "3000:3000"
7 backend:
8 build: ./backend
9 ports:
10 - "5000:5000"
11
✅ Pros
-
Best of both worlds: separation + easy deployment.
-
Backend and frontend can scale independently.
-
Works well in local development and production.
❌ Cons
-
Not technically “one container.”
-
Some hosting providers don’t allow multi-container unless using Kubernetes/Docker Swarm.
Conclusion
There’s no single “best” way — it depends on your stack and goals:
-
Vite/Remix static → Serve via backend (simple).
-
Next.js/Remix SSR → Use Nginx reverse proxy inside the container.
-
Small fullstack apps → Use Next.js/Remix API routes (all-in-one).
-
Production-ready → Use Docker Compose for separation.
👉 For quick prototypes or internal tools: go with Approach 1 or 3.
👉 For scalable production: Approach 2 or 4 is safer.

Optimize with ZEN's Expertise
Upgrade your development process or let ZEN craft a subsystem that sets the standard.
Read more:
Best Ways to Host Your React-Based Frontend (Vite, Next.js, Remix) and Backend from One Container
Modern applications often combine a React-based frontend (built with Vite, Next.js, Remix, etc.) and a backend API (Node...
AI is the missing piece of the Productivity Puzzle
Today, I’d like to plea that Artificial Intelligence (AI) is the missing piece of the productivity puzzle, revolutionizi...
Say Goodbye to Frustration: ZEN Software's Plugin Makes Picture Labeling a Breeze!
WordPress empowers businesses, creative enthusiasts, and content creators with its user-friendly interface and extensive...
Programmer frustration: Yak Shaving
The term "yak shaving" in programming originated from an episode of the popular 1990s cartoon "Ren & Stimpy." The episod...
Amazon Prime Video swaps Microservices for Monolith: 90% Cost Reduction
Recently, Amazon Prime Video published a surprising article [revealing how they saved 90%](https://www.primevideotech.co...
Remote Development in the Cloud
Remote development has become increasingly popular in recent years. It allows developers to take advantage of powerful c...