Docker
Docker est un logiciel libre permettant de lancer des applications dans des conteneurs.
C'est est un outil qui peut empaqueter une application et ses dépendances dans un conteneur isolé, qui pourra être exécuté sur n'importe quel serveur. Il ne s'agit pas de virtualisation, mais de conteneurisation, une forme plus légère qui s'appuie sur certaines parties de la machine hôte pour son fonctionnement. Cette approche permet d'accroître la flexibilité et la portabilité d’exécution d'une application, laquelle va pouvoir tourner de façon fiable et prévisible sur une grande variété de machines hôtes, que ce soit sur la machine locale, un cloud privé ou public, une machine nue, etc...
Contrairement aux machines virtuelles traditionnelles, un conteneur Docker n'inclut pas de système d'exploitation, mais s'appuie au contraire sur les fonctionnalités du système d’exploitation fournies par la machine hôte.
J'ai trouvé sur youtube une excellente série de vidéos que je vais essayer de mettre en pratique, commenter et éventuellement mettre à jour.
1) Installation de docker
L'installation ci-dessous va utiliser les repositories Docker officiels (au lieu des repositories Raspbian qui ne sont pas toujours à jour).
# Install some required packages first
sudo apt update
sudo apt install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common
# Get the Docker signing key for packages
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -
# Add the Docker official repos
echo "deb [arch=armhf] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list
# Install Docker
# The aufs package, part of the "recommended" packages, won't install on Buster just yet, because of missing pre-compiled kernel modules.
# We can work around that issue by using "--no-install-recommends"
sudo apt update
sudo apt install -y --no-install-recommends \
docker-ce \
cgroupfs-mount
# Pour démarrer automatiquement Docker au démarrage de la machine
sudo systemctl enable docker
# Quelques commandes utiles pour arrêter, démarrer, redémarrer ou vérifier le statut de Docker
sudo systemctl stop docker
sudo systemctl start docker
sudo systemctl restart docker
sudo systemctl status docker
# Pour tester que Docker fonctionne bien
pi@raspberrypi2:~ $ sudo docker run --rm arm32v7/hello-world
Unable to find image 'arm32v7/hello-world:latest' locally
latest: Pulling from arm32v7/hello-world
c1eda109e4da: Pull complete
Digest: sha256:07e995a680212a0a8a01e181b3fff128d44b8fe0c11426b638ec3cde7273f0a3
Status: Downloaded newer image for arm32v7/hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm32v7)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
pi@raspberrypi2:~ $
2) Quelques commandes indispensables
La vidéo suivante montre quelques commandes basiques, pour manipuler les images et containers ainsi que des commandes systèmes.
3) Exécuter Jenkins dans un container Docker
La vidéo suivante explique comment exécuter Jenkins dans un container Docker, et comment créer et utiliser les volumes.
Mise en pratique
# On télécharge l'image jenkins/jenkins:lts depuis le Docker Hub (https://hub.docker.com/r/jenkins/jenkins)
prabou@prabou-VPCZ23C5E:~$ sudo docker pull jenkins/jenkins:lts
lts: Pulling from jenkins/jenkins
092586df9206: Pull complete
ef599477fae0: Pull complete
4530c6472b5d: Pull complete
d34d61487075: Pull complete
272f46008219: Pull complete
12ff6ccfe7a6: Pull complete
f26b99e1adb1: Pull complete
b5a7230f28ac: Pull complete
d19ccd039899: Pull complete
0cd916c5652e: Pull complete
e7f33481e423: Pull complete
3c8f6834c187: Pull complete
aed304377df9: Pull complete
841ddf9b4483: Pull complete
84beffd862a8: Pull complete
2643324effeb: Pull complete
2b8c3739eb59: Pull complete
42423eff2b9e: Pull complete
ce3c0ae47fcb: Pull complete
Digest: sha256:bf741663dff2c5c163bd16706d4d1b9e6f86fa7b92e365257e170239d0bfb24f
Status: Downloaded newer image for jenkins/jenkins:lts
docker.io/jenkins/jenkins:lts
# On affiche les images disponibles
prabou@prabou-VPCZ23C5E:~$ sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
jenkins/jenkins lts 5721a6cac43c 2 weeks ago 572MB
prabou@prabou-VPCZ23C5E:~$
prabou@prabou-VPCZ23C5E:~$ mkdir jenkins_home
prabou@prabou-VPCZ23C5E:~$ sudo chmod 777 jenkins_home
# On démarre un container à partir de cette image tout en créant le volume /home/prabou/jenkins_home sur le système hôte
prabou@prabou-VPCZ23C5E:~$ sudo docker run --name container_prabou1 -p 8080:8080 -p 50000:50000 -v /home/prabou/jenkins_home:/var/jenkins_home jenkins/jenkins:lts
Running from: /usr/share/jenkins/jenkins.war
webroot: EnvVars.masterEnvVars.get("JENKINS_HOME")
2019-10-16 20:33:33.692+0000 [id=1] INFO org.eclipse.jetty.util.log.Log#initialized: Logging initialized @659ms to org.eclipse.jetty.util.log.JavaUtilLog
2019-10-16 20:33:33.849+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file
2019-10-16 20:33:35.466+0000 [id=1] WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2019-10-16 20:33:35.529+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-9.4.z-SNAPSHOT; built: 2019-05-02T00:04:53.875Z; git: e1bc35120a6617ee3df052294e433f3a25ce7097; jvm 1.8.0_222-b10
2019-10-16 20:33:35.925+0000 [id=1] INFO o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2019-10-16 20:33:35.996+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: DefaultSessionIdManager workerName=node0
2019-10-16 20:33:35.997+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: No SessionScavenger set, using defaults
2019-10-16 20:33:36.003+0000 [id=1] INFO o.e.j.server.session.HouseKeeper#startScavenging: node0 Scavenging every 660000ms
Jenkins home directory: /var/jenkins_home found at: EnvVars.masterEnvVars.get("JENKINS_HOME")
2019-10-16 20:33:36.598+0000 [id=1] INFO o.e.j.s.handler.ContextHandler#doStart: Started w.@53499d85{Jenkins v2.190.1,/,file:///var/jenkins_home/war/,AVAILABLE}{/var/jenkins_home/war}
2019-10-16 20:33:36.623+0000 [id=1] INFO o.e.j.server.AbstractConnector#doStart: Started ServerConnector@302c971f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2019-10-16 20:33:36.624+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: Started @3592ms
2019-10-16 20:33:36.624+0000 [id=21] INFO winstone.Logger#logInternal: Winstone Servlet Engine v4.0 running: controlPort=disabled
2019-10-16 20:33:38.717+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization
2019-10-16 20:33:38.759+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins
2019-10-16 20:33:40.354+0000 [id=33] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
2019-10-16 20:33:40.362+0000 [id=33] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins
2019-10-16 20:33:40.378+0000 [id=28] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
2019-10-16 20:33:41.193+0000 [id=27] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
2019-10-16 20:33:41.238+0000 [id=46] INFO hudson.model.AsyncPeriodicWork$1#run: Started Download metadata
2019-10-16 20:33:41.251+0000 [id=46] INFO hudson.util.Retrier#start: Attempt #1 to do the action check updates server
2019-10-16 20:33:42.470+0000 [id=28] INFO o.s.c.s.AbstractApplicationContext#prepareRefresh: Refreshing org.springframework.web.context.support.StaticWebApplicationContext@6df25b1b: display name [Root WebApplicationContext]; startup date [Wed Oct 16 20:33:42 UTC 2019]; root of context hierarchy
2019-10-16 20:33:42.471+0000 [id=28] INFO o.s.c.s.AbstractApplicationContext#obtainFreshBeanFactory: Bean factory for application context [org.springframework.web.context.support.StaticWebApplicationContext@6df25b1b]: org.springframework.beans.factory.support.DefaultListableBeanFactory@7d1dc4b8
2019-10-16 20:33:42.489+0000 [id=28] INFO o.s.b.f.s.DefaultListableBeanFactory#preInstantiateSingletons: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7d1dc4b8: defining beans [authenticationManager]; root of factory hierarchy
2019-10-16 20:33:42.778+0000 [id=28] INFO o.s.c.s.AbstractApplicationContext#prepareRefresh: Refreshing org.springframework.web.context.support.StaticWebApplicationContext@3a996d27: display name [Root WebApplicationContext]; startup date [Wed Oct 16 20:33:42 UTC 2019]; root of context hierarchy
2019-10-16 20:33:42.779+0000 [id=28] INFO o.s.c.s.AbstractApplicationContext#obtainFreshBeanFactory: Bean factory for application context [org.springframework.web.context.support.StaticWebApplicationContext@3a996d27]: org.springframework.beans.factory.support.DefaultListableBeanFactory@10ff9cb
2019-10-16 20:33:42.780+0000 [id=28] INFO o.s.b.f.s.DefaultListableBeanFactory#preInstantiateSingletons: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@10ff9cb: defining beans [filter,legacy]; root of factory hierarchy
2019-10-16 20:33:43.190+0000 [id=28] INFO jenkins.install.SetupWizard#init:
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
82c337f27cd14033be4cecc913d4b775
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
2019-10-16 20:33:49.974+0000 [id=46] INFO hudson.model.UpdateSite#updateData: Obtained the latest update center data file for UpdateSource default
2019-10-16 20:33:51.318+0000 [id=46] INFO h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2019-10-16 20:33:51.320+0000 [id=46] INFO hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1
2019-10-16 20:33:51.323+0000 [id=46] INFO hudson.model.AsyncPeriodicWork$1#run: Finished Download metadata. 10,084 ms
2019-10-16 20:33:51.592+0000 [id=28] INFO hudson.model.UpdateSite#updateData: Obtained the latest update center data file for UpdateSource default
2019-10-16 20:33:51.816+0000 [id=33] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization
2019-10-16 20:33:51.841+0000 [id=20] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running
Maintenant que Jenkins est prêt, on ouvre Firefox à l'url http://localhost:8080/
Lorsqu'un container est supprimé, l'ensemble des fichiers présents à l'intérieur le sont également.
C'est pour cette raison que nous avons créé un volume (externe au container) qui contiendra toute la configuration Jenkins. La création d'un volume consiste soit à monter un répertoire du système d’exploitation hôte, soit un "vrai" volume completement géré par Docker ce qui a plusieurs avantages.
Parmi les avantages on peut citer:
- les volumes sont plus faciles à sauvegarder que les montages de répertoires (de la machine hôte ou ailleurs)
- la possibilité de gérer les volumes avec Docker CLI ou l'API Docker.
- les volumes fonctionent aussi bien avec les containers Linux que Windows.
- les volumes peuvent être partagés de façon sécurisée entre plusieurs containers.
- les volumes drivers permettent de stocker les volumes sur un hôte distant ou un cloud, d'encrypter le contenu des volumes ou encore d'ajouter d'autres fonctionnalités
- les nouveaux volumes peuvent avoir leur contenu pre-populé par un conteneur.
4) Dockerfile
5) Sources
Si vous chercher des livres ou des sites internet pour vous documenter sur Docker, voici quelques références:
- Learning Docker - Optimize the power of Docker to run your applications quickly and easily (livre)