Conteneuriser une application : Un exemple avec Svelte / Node

Et comment on fait avec une application Node ? Genre SvelteKit par exemple ?

DONNE MOI LE RÉSUMÉ

Un dernier exemple de conteneurisation avant de passer Ă  autre chose : transformer une application Svelte / Node en un conteneur.

Nous allons travailler dans un nouveau dossier et généré un projet sveltekit simplistes.

mkdir svelte
cd svelte
npm create svelte@latest sveltekit-simple
Need to install the following packages:
create-svelte@6.0.8
Ok to proceed? (y) y

create-svelte version 6.0.8

┌  Welcome to SvelteKit!
│
◇  Which Svelte app template?
│  SvelteKit demo app
│
◇  Add type checking with TypeScript?
│  No
│
◇  Select additional options (use arrow keys/space bar)
│  none
│
└  Your project is ready!

Nous allons utiliser le projet Sveltekit de démo, sans type checking ni autre élément.

cd sveltekit-simple
npm install
touch Dockerfile

Comme pour Ruby, et comme pour toutes applications Ă  conteneuriser, il faut d’abord regarder notre environnement. Pour Svelte, cela commence par regarder la version de node utilisĂ© en local et en trouvant une Ă©quivalente sur le docker hub de node.

node --version
v18.17.1

La version la plus proche sur docker est 18.19-bookworm mais la souplesse de node fait que nous pouvons nous permettre d’utiliser les versions plus rĂ©centes comme 21.6-bookworm.

ARG NODE_VERSION=21.6-bookworm
FROM node:${NODE_VERSION}

Pour une application node, le plus simple est d’abord d’installer les dĂ©pendances avec NPM, puis copier les fichiers pour enfin lancer les commande de productions. Commençons par les deux premiĂšres Ă©tapes.

ARG NODE_VERSION=21.6-bookworm
FROM node:${NODE_VERSION}

WORKDIR /app

COPY ./package*.json ./
RUN npm install

COPY ./src/ ./src/
COPY ./static/ ./static/
COPY ./.npmrc ./
COPY ./*.config.js ./

Tu l’auras remarquĂ©, il faut d’abord copier les fichiers des dĂ©pendances npm, installĂ© les dĂ©pendances, puis copier les fichiers utiles de notre application. Attention, si l’on fait une copie du type COPY ./* ./, docker va aussi copie le node_modules local, ce qui va surcharger nos dĂ©pendances du conteneur que l’on vient juste d’installer. Dans la derniĂšre section, on verra comment faire pour pouvoir ignorer des fichiers lorsque l’on fait des COPY ./* ./.

Un dernier dĂ©tail, lorsque l’on utilise COPY, il faut faire attention Ă  respecter la syntaxe pour les dossiers. Par exemple, faire COPY ./src ./ est trĂšs diffĂ©rents de COPY ./src/ ./src/. Dans le premier cas, docker va copier tous les fichiers du dossier local src dans le chemin actuel, sans crĂ©er de nouveau dossier. Dans le second cas, docker copie tous les fichiers du dossier src vers un dossier src sur le conteneur, qu’il crĂ©e s’il n’existe pas.

Pour svelte, il est important de modifier ce qui est appelĂ© un adaptateur dans le fichier svelte.config.js. Comme nous utilisons node, nous allons modifier l’adaptateur pour celui de node.

import adapter from '@sveltejs/adapter-node';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
    // If your environment is not supported or you settled on a specific environment, switch out the adapter.
    // See https://kit.svelte.dev/docs/adapters for more information about adapters.
    adapter: adapter(),
  },
};

export default config;

Nous devons installe l’adaptateur en local pour l’ajouter aux dĂ©pendances.

npm install @sveltejs/adapter-node

Pour construire les fichiers de production, nous devons appeler la commande npm run build qui crée un dossier build que nous pouvons servir avec node.

ARG NODE_VERSION=21.6-bookworm
FROM node:${NODE_VERSION}

WORKDIR /app

COPY ./package*.json ./
RUN npm install

COPY ./src/ ./src/
COPY ./static/ ./static/
COPY ./.npmrc ./
COPY ./*.config.js ./

RUN npm run build
CMD ["node", "build"]
docker build --tag tornade-svelte .
[+] Building 5.8s (14/14) FINISHED                                                                                                                          docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                                        0.0s
 => => transferring dockerfile: 276B                                                                                                                                        0.0s
 => [internal] load .dockerignore                                                                                                                                           0.0s
 => => transferring context: 2B                                                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/node:21.6-bookworm                                                                                                       0.0s
 => [1/9] FROM docker.io/library/node:21.6-bookworm                                                                                                                         0.0s
 => [internal] load build context                                                                                                                                           0.0s
 => => transferring context: 1.48kB                                                                                                                                         0.0s
 => CACHED [2/9] WORKDIR /app                                                                                                                                               0.0s
 => CACHED [3/9] COPY ./package*.json ./                                                                                                                                    0.0s
 => CACHED [4/9] RUN npm install                                                                                                                                            0.0s
 => [5/9] COPY ./src/ ./src/                                                                                                                                                0.3s
 => [6/9] COPY ./static/ ./static/                                                                                                                                          0.0s
 => [7/9] COPY ./.npmrc ./                                                                                                                                                  0.0s
 => [8/9] COPY ./*.config.js ./                                                                                                                                             0.0s
 => [9/9] RUN npm run build                                                                                                                                                 4.8s
 => exporting to image                                                                                                                                                      0.5s
 => => exporting layers                                                                                                                                                     0.5s
 => => writing image sha256:04048190c37ee81cafff2323b365435c32917269881a9d26546492d0781b44cf                                                                                0.0s 
 => => naming to docker.io/library/tornade-svelte                                                                                                                           0.0s

Il nous reste plus qu’à lancer notre application en n’oubliant pas de mapper les ports 3000 du conteneur et en local.

docker run -p 3000:3000 tornade-svelte

Et cela fonctionne ! Bravo, tu viens de conteneuriser ta premiĂšre application node !

Takeaways

Conteneuriser une application se fait toujours en essayant de copier les commandes que l’on effectuerait en local pour dĂ©ployer notre application.

La commande COPY peut ĂȘtre capricieuse et il faut bien respecter et tester sa syntaxe.

Si le docker hub ne dispose pas spĂ©cifique de notre version, il est toujours judicieux d’essayer avec une autre version disponible (avant de crĂ©er sa propre image).