Aller au contenu

Dagger & Dockerfile

On build des packages, on utilise les commandes Dagger, mais on ne va pas réinventer la roue non ? On avait l’habitude des Dockerfile, et tous nos projets les utilisent déjà, donc, on va réutiliser ce code avec Dagger!

On va donc essayer de build notre Dockerfile, et le publish sur un registrie privé type Scaleway.

Dockerfile

Pour l’instant, je vais partir sur un Dockerfile très très simple (Oui ce n’est pas en user node, mais c’est pour la démo)

Le voici :

FROM node:lts
WORKDIR /app
COPY . /app
EXPOSE 8080
CMD [ "npm", "run", "start" ]

Daggerization

Init

Pour daggerizer notre projet, on va déjà init dagger avec le SDK TypeScript.

Fenêtre de terminal
dagger init --sdk=typescript --source=./dagger

Ensuite, dans mon dagger.json je vais exclure les nodes_modules pour éviter de les copier si je suis en plein dev. Ceci peut poser problème entre les différentes versions d’OS et de node.

"exclude": [
"**/node_modules"
]

Build

On va déjà créer une fonction pour faire une installation des dépendances.

@func()
dev(source: Directory): Directory {
const nodeCache = dag.cacheVolume("node")
const npmInstall = dag
.container()
// start from a base Node.js container
.from("node:lts")
// add the source code at /src
.withDirectory("/app", source)
// mount the cache volume at /root/.npm
.withMountedCache("/root/.npm", nodeCache)
// change the working directory to /src
.withWorkdir("/app")
// run npm install to install dependencies
.withExec(["npm", "install"])
// Return directory
return npmInstall.directory("/app")
}

Cette fonction va nous permettre de retourner le répertoire avec le npm install qu’on utilisera plus tard.

On fait déjà un test ?

dagger call dev --source=.

Dagger build

Super ! Maintenant on va build le Dockerfile.

Build

Avant d’essayer de publish, nous allons essayer de tester le container en live depuis dagger.

C’est possible ???

Eh oui, vous pouvez créer des services que vous exposez sur votre hôte, si vous n’exposez pas, vous pouvez utiliser le service comme endpoint http pour vos autres fonctions.

@func()
build(source: Directory): Service {
const devDirectory = this.dev(source)
return dag
.container()
.withDirectory("/app", devDirectory)
.build(devDirectory,{dockerfile: "Dockerfile"})
.asService()
}

Je souhaite, exposer en tant que services pour vérifier que ça fonctionne et que le Dockerfile est bien pris en compte.

Si on lance simplement la commande suivante, le service va se lancer mais ne sera pas disponible sur notre hôte.

Fenêtre de terminal
dagger call build --source=.

Nous allons donc exposer le service avec --ports

Fenêtre de terminal
dagger call build --source=. up --ports 9002:8080

Dagger services

Notre conteneur répond bien !

*[main][~/Documents/dev-aidalinfo/tmp/node-api-demo]$ curl http://localhost:9002
Ready !!! 🔥🔥🔥

Parfait, maintenant on va le remettre en mode container :

@func()
build(source: Directory): Container {
const devDirectory = this.dev(source)
return dag
.container()
.withDirectory("/app", devDirectory)
.build(devDirectory,{dockerfile: "Dockerfile"})
}

Et si on test d’exposer sur notre hôte en mode container ?

Conteneur exposé

Ça fonctionne ! 😲

Conclusion

On a bien notre fonction qui permet le build avec le Dockerfile, pour le publish sur un registre privé, il faudra aller à la page suivante !

Je préfère séparer pour que les informations soient digestes et bien découpées.

Code Dagger

Voici le index.ts de dagger complet :

import { dag, Container, Directory, object, func } from "@dagger.io/dagger"
@object()
export class NodeApiDemo {
@func()
build(source: Directory): Container {
const devDirectory = this.dev(source)
return dag
.container()
.withDirectory("/app", devDirectory)
.build(devDirectory,{dockerfile: "Dockerfile"})
}
@func()
dev(source: Directory): Directory {
const nodeCache = dag.cacheVolume("node")
const npmInstall = dag
.container()
// start from a base Node.js container
.from("node:lts")
// add the source code at /src
.withDirectory("/app", source)
// mount the cache volume at /root/.npm
.withMountedCache("/root/.npm", nodeCache)
// change the working directory to /src
.withWorkdir("/app")
// run npm install to install dependencies
.withExec(["npm", "install"])
// Return directory
return npmInstall.directory("/app")
}
}

GitHub

https://github.com/Killian-Aidalinfo/node-api-demo-dockerfile