Update Article “2023-04-11-fabriquer-des-conteneurs-légers-depuis-une-ci-cd”
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
8d000c365d
commit
9d650fbcf1
1 changed files with 37 additions and 32 deletions
|
@ -19,55 +19,60 @@ Alors maintenant qu'on a notre périmètre, décortiquons le:
|
||||||
- **multi-plateforme :** un seul tag d'image permettra à des gens sur ARM comme sur X86_64 d'utiliser votre logiciel
|
- **multi-plateforme :** un seul tag d'image permettra à des gens sur ARM comme sur X86_64 d'utiliser votre logiciel
|
||||||
- **publier** : on publier les conteneurs sur un registre, ici nous verrons comment faire sur le docker hub mais aussi sur notre registre statique à base de Garage
|
- **publier** : on publier les conteneurs sur un registre, ici nous verrons comment faire sur le docker hub mais aussi sur notre registre statique à base de Garage
|
||||||
|
|
||||||
_À noter qu'il y a un dernier point qui ne sera pas abordé dans ce billet qui sera sans aucun doute beaucoup trop long de toute manière, c'est comment gérer la garbage collection de nos artifacts._
|
_À noter qu'il y a un dernier point qui ne sera pas abordé dans ce billet qui sera sans aucun doute beaucoup trop long de toute manière, c'est comment gérer la garbage collection de nos artifacts._
|
||||||
|
|
||||||
## Une build file avec Nix Flake
|
## Une build file avec Nix Flake
|
||||||
|
|
||||||
Pour ce billet, on va prendre comme un exemple un programme en go que j'ai écrit, Albatros, ma propre CI/CD (ça devient déjà meta). L'avantage de prendre comme exemple un programme en Go, c'est que ça se cross compile facilement. Voilà un extrait du fichier `flake.nix` de notre projet :
|
Pour ce billet, on va prendre comme un exemple un programme en go que j'ai écrit, Albatros, ma propre CI/CD (ça devient déjà meta). L'avantage de prendre comme exemple un programme en Go, c'est que ça se cross compile facilement. Voilà un extrait du fichier `flake.nix` de notre projet :
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
# declare the go module of this package, allow for cross compilation
|
# declare the go module of this package, allow for cross compilation
|
||||||
gopkg = arch: (pkgs.buildGoModule rec {
|
gopkg = arch: (pkgs.buildGoModule rec {
|
||||||
pname = "albatros-go-module";
|
pname = "albatros-go-module";
|
||||||
version = "0.9";
|
version = "0.9";
|
||||||
CGO_ENABLED = 0;
|
CGO_ENABLED = 0;
|
||||||
# ...
|
# ... skip
|
||||||
}).overrideAttrs (old: old // { GOOS = "linux"; GOARCH = arch; });
|
}).overrideAttrs (old: old // { GOOS = "linux"; GOARCH = arch; });
|
||||||
|
|
||||||
# logic to build static binaries
|
# logic to build static binaries
|
||||||
albatrosStaticBin = arch: pkgs.stdenv.mkDerivation {
|
albatrosStaticBin = #... extract the binary from gopkg (skipped here)
|
||||||
pname = "albatros";
|
|
||||||
version = "0.9";
|
|
||||||
unpackPhase = "true";
|
|
||||||
installPhase = ''
|
|
||||||
cp `find ${gopkg arch}/bin -name albatros` $out
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# logic to build docker containers
|
# logic to build docker containers
|
||||||
docker = staticBin: arch: pkgs.dockerTools.buildImage {
|
docker = (staticBin: arch: pkgs.dockerTools.buildImage {
|
||||||
name = "dxflrs/albatros";
|
name = "dxflrs/albatros";
|
||||||
architecture = arch;
|
architecture = arch;
|
||||||
config = {
|
config = {
|
||||||
Cmd = [ "${staticBin}" ];
|
Cmd = [ "${staticBin}" ];
|
||||||
};
|
};
|
||||||
};
|
});
|
||||||
|
|
||||||
# map nixos/llvm arch to golang arch
|
# map nixos/llvm arch to golang arch
|
||||||
archmap = {
|
archmap = {
|
||||||
"aarch64-linux" = "arm64";
|
"aarch64-linux" = "arm64";
|
||||||
"x86_64-linux" = "amd64";
|
"x86_64-linux" = "amd64";
|
||||||
"i686-linux" = "386";
|
"i686-linux" = "386";
|
||||||
"armv6l-linux" = "arm";
|
"armv6l-linux" = "arm";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# generate packages for each architecture
|
||||||
|
packages = builtins.mapAttrs (name: value: {
|
||||||
|
docker.albatros = (docker (albatrosStaticBin value) value);
|
||||||
|
# other targets (skipped)...
|
||||||
|
}) archmap;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Ce fichier est relativement simple à lire une fois qu'on sait comment le lire. Ici, on va construire par rafinement successif les outils pour construire notre conteneur. Le premier bloc consiste en une fonction qui permet de compiler un module Go à partir de la recette fournie par la bibliothèque standard NixOS. Je dis bien une fonction, car ce bloc prend en paramètre `arch` qui contient l'architecture cible de notre module. Ainsi, si on lui passe `arm64` on aura un binaire qui fonctionne sur les processeurs ARM 64 bits, si on passe `386`, on aura un binaire pour les vieux PC x86 32 bits, etc.
|
||||||
|
|
||||||
|
Dans les blocs suivants, on raffine donc ce premier module. On va d'abord avoir une fonction qui va extraire le binaire statique du module généré par Go, ensuite une fonction Docker qui va mettre ce binaire statique dans un conteneur.
|
||||||
|
|
||||||
|
Enfin, on va déclarer quelles architectures on choisit de supporter, là j'en ai choisi 4. On va donc faire une boucle (`mapAttrs`) pour générer le conteneur Docker qui va bien pour chaque architecture.
|
||||||
|
|
||||||
|
## Créer les artefacts avec nix build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue