Conteneuriser une application : Un exemple avec Svelte / Node
Apprenez à conteneuriser une application SvelteKit avec Docker. Exemple complet avec Node.js, configuration du Dockerfile et exécution en environnement isolé.
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).