Chapitre 835 min2 exercices
Next.js sous Docker
Deux usages, deux configurations. En développement, le conteneur lit ton code en direct. En production, on livre une image compacte et figée.
Créer un projet sans Node installé
cd projet
docker run --rm -it --user "$(id -u):$(id -g)" -e HOME=/tmp \
-v "$PWD":/app -w /app node:24-slim npx create-next-app@latest frontRéponds aux questions (les valeurs par défaut conviennent). HOME=/tmp donne à npm un dossier où écrire son cache, puisque ton utilisateur n'existe pas dans l'image.
Le mode développement
Le code est partagé par un bind mount, next dev tourne dans le conteneur. Tu modifies un fichier, la page se recharge.
FROM node:24-slim
WORKDIR /app
# Prépare les dossiers pour l'utilisateur node (uid 1000)
RUN mkdir -p node_modules .next && chown -R node:node /app
USER node
EXPOSE 3000
CMD ["sh", "-c", "npm install && npm run dev"]services:
front:
build:
context: ./front
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./front:/app
- front-modules:/app/node_modules
- front-next:/app/.next
volumes:
front-modules:
front-next:docker compose up -d --build
docker compose logs -f front # attends « Ready »
docker compose exec front npm install zod # ajouter une dépendanceL'image de production
En production, on ne monte pas le code : il est copié et compilé dans l'image. Le mode standalone de Next.js produit un serveur autonome qui n'embarque que les fichiers réellement utilisés.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
};
export default nextConfig;COPY --from.# Étape 1 : installer les dépendances
FROM node:24-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# Étape 2 : construire l'application
FROM node:24-slim AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build
# Étape 3 : l'image finale, avec le strict nécessaire
FROM node:24-slim AS run
WORKDIR /app
ENV NODE_ENV=production PORT=3000 HOSTNAME=0.0.0.0
COPY --from=build --chown=node:node /app/public ./public
COPY --from=build --chown=node:node /app/.next/standalone ./
COPY --from=build --chown=node:node /app/.next/static ./.next/static
USER node
EXPOSE 3000
CMD ["node", "server.js"]node_modules
.next
.git
.env*
Dockerfile*cd front
docker build -t front:prod --build-arg NEXT_PUBLIC_API_URL=https://api.exemple.com .
docker run --rm -p 3000:3000 front:prodLe piège NEXT_PUBLIC_
Les variables qui commencent par NEXT_PUBLIC_ sont écrites en dur dans le JavaScript envoyé au navigateur, au moment du npm run build. Les passer au docker run ne change rien : il est trop tard.
| Variable | Lue quand | Comment la passer à Docker |
|---|---|---|
NEXT_PUBLIC_API_URL | Au build, figée dans le code client | --build-arg et ARG dans le Dockerfile |
API_URL_INTERNAL | À l'exécution, côté serveur uniquement | -e ou environment: dans Compose |
Next.js en développement dans Docker
- Crée un projet Next.js dans
projet/frontsans installer Node. - Ajoute
Dockerfile.devet uncompose.yamlavec le servicefront. - Démarre, ouvre
localhost:3000et remplace le contenu deapp/page.tsxpar un titre à toi.
Ce que tu dois obtenir
localhost:3000 affiche ta page. Quand tu enregistres app/page.tsx, le navigateur se met à jour en une ou deux secondes, sans relancer le conteneur.
Un indice
La page ne se met pas à jour ? Vérifie que ton projet n'est pas dans /mnt/c sous Windows. En dernier recours, ajoute WATCHPACK_POLLING: "true" dans l'environment du service.
Voir la solution
cd projet
# Crée front/ avec create-next-app, puis front/Dockerfile.dev et compose.yaml
docker compose up -d --build
docker compose logs -f front
# Modifie front/app/page.tsx et regarde le navigateurUne image de production légère
- Active
output: "standalone", ajoute leDockerfilede production et le.dockerignore. - Affiche
process.env.NEXT_PUBLIC_API_URLdans la page d'accueil. - Construis l'image avec une URL en
--build-arg, lance-la et vérifie sa taille.
Ce que tu dois obtenir
docker images front affiche une image de l'ordre de 200 à 300 Mo, et localhost:3000 sert le site compilé. La page affiche l'URL passée en --build-arg.
Un indice
Erreur Cannot find module server.js ? Il manque output: "standalone" dans next.config.ts.
Voir la solution
export default function Home() {
return <h1>API : {process.env.NEXT_PUBLIC_API_URL}</h1>;
}cd front
docker build -t front:prod --build-arg NEXT_PUBLIC_API_URL=https://api.exemple.com .
docker images front
docker run --rm -p 3000:3000 front:prod