Pour travailler ensemble
Tout le monde dĂ©veloppe sur diffĂ©rentes machines. Il nâest pas rare que plusieurs collĂšgues aient installĂ© diffĂ©rentes version dâune mĂȘme library, dâun package manager, du runtime de leur applicationâŠâ (cc node/npm đ)
Lorsque lâapplication de dĂ©veloppement est dockerisĂ©e, tous les devs (et la prod !) sont soumis aux mĂȘmes rĂšgles, ce qui Ă©vite le syndrĂŽme de "mais ça marche sur mon PC" tout en rĂ©duisant la configuration nĂ©cessaire Ă installer lâenvironnement de dev. Voir juste aprĂšs !
La configuration, câest du temps passĂ© Ă ne pas ĂȘtre productif. Plus il y a dâenvironnements dans lesquels une application doit tourner, plus il y a de configuration Ă faire. Docker permet dâabstraire lâenvironnement dans lequel tourne lâapplication et donc de ne faire que le minimum nĂ©cessaire.
Une consĂ©quence notable : pour ajouter un service Ă la stack, plus forcĂ©ment besoin dâapprendre en dĂ©tails une technologie. Il suffit dâajouter une image existante de celle-ci, et de simplement spĂ©cifier les variables dâenvironnement nĂ©cessaires. Par exemple, pour ajouter une database PostgreSQL, il suffit au minimum de renseigner un root password et de monter un volume pour persister les donnĂ©es.
Pour séparer les problÚmes
Comme chaque service est aussi simple que possible, chacun nâa que trĂšs peu de dĂ©pendances avec le reste du monde. On voit que, par nature, les conteneurs nous poussent Ă nâavoir que le minimum vital de dĂ©pendances entre services.
Par dépendances, je pense en particulier à :
- SystÚme, programmes, libraries installées
- Configurations associées à ce setup
- Volumes (fichiers)
- AccÚs réseau
Pour gérer et sécuriser les connexions réseau
Car oui : câest vite fait de faire fuiter le port dâune database, et quand elle nâest pas sĂ©curisĂ©e câest gĂȘnant đŹ
LâidĂ©e est de penser un service comme une boĂźte noire qui expose un ou plusieurs ports. Les services communiquent entre eux grĂące aux volumes montĂ©s en commun ou Ă travers des ports internes. En effet, les services appartenant Ă un mĂȘme rĂ©seau peuvent par dĂ©faut sâaccĂ©der entre eux.
PiĂšges et trucs Ă savoir
Sous Windows et Mac, les conteneurs tournent sur une VM. Du coup câest lent, pas natif et les lectures/Ă©critures disque peuvent ralentir lâĂ©dition de fichiers. La solution est simple : utilise Linux đ (ou un Windows/Mac puissant)
Lorsquâun mĂȘme volume (dossier) est montĂ© en Ă©criture dans deux conteneurs Ă la fois, on peut se retrouver avec des comportements inattendus : chez moi, lâintĂ©gralitĂ© du dossier gĂ©nĂ©rĂ© par un run de build disparaissait en mĂȘme temps que le conteneur Ă la fin du run. Je recommande donc vivement de ne monter en Ă©criture quâun seul fichier ou dossier Ă la fois.
Câest possible de ne partager en Ă©criture quâune partie dâune mĂȘme arborescence commune. Par exemple, si backend
et frontend
partagent code
en lecture mais que backend
doit Ă©crire dans code/target
et frontend
doit Ă©crire dans code/dist
, alors les volumes peuvent ĂȘtre surchargĂ©s comme ceci :
backend:
volumes:
- ./code:/code:ro
- ./code/target:/code/target
webapp:
volumes:
- ./code:/code:ro
- ./code/dist:/code/dist
Les images Docker peuvent vite prendre de lâespace disque. Mais avec le temps, la communautĂ© opte de plus en plus pour des versions minimalistes de chaque image. Autrefois avec une version slim de Debian, et aujourdâhui souvent avec une version Alpine Linux qui permet aux images de faire moins de 10Mo de base ! PrĂ©fĂšre-donc utiliser les tags -alpine
de chaque image.
Enfin, la gestion des permissions est dĂ©routante au dĂ©but. Docker tourne en root par dĂ©faut et a de bonnes raisons de le faire : autant dire que jâapprĂ©cie de pouvoir ouvrir les ports 80 ou 443 en dev comme en prod đ
Pour mieux comprendre pourquoi et comment bien gérer ses permissions : voir cet article.
Par oĂč commencer?
En prenant le temps de lire la doc dans lâordre, tout ne peut que bien se passer :
Exemple
Une stack complĂšte React/Rust/PostgreSQL pourrait ĂȘtre lancĂ©e avec la simple config suivante Ă la racine dâun projet :
version: "3"
services:
db:
image: postgres:alpine
environment:
- POSTGRES_PASSWORD=yolo
volumes:
- ./db/data:/var/lib/postgresql/data
backend:
image: rust:slim
environment:
- PGHOST=db
- PGDATABASE=monservice
- PGUSER=root
- PGPASSWORD=yolo
volumes:
- ./backend/:/home/backend
- ./webapp/:/home/webapp:ro
command: cargo run
ports:
- 4000:4000
webapp:
image: node:alpine
environment:
- BACKEND_URL=http://backend:4000/
volumes:
- ./webapp/:/home/webapp
command: sh -c "yarn install && CI=true yarn start"
ports:
- 80:8080
docker compose up -d
et câest parti directement sur localhost ! đ»