De beste manieren om je React-frontend (Vite, Next.js, Remix) en backend vanuit één container te hosten



Smiling person in layered hair w/eyelashes,gesturing

Zoia Baletska

18 september 2025

a4dxkv.webp

Moderne applicaties combineren vaak een React-frontend (gebouwd met Vite, Next.js, Remix) en een backend-API (Node.js, Python, Java). In productie is het meestal het schoonst om frontend en backend als aparte diensten uit te rollen.

Maar soms wil je gewoon het gemak van allebei in één container — zeker bij:

  • kleine tot middelgrote apps

  • interne tools of MVP's

  • projecten waar de kosten scherp liggen

  • hostingpartijen die maar één container toestaan

In dit artikel lopen we de beste manieren langs om een React-frontend samen met een backend in één Docker-container te hosten, met voorbeelden en de voor- en nadelen per aanpak.

Aanpak 1: serveer je frontend als statische bestanden vanuit je backend

Bij Vite- of Remix-projecten (statische export) bouw je je frontend tot statische bestanden die je backend rechtstreeks uitserveert.

Voorbeeld: 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"));

✅ Voordelen

  • Erg eenvoudig (één proces).

  • Werkt prima met statische builds van Vite, CRA of Remix.

  • Makkelijk in te passen in je CI/CD.

❌ Nadelen

  • Je backend wordt verantwoordelijk voor het uitserveren van statische bestanden → extra belasting.

  • Niet geschikt voor frameworks die SSR nodig hebben (Next.js of Remix in servermodus).

Aanpak 2: Nginx voor je frontend plus een reverse proxy naar je backend

Bij Next.js (SSR) of Remix (servermodus) moet je backend meestal als Node.js-server draaien. Een gangbaar patroon is dan:

  • Nginx je statische frontendbestanden laten serveren (of SSR-routes doorsturen).

  • /api-verzoeken doorsturen naar je 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

✅ Voordelen

  • Nginx serveert statische bestanden efficiënt uit.

  • Heldere scheiding tussen frontend- en backendroutes.

  • Uitstekend voor SSR-opstellingen met Next.js of Remix.

❌ Nadelen

  • Twee processen in één container (je hebt Supervisor of & nodig).

  • Ingewikkelder Dockerfile en nginx.conf.

Aanpak 3: gebruik Next.js of Remix als frontend én backend

Frameworks als Next.js en Remix ondersteunen zelf al API-routes. Je kunt je frontend- en backendlogica dus in één app combineren en die vervolgens in een container stoppen.

Dockerfile (full-stack Next.js-app):

1FROM node:18
2WORKDIR /app
3COPY . .
4RUN npm install && npm run build
5       
6EXPOSE 3000
7CMD ["npm", "start"]

Zo heb je geen twee aparte servers meer nodig.

✅ Voordelen

  • Eén framework regelt zowel je frontend als je backend.

  • Het eenvoudigst om te containeriseren.

  • Uitstekend voor full-stack apps met bescheiden backendbehoeften.

❌ Nadelen

  • Beperkte flexibiliteit (je backend later verhuizen wordt lastiger).

  • Je backend zit strak vast aan Next.js of Remix.

  • Ongeschikt voor zware backendworkloads.

Aanpak 4: meerdere diensten met Docker Compose

Ook als je “één uitrolbare eenheid” wilt, is het vaak schoner om Docker Compose met twee diensten te gebruiken (frontend en 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

✅ Voordelen

  • Het beste van twee werelden: scheiding én makkelijk uitrollen.

  • Je backend en frontend schalen onafhankelijk van elkaar.

  • Werkt goed in zowel je lokale omgeving als in productie.

❌ Nadelen

  • Strikt genomen niet “één container”.

  • Sommige hostingpartijen staan meerdere containers alleen toe via Kubernetes of Docker Swarm.

Tot slot

Er is geen enkele “beste” manier — het hangt af van je stack en je doelen:

  • Statische Vite of Remix → serveer vanuit je backend (simpel).

  • Next.js of Remix met SSR → gebruik een Nginx reverse proxy in je container.

  • Kleine full-stack apps → gebruik de API-routes van Next.js of Remix (alles-in-één).

  • Klaar voor productie → gebruik Docker Compose voor de scheiding.

👉 Voor snelle prototypes of interne tools: ga voor aanpak 1 of 3.
👉 Voor schaalbare productie: aanpak 2 of 4 is veiliger.

no image placeholder

Softwareontwikkeling ontmoeilijken