Dans ce module, nous allons utiliser la commande Docker Compose pour exécuter notre image Docker.
Voici notre image Docker :
1FROM --platform=amd64 node:18-alpine As base23FROM base AS builder45# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.6RUN apk add --no-cache libc6-compat7RUN apk update8# Set working directory9WORKDIR /app10RUN npm install --global turbo11COPY --chown=node:node . .12RUN turbo prune @virgile/backend --docker1314# Add lockfile and package.json's of isolated subworkspace15FROM base AS installer16RUN apk add --no-cache libc6-compat17RUN apk update18WORKDIR /app1920# First install the dependencies (as they change less often)21COPY .gitignore .gitignore22COPY --chown=node:node --from=builder /app/out/json/ .23COPY --chown=node:node --from=builder /app/out/package-lock.json ./package-lock.json24RUN npm install2526# Build the project27COPY --from=builder /app/out/full/ .28COPY turbo.json turbo.json2930# Uncomment and use build args to enable remote caching31ARG TURBO_TEAM32ENV TURBO_TEAM=$TURBO_TEAM3334ARG TURBO_TOKEN35ENV TURBO_TOKEN=$TURBO_TOKEN36ENV TZ=Europe/Paris37ENV NODE_ENV="production"3839ADD backend/prisma backend/prisma40RUN cd backend && npx prisma generate4142RUN npm run build4344FROM base AS runner45WORKDIR /app4647# Don't run production as root48RUN addgroup --system --gid 1001 nodejs49RUN adduser --system --uid 1001 remix-api50USER remix-api5152# ENV TZ=Europe/Paris53# ENV NODE_ENV="production"5455COPY --chown=remix-api:nodejs --from=installer /app/backend/package.json ./backend/package.json56COPY --chown=remix-api:nodejs --from=installer /app/backend/dist ./backend/dist57COPY --chown=remix-api:nodejs --from=installer /app/node_modules ./node_modules58COPY --chown=remix-api:nodejs --from=installer /app/node_modules/@virgile/frontend ./node_modules/@virgile/frontend59COPY --chown=remix-api:nodejs --from=installer /app/node_modules/@virgile/typescript-config ./node_modules/@virgile/typescript-config60COPY --chown=remix-api:nodejs --from=installer /app/node_modules/@virgile/eslint-config ./node_modules/@virgile/eslint-config61COPY --chown=remix-api:nodejs --from=installer /app/backend/prisma ./backend/prisma6263COPY --chown=remix-api:nodejs --from=builder /app/backend/start.sh ./backend/start.sh6465ENTRYPOINT [ "backend/start.sh" ]
Et voici le fichier docker-compose.dev.yml
que nous allons configurer ensemble :
1services:2monorepo_dev:3environment:4- REDIS_URL=redis://redis_dev:63795- NODE_ENV=development6- DATABASE_URL78container_name: nestjs-remix-monorepo-dev9build:10context: .11dockerfile: Dockerfile12# image: varkoff/nestjs-remix-monorepo:dev13restart: always14ports:15- 3000:300016redis_dev:17image: redis:latest18restart: always19ports:20- '6379:6379'21command: ["redis-server"]22volumes:23- ./cache:/data
Docker Compose est conçu pour orchestrer plusieurs conteneurs Docker. Par exemple, une base de donnée Redis, une application frontend et une application backend.
Dans notre cas, nous n'utilisons qu'un seul service (pour l'instant). Il s'appelle monorepo_dev
.
Voici les différentes instructions :
environment
: contient les variables d'environnements. Pour chaque variable d'environnement que vous utilisez dans le projet, vous devez ABSOLUMENT la rajouter ici. Sinon elle ne sera jamais détectée par notre application.container_name
: le nom de notre conteneur. Utile lorsque nous voudrons lancer plusieurs conteneurs, par exemple un environnement de staging et un environnement de production.build
: le contexte de notre build. En production, nous allons télécharger l'image Docker directement depuis Docker Hub. En local, nous allons utiliser le Dockerfile pour créer notre propre image Docker. (Pour s'assurer que l'application se build sans erreur.)restart
: cette instruction permet de redémarrer le conteneur (notre application) en cas de crash. Très utile.ports
: Nous effectuons ici du reverse proxy. Par défaut, notre application tourne dans une image virtualisée, elle est inaccessible en dehors du conteneur. Avec cette instruction, nous bindons le port 3000 de notre machine hôte (ordinateur en local) sur le port 3000 de l'image virtualisée. Cela signifie que Docker va nous autoriser à accéder à son port 3000.volumes
: Cette instruction est nécessaire lorsque nous utilisons une base de données, ou que nous souhaitons conserver les fichiers sauvegardés sur le disque dur du serveur. Si cette instruction n'est pas présente, les fichiers seront supprimés à chaque fois que le conteneur est relancé (à chaque mise en production).Maintenant, nous allons créer le même fichier qui lancera notre application en production.
Il est similaire, à l'exception qu'il n'effectuera pas un build sur le serveur qui lance l'application. Le build sera lancé en amont durant la CI/CD avec Github Actions.
Pour différencier les deux images en inspectant les logs avec la commande docker ps
, nous nommons le container nestjs-remix-monorepo-prod
au lieu de nestjs-remix-monorepo-dev
.
1services:2monorepo_prod:3environment:4- REDIS_URL=redis://redis_prod:63795- NODE_ENV6- DATABASE_URL789container_name: nestjs-remix-monorepo-prod10image: varkoff/nestjs-remix-monorepo:production11restart: always12ports:13- 3000:300014redis_prod:15image: redis:latest16restart: always17command: ["redis-server"]18volumes:19- /dev/volumes/nestjs-remix/production/sessions/:/data
Nous devons maintenant créer un compte gratuit sur le site Docker Hub.
Une fois connecté, nous allons créer un nouveau repository. Nous allons lui donner le même nom que l'on a défini dans notre fichier docker-compose.prod.yml
à savoir nestjs-remix-monorepo
.
L'instruction image: varkoff/nestjs-remix-monorepo:production
signifie que notre image Docker se nommera varkoff/nestjs-remix-monorepo
ou varkoff
représente le nom de votre compte DOcker, et production
le tag de l'image.
Sauf que le repository ne contient pas encore d'image hébergée. Nous venons tout juste de le créer.
Dans la prochaine leçon, nous allons configurer les Github Actions pour automatiquement mettre à jour notre application sur le serveur de production.