Hier j’ai découvert Earthly, un outil pour d’automatisation de construction d’image Docker, de binaires ou simplement pour faire tourner vos tests automatisés.
À quoi sert-il?
Cet outil vous permet, en un seul fichier Earthfile
, de générer différent type de choses au travers de targets.
Concrètement, si dans vos projet vous avez un fichier Dockerfile
pour votre développement, puis un fichier Dockerfile.ci
pour construire l’image où seront exécutés vos tests, ainsi qu’un fichier Dockerfile.production
pour créer l’image finale de votre projet, vous pourrez faire la même chose en déclarant 3 targets pour les 3 différents environnements.
Vos 3 fichiers ont des points communs et des différences. Les points communs sont à mettre dans un ou des targets qui serviront dans les 3 targets finaux.
Pour mieux comprendre, si ce n’est pas clair, voici un exemple de la structure de votre Earthfile
où vous trouverez un target deps
pour installer les dépendences du projet (qui dans cette exemple sont toujours les mêmes, que ce soit en development, sur le CI ou en production) puis les 3 targets dev
, ci
, et prod
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM ruby
WORKDIR /application
deps:
# Installer ici les dépendences en utilisant les commandes COPY et RUN
# Puis à la fin sauvegarder l'image
SAVE IMAGE
prod:
FROM +deps
# Exécuter les commandes uniquement pour l'image de production
ci:
FROM +deps
# Exécuter les commandes pour lancer les tests
dev:
FROM +deps
# Exécuter les commandes uniquement pour l'image de production
Ceci replace vos 3 fichiers, et pas besoin de commande où vous passez tel ou tel Dockerfile
!
Comment créer les images?
Après avoir installé Earthly, vous aurez la commande earth
qui permet d’utiliser votre nouveau fichier Earthfile
.
Il vous suffit de passer le target voulut en paramètre en ajoutant un +
devant son nom.
Pour lancer le target dev
, vous le ferez en lancant la commande:
1
earth +dev
Un exemple concret
J’ai donc testé ce nouvel outil sur mon projet bac à sable: Brewformuas.org.
Vous trouverez le commit où j’ai remplacé mes fichiers Dockerfile
par un fichier Earthfile
ici.
Et voici mon fichier Earthfile
pour ce projet Ruby On Rails:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
FROM ruby:2.6-slim-buster
WORKDIR /application
# `deps` installs all the system libraries required by the gems in order
# to install them all.
# Finally it creates a temporary image used as a base image later.
deps:
RUN apt-get update \
&& apt-get install -y libpq-dev \
build-essential \
nodejs \
git
SAVE IMAGE
# `gems` installs all the gems from the Gemfile.lock for a production usage.
# Finally it creates a temporary image used as a base image later.
gems:
FROM +deps
ENV BUNDLE_GEMFILE=/application/Gemfile
ENV BUNDLE_JOBS=8
ENV BUNDLE_PATH=/bundle
COPY Gemfile* ./
RUN gem install rubygems-update \
&& update_rubygems \
&& gem install bundler:1.16.0 \
&& bundle install --without development test
SAVE IMAGE
# `assets` runs the Rails assets:precompile task and create an artifact from it
# used in the `prod` target.
assets:
FROM +gems
ENV RAILS_ENV production
COPY . /application
RUN bundle exec rake assets:precompile RAILS_ENV=production
SAVE ARTIFACT public/assets assets
# `prod` builds the production image of the project which means precompiling
# the projet assets.
# Finally it creates the Docker image used in order to run the project.
prod:
FROM +gems
ENV RAILS_ENV production
RUN useradd -ms /bin/bash brewformulas
COPY . /application
COPY +assets/assets public/assets
RUN chown -R brewformulas:users /application
EXPOSE 3000
ENTRYPOINT ["bundle", "exec"]
CMD ["bin/rails server -b 0.0.0.0"]
SAVE IMAGE zedtux/brewformulas.org:latest
# `ci` is based on the production image, in order to keep an environmnet as
# close as possible with production when running the tests.
# Nonetheless it install additionnal gems used to run the tests.
ci:
FROM +prod
ENV RAILS_ENV test
RUN bundle config --delete without
RUN bundle install --gemfile=/application/Gemfile \
--jobs=8 \
--path=/bundle \
--without development
SAVE IMAGE zedtux/brewformulas.org:latest-ci
# `dev` is based on the production image, in order to keep an environmnet as
# close as possible with produciton and then installs all the other gems for
# developing the project.
# The final image is used by the local docker-compose.yml file.
dev:
FROM +prod
ENV RAILS_ENV development
RUN bundle config --delete without
RUN bundle install --gemfile=/application/Gemfile \
--jobs=8 \
--path=/bundle
# Allow adding/removing/updating gems
RUN chown -R brewformulas:users /bundle
SAVE IMAGE zedtux/brewformulas.org:latest-dev
Explications
deps
Ce target est responsable pour l’installation des paquets systèmes nécessaires à la compilation de certaines gems du projet.
J’utilises SAVE IMAGE
à la fin pour créer une image de base pour les targets suivant.
gems
Ce target commence par déclarer qu’il se base sur l’image générée depuis le target deps
.
Ensuite il va déclarer les variables d’environnement de bundler, copier les fichiers Gemfile
et Gemfile.lock
puis installer les gems dans le dossier /bundle
après avoir installé bundler.
Pour finir j’utilises encore une fois SAVE IMAGE
bien que j’aurai put utiliser SAVE ARTIFACT
pour ne garder que le dossier /bundle
.
Surement une amélioration que je ferai 😉
assets
Ce target se base sur l’image générée depuis le target gems, de manière à avoir tout l’environnement nécessaire à pré-compiler les assets (CSS, JS, polices d’écritures et images).
RAILS_ENV
y est défini avec la valeur production
car le projet n’a pas d’autres cas où utiliser rake assets:precompile
.
Puis il lance la commande bundle exec rake assets:precompile
.
Je viens de me rendre compte que j’ai oublié de retirer RAILS_ENV=production dans la commande RUN …
Ce target fini avec la commande SAVE ARTIFACT public/assets assets
qui indique à Earthly de sauvegarder le contenu du dossier /application/public/assets
dans un espace nommé assets
de façon à pouvoir le ré-importer n’importe quand.
prod
Évidement, ce target permet de générer l’image finale pour le déploiement (qui ne se fait plus depuis que j’ai arrêter son hergement).
Il se base sur l’image générée depuis le target gems
puis il redéfini la variable d’environnement RAILS_ENV
à production
, créé l’utilisateur brewformulas
qui sera utilisé pour lancer le projet, il importe les fichiers du projet.
L’artifacte assets
est importé après car le dossier du projet contient déjà un dossier public
, et je suppose qu’importer l’artifacte assets
avant la copie des fichiers du projet pourrait effacer le dossier public/assets
.
Il fini sur le paramètrage EXPOSE
, ENTRYPOINT
et CMD
, puis se termine en créant l’image, mais en donnant son nom final qui est zedtux/brewformulas.org:latest
ci
Ce target se base sur l’image de production, il redéfini la variable d’environnement RAILS_ENV
, il installe les gems pour lancer les tests et fini par créer une image zedtux/brewformulas.org:latest-ci
.
dev
Ce target se base sur l’image de production aussi, il redéfini la variable d’environnement RAILS_ENV
.
Pour annuler l’effet de la commande bundle install --without development test
qui a été utilisé dans le target gems, j’utilises la commande bundle config --delete without
.
Pour finir, il install tous les gems, et change les permissions du dossier /bundle
de manière à ce que je puisse continuer à ajouter/supprimer/mettre à jour des gems en développement.
Il fini sur la création de l’image docker zedtux/brewformulas.org:latest-dev
afin d’avoir une image nommée.
Si j’avais laissé zedtux/brewformulas.org:latest
, puisque le nom est le même que dans le tatget prod
, Earthly aurait gardé zedtux/brewformulas.org:latest
uniquement pour l’image de production, ce qui aurait pour effet que l’image de dev
ne serait accessible que par son ID:
1
2
zedtux/brewformulas.org <none> efaff4f9ed29 28 hours ago 1.15GB
zedtux/brewformulas.org latest 9116b6c229ef 28 hours ago 740MB
Du coup, j’ai changé le fichier docker-compose.yml
pour que l’attribut image
de chaque services pointent vers zedtux/brewformulas.org:latest-dev
.
Conclusion
Earthly est un super outil, qui facilite encore plus la gestion de projets avec Docker, et une fois son principe compris, vous ne pourrez plus vous en passer, j’en suis sûr! ☺️
En tous les cas, personnellement, je vais pousser pour utiliser cet outil dans les projets dans lesquelles je travails, c’est certain 😇.