Compétence de déploiement Docker local pour Next.js
Objectif
Utilisez cette compétence pour construire et exécuter une application Next.js avec Docker en utilisant une étiquette d'image versionnée.
Cette compétence ne doit pas coder en dur le nom du projet. Déduisez le nom de l'image du dépôt actuel sauf si l'utilisateur fournit un nom spécifique.
Résolution du nom du projet
Avant de construire, déterminez ces valeurs :
PROJECT_NAME=<nom du projet résolu>
IMAGE_NAME=<nom de l'image résolu>
IMAGE_VERSION=<version résolue>
IMAGE_TAG=${IMAGE_NAME}:${IMAGE_VERSION}
CONTAINER_NAME=<nom du conteneur résolu>
ENV_FILE=<fichier d'environnement résolu>
HOST_PORT=<port hôte résolu>
CONTAINER_PORT=<port conteneur résolu>
Règles de résolution :
-
Si l'utilisateur fournit un nom d'image, utilisez-le.
-
Sinon, lisez
package.jsonet utilisez le champname. -
Si
package.jsonn'a pas dename, utilisez le nom du dossier courant. -
Normalisez le nom de l'image :
- minuscule
- remplacez les espaces et underscores par des tirets
- supprimez les caractères invalides pour les noms d'images Docker
-
Si l'utilisateur fournit une version, utilisez-la.
-
Sinon, prenez par défaut
1.0.0. -
Si l'utilisateur fournit un nom de conteneur, utilisez-le.
-
Sinon, utilisez le nom d'image normalisé comme nom de conteneur.
-
Si l'utilisateur fournit un fichier d'environnement, utilisez-le.
-
Sinon, prenez par défaut
.env.production. -
Si l'utilisateur fournit des ports, utilisez-les.
-
Sinon, prenez par défaut
HOST_PORT=4000etCONTAINER_PORT=3000.
Exemple :
package.json name: nextjs-skill-app-workshop
PROJECT_NAME=nextjs-skill-app-workshop
IMAGE_NAME=nextjs-skill-app-workshop
IMAGE_VERSION=1.0.0
IMAGE_TAG=nextjs-skill-app-workshop:1.0.0
CONTAINER_NAME=nextjs-skill-app-workshop
ENV_FILE=.env.production
HOST_PORT=4000
CONTAINER_PORT=3000
Règles de sécurité
Avant d'exécuter une commande de construction ou d'exécution :
-
Vérifiez que le répertoire de travail actuel est la racine du projet.
-
Vérifiez que
Dockerfileexiste. -
Vérifiez que le fichier d'environnement existe.
-
Vérifiez que Docker est installé et en cours d'exécution.
-
Vérifiez si l'étiquette d'image demandée existe déjà localement.
-
Vérifiez si le nom de conteneur demandé existe déjà.
-
Ne jamais afficher les secrets du fichier d'environnement.
-
N'utilisez pas l'étiquette
latestsauf demande explicite de l'utilisateur. -
N'exécutez pas de commandes de nettoyage destructrices telles que :
docker system prunedocker image prunedocker volume prune
-
Ne pas arrêter, supprimer ou remplacer un conteneur existant sans confirmation explicite de l'utilisateur.
-
Ne pas reconstruire une étiquette de version existante sauf confirmation claire de l'utilisateur.
Vérifications préalables
Exécutez ces vérifications en premier :
pwd
ls -la
test -f package.json && echo "OK: package.json trouvé" || echo "ATTENTION: package.json non trouvé"
test -f Dockerfile && echo "OK: Dockerfile trouvé" || echo "ERREUR: Dockerfile non trouvé"
test -f "$ENV_FILE" && echo "OK: fichier d'environnement trouvé : $ENV_FILE" || echo "ERREUR: fichier d'environnement non trouvé : $ENV_FILE"
docker --version
docker info >/dev/null && echo "OK: le démon Docker est en cours d'exécution" || echo "ERREUR: le démon Docker n'est pas en cours d'exécution"
Si Dockerfile est manquant, arrêtez-vous et signalez le problème.
Si le fichier d'environnement est manquant, arrêtez-vous et signalez le problème. Ne créez pas de fichier d'environnement factice sauf demande de l'utilisateur.
Si le démon Docker n'est pas en cours d'exécution, arrêtez-vous et dites à l'utilisateur de démarrer Docker Desktop ou Docker Engine.
Commandes d'aide suggérées
Pour déduire le nom de l'image à partir de package.json :
node -p "require('./package.json').name"
Si package.json n'existe pas ou n'a pas de name, utilisez le nom du répertoire courant :
basename "$PWD"
Pour normaliser manuellement un nom de projet, utilisez le kebab-case en minuscules.
Exemple :
My Next App -> my-next-app
nextjs_skill_app -> nextjs-skill-app
Vérification de l'étiquette de version
Avant de construire, vérifiez si l'étiquette d'image demandée existe déjà :
docker image inspect "$IMAGE_TAG" >/dev/null 2>&1 \
&& echo "EXISTE : $IMAGE_TAG" \
|| echo "DISPONIBLE : $IMAGE_TAG"
Listez également les versions locales existantes pour cette image :
docker images "$IMAGE_NAME" --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}"
Si l'étiquette d'image demandée existe déjà :
- N'exécutez pas
docker build. - Signalez que la version existe déjà localement.
- Suggérez la prochaine version de correctif, par exemple
1.0.1. - Demandez à l'utilisateur s'il souhaite utiliser une nouvelle version ou reconstruire explicitement la même étiquette.
Ne reconstruisez une étiquette existante que si l'utilisateur confirme clairement.
Vérification du nom du conteneur
Avant d'exécuter le conteneur, vérifiez si le nom du conteneur existe déjà :
docker ps -a --filter "name=^/${CONTAINER_NAME}$" \
--format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
Si un conteneur avec le même nom existe déjà :
- N'exécutez pas un autre conteneur avec le même nom.
- Signalez l'état du conteneur existant.
- Demandez à l'utilisateur s'il souhaite arrêter/supprimer le conteneur ou utiliser un nom de conteneur différent.
- Ne le supprimez pas automatiquement.
Commande de construction
Si l'étiquette d'image n'existe pas, exécutez :
docker build -t "$IMAGE_TAG" .
Après la construction, vérifiez que l'image existe :
docker image inspect "$IMAGE_TAG" >/dev/null \
&& echo "OK: image construite avec succès : $IMAGE_TAG" \
|| echo "ERREUR: image non trouvée après construction : $IMAGE_TAG"
Commande d'exécution
Si l'image existe et que le nom du conteneur est disponible, exécutez :
docker run --restart=always -d \
--name "$CONTAINER_NAME" \
--env-file "$ENV_FILE" \
-p "${HOST_PORT}:${CONTAINER_PORT}" \
"$IMAGE_TAG"
Validation après exécution
Après avoir exécuté le conteneur, validez avec :
docker ps --filter "name=^/${CONTAINER_NAME}$" \
--format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail=80 "$CONTAINER_NAME"
curl -I "http://localhost:${HOST_PORT}"
Résultat attendu :
- Le statut du conteneur doit être
Up. - Le mappage de port doit inclure
${HOST_PORT}->${CONTAINER_PORT}. - Les logs ne doivent pas montrer d'erreurs fatales.
curl -Idoit retourner une réponse HTTP telle que200,301,302,307ou308.
Si curl échoue, inspectez les logs et signalez la cause probable.
Gestion des échecs courants
L'étiquette d'image existe déjà
Signalez :
L'étiquette d'image existe déjà localement :
<IMAGE_TAG>
Action recommandée :
- Utiliser une nouvelle version de correctif, par exemple 1.0.1
- Ou confirmer explicitement la reconstruction de la même étiquette
Le nom du conteneur existe déjà
Signalez :
Le conteneur existe déjà :
<CONTAINER_NAME>
Veuillez confirmer si vous souhaitez l'arrêter/le supprimer, ou fournir un nom de conteneur différent.
Le port est déjà utilisé
Vérifiez :
lsof -i :"$HOST_PORT"
Signalez le processus utilisant le port et demandez si l'utilisateur souhaite changer HOST_PORT.
Fichier d'environnement manquant
Signalez :
Le fichier d'environnement est introuvable :
<ENV_FILE>
Je ne peux pas exécuter le conteneur avec --env-file tant que ce fichier n'existe pas.
N'affichez pas et ne déduisez pas de secrets.
Démon Docker non en cours d'exécution
Signalez :
Docker est installé mais le démon n'est pas en cours d'exécution.
Démarrez Docker Desktop ou Docker Engine, puis relancez les vérifications préalables.
Format de réponse final
Lorsque vous avez terminé, signalez :
Résultat :
- Projet : <PROJECT_NAME>
- Image : <IMAGE_TAG>
- Conteneur : <CONTAINER_NAME>
- Fichier d'environnement : <ENV_FILE>
- Port : http://localhost:<HOST_PORT>
- Politique de redémarrage : always
- Validation : réussie/échouée
Commandes utilisées :
<liste des commandes importantes>
Notes :
<avertissements éventuels, conflits d'image/conteneur existants, action de suivi>
Si le flux de travail s'arrête à cause d'une étiquette de version existante, d'un fichier d'environnement manquant, d'un conteneur existant, d'une erreur Docker ou d'un conflit de port, indiquez clairement le problème bloquant et la commande suivante la plus sûre.