docker_icon

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/

Jenkins1 Jenkins2 Jenkins3 Jenkins4 Jenkins5 Jenkins6 Jenkins7

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)