Pourquoi Docker Compose : Next.js + PostgreSQL ?
Docker Compose est une outil puissant qui permet d'orchestrer et de gérer des applications multi-conteneurs en un seul fichier de configuration YAML. C'est particulièrement utile pour les développeurs de logiciels qui travaillent avec des applications complexes nécessitant plusieurs services, comme Next.js et PostgreSQL.
Un cas d'utilisation concret serait le développement d'une application web qui nécessite une base de données relationnelle pour stocker des informations utilisateur et des transactions. Avec Docker Compose, vous pouvez facilement configurer, démarrer et gérer les conteneurs pour Next.js et PostgreSQL en un seul clic.
Prerequis
- Connaissance de base de JavaScript et React
- Familiarité avec le terminal et les commandes Unix/Linux
- Installation d'Node.js (v14.0.0 ou plus)
- Installation de Docker Desktop (https://www.docker.com/products/docker-desktop)
Concepts fondamentaux
1. Dockerfile
Le Dockerfile est un fichier texte qui contient des instructions pour construire une image Docker. C'est la base de tout conteneur Docker.
## Dockerfile pour Next.js
FROM node:14-alpine as builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN NEXT_PUBLIC_API_URL=http://localhost:5000 next build
FROM node:14-alpine
ENV NODE_ENV production
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json yarn.lock ./
CMD ["yarn", "start"]
2. docker-compose.yml
Le docker-compose.yml est un fichier de configuration YAML qui définit et configure les services, réseaux et volumes pour une application multi-conteneur.
version: '3.8'
services:
nextjs:
build: .
ports:
- "3000:3000"
depends_on:
- postgres
postgres:
image: postgres:13-alpine
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
3. Volumes
Les volumes dans Docker permettent de persister les données entre les conteneurs et d'éviter la perte des données lorsque le conteneur est supprimé.
volumes:
db_data:
Mise en pratique : projet fil rouge
Étape 1 : Créer un nouveau projet Next.js
Commencez par créer un nouveau projet Next.js avec l'assistant de création de projet :
npx create-next-app@latest nextjs-postgres
cd nextjs-postgres
Étape 2 : Configurer le fichier docker-compose.yml
Créez un fichier docker-compose.yml à la racine de votre projet avec le contenu suivant :
version: '3.8'
services:
nextjs:
build: .
ports:
- "3000:3000"
depends_on:
- postgres
postgres:
image: postgres:13-alpine
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Étape 3 : Créer le fichier Dockerfile
Créez un fichier Dockerfile à la racine de votre projet avec le contenu suivant :
## Dockerfile pour Next.js
FROM node:14-alpine as builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN NEXT_PUBLIC_API_URL=http://localhost:5000 next build
FROM node:14-alpine
ENV NODE_ENV production
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json yarn.lock ./
CMD ["yarn", "start"]
Étape 4 : Créer le modèle et le service pour PostgreSQL
Créez un dossier models et ajoutez un fichier user.js :
// models/user.js
const { Client } = require('pg');
const client = new Client({
user: 'myuser',
host: 'postgres',
database: 'mydatabase',
password: 'mypassword',
port: 5432,
});
async function connect() {
await client.connect();
}
async function getUsers() {
const result = await client.query('SELECT * FROM users');
return result.rows;
}
module.exports = { connect, getUsers };
Étape 5 : Créer un routeur pour obtenir les utilisateurs
Créez un fichier routes/api/users.js :
// routes/api/users.js
const { getUsers } = require('../../models/user');
export default async function handler(req, res) {
await connect();
const users = await getUsers();
res.status(200).json(users);
}
Étape 6 : Créer une page pour afficher les utilisateurs
Créez un fichier pages/index.js :
// pages/index.js
import { useEffect, useState } from 'react';
export default function Home() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('/api/users')
.then((response) => response.json())
.then((data) => setUsers(data));
}, []);
return (
<div>
<h1>Utilisateurs</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
Étape 7 : Configurer le .env.local
Ajoutez les variables d'environnement nécessaires au fichier .env.local :
DATABASE_URL=postgres://myuser:mypassword@postgres/mydatabase
NEXT_PUBLIC_API_URL=http://localhost:5000
Étape 8 : Initialiser la base de données
Connectez-vous à votre conteneur PostgreSQL et créez une table users :
docker-compose exec postgres psql -U myuser -d mydatabase
Puis, exécutez les commandes SQL suivantes :
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
Étape 9 : Ajouter des utilisateurs à la base de données
Insérez quelques utilisateurs dans la table users :
INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');
Étape 10 : Exécuter l'application
Démarrer les services avec Docker Compose :
docker-compose up --build
Accédez à http://localhost:3000 pour voir la liste des utilisateurs.
Erreurs frequentes et debugging
Erreur 1 : Le service Next.js ne démarre pas
Message d'erreur :
nextjs exited with code 1
Code incorrect :
docker-compose up --build
Code correct :
docker-compose down -v
docker-compose up --build
Erreur 2 : La base de données n'est pas accessible
Message d'erreur :
error: connect ECONNREFUSED 172.18.0.3:5432
Code incorrect :
const { Client } = require('pg');
const client = new Client({
user: 'myuser',
host: 'postgres',
database: 'mydatabase',
password: 'mypassword',
port: 5432,
});
Code correct :
Assurez-vous que le service postgres est démarré et accessible.
Erreur 3 : La table users n'existe pas
Message d'erreur :
error: relation "users" does not exist
Code incorrect :
Insérez des utilisateurs manuellement dans la base de données.
Code correct :
Connectez-vous à votre conteneur PostgreSQL et créez une table users :
docker-compose exec postgres psql -U myuser -d mydatabase
Puis, exécutez les commandes SQL suivantes :
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
Pour aller plus loin
Ajouter un service Redis pour le cache : https://docs.docker.com/compose/extends/
Utiliser Docker Secrets pour gérer les mots de passe sensibles : https://docs.docker.com/engine/swarm/secrets/
Déployer l'application sur Kubernetes avec Helm : https://helm.sh/docs/intro/install/
Défi pratique : Ajoutez une fonctionnalité pour ajouter de nouveaux utilisateurs via une API POST.