[vc_row][vc_column][vc_column_text]
Rapide intro sur Docker, installation, commandes basiques, dockerfile et docker-compose.
Les bases en somme.
Quick start.
Rendez vous sur https://hub.docker.com/ pour télécharger Docker Desktop (850 Mo environ).
Personnellement j'avais Oracle VM sur ma machine et Docker n'a pas aimé. J'ai eu aussi d'autres problèmes par la suite, du coup le plus simple c'est de tout désinstaller et tout réinstaller, à commencer par HyperV sur Windows. Virer aussi les variables d'environnement qui commence par DOCKER.
Une fois installé, ouvrir une fenêtre de commande et taper "docker —version" :
Votre installation est correcte.
Les bases
Si comme moi Docker vous l'avez vu de loin, il est peut être bon de revoir les bases, qq tuto sur le net, des petites videos youtubes peuvent vous faire du bien. Par exemple https://www.youtube.com/watch?v=fdlZqRZXWOc&list=PLn6POgpklwWq0iz59-px2z-qjDdZKEvWd
La vidéo nous explique comment créer et executer une image docker basé sur une distrib linux Alpine qui a l'avantage d'être ultra légère (5Mo !)
Commandes utiles
docker --version
docker ps
docker ps - a
docker pull alpine
docker run alpine:latest
docker -di --name mycontainername alpine:latest
docker run mycontainername
docker exec -ti mycontainername sh
docker stop mycontainername
docker rm mycontainername
remove all containers forcefully
docker rm -f $(docker ps -a -q)
remove all docker images forcefully
docker rmi -f $(docker images -q)
Monter un serveur web
https://www.youtube.com/watch?v=NJ2berxUmgg&list=PLn6POgpklwWq0iz59-px2z-qjDdZKEvWd&index=2
docker run -tid -p 8080:80 --name web nginx:latest
Cette commande lance un container avec l'image nginx qui est un serveur web, avec une redirection de port 8080 sur la machine host vers le port 80 du container.
Si vous avez redémarré votre machine, il faudra relancer le container :
docker start web
Pour avoir des infos sur votre container :
docker inspect web
[
{
"Id": "203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859",
"Created": "2020-01-09T15:54:16.1392739Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 3045,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-01-09T15:54:17.0341364Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:f7bb5701a33c0e572ed06ca554edca1bee96cbbc1f76f3b01c985de7e19d0657",
"ResolvConfPath": "/var/lib/docker/containers/203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859/hostname",
"HostsPath": "/var/lib/docker/containers/203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859/hosts",
"LogPath": "/var/lib/docker/containers/203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859/203a6655feec009ab84d8c61bc1135fbd49c9f9da7672cf7efb651594f7ed859-json.log",
"Name": "/web",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
]
},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
52,
176
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/6f5597eeb9943113a851aa40f4fa879f9be20b30757ba75495377110a157f0bb-init/diff:/var/lib/docker/overlay2/fb2e13f274925a9b6d047910047d5c41d5cdcd7ce743f13f7343cf862e39ba0c/diff:/var/lib/docker/overlay2/fe36b3a86cae3bbb35c68761d5e56bb8daeba054f7f564dca68d300575078531/diff:/var/lib/docker/overlay2/91166ce1015d94d52e6d00dd3afbbb9c8443be268a9c584cb37296e56bbd5d44/diff",
"MergedDir": "/var/lib/docker/overlay2/6f5597eeb9943113a851aa40f4fa879f9be20b30757ba75495377110a157f0bb/merged",
"UpperDir": "/var/lib/docker/overlay2/6f5597eeb9943113a851aa40f4fa879f9be20b30757ba75495377110a157f0bb/diff",
"WorkDir": "/var/lib/docker/overlay2/6f5597eeb9943113a851aa40f4fa879f9be20b30757ba75495377110a157f0bb/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "203a6655feec",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": true,
"OpenStdin": true,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.17.6",
"NJS_VERSION=0.3.7",
"PKG_RELEASE=1~buster"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "nginx:latest",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGTERM"
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "c47117b944d6f019ff284a4132f4cf4e528a1c2489fdbcb783523b48e6de1a1a",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "8080"
}
]
},
"SandboxKey": "/var/run/docker/netns/c47117b944d6",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "5190900bdbb29ebe0ff029f3dd285ed71720a52f4167176902cef5e5b2d7c4d1",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ed4b431234b99c2152d29f4c589ea7e9c6d2563db1318aaa99dc29288510b8b8",
"EndpointID": "5190900bdbb29ebe0ff029f3dd285ed71720a52f4167176902cef5e5b2d7c4d1",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
Vous pouvez accéder à votre nouveau seveur web de votre container depuis un browser de votre machine sur localhost:8080
Monter un volume
accéder au container avec un shell
docker exec -ti web sh
On peut modifier la page web d'accueil situé dans /usr/share/nginx/html/index.html et faire un refresh sur le browser, on verra notre modif, ca marche.
Arrêter et relancer ce container n'aura pas d'incidence.
Par contre, si on supprime le container et on le remet en place, il ne va plus rester de trace de notre modification.
Il faut alors utiliser des volumes montés (une sorte de passerelle entre votre disque dur de l'hote du container et celui ci).
on va supprimer notre container pour en refaire un tout propre :
docker rm -f web
docker run -tid -p 8080:80 -v D:\\Docker\\webshare:/usr/share/nginx/html --name web nginx:latest
on a ajouter le paramètre -v pour volume.
Il faut aussi cocher le partage de drives sur la config de Docker Desktop
Si on fait un inspect de ce container :
(...)
"Mounts": [
{
"Type": "bind",
"Source": "/host_mnt/d/Docker/webshare",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
(...)
On voit notre source qui est "/host_mnt/d/Docker/webshare"
Dans mon dossier D:\Docker\webshare j'ai ajouté un fichier index.html avec un bout de code "<h1>Hello World</h1>".
Un refresh de ma page localhost:8080 m'affiche mon fichier, magique !
On peut donc monter une image docker avec un serveur web dedans qui execute un site dont le code source se situe ailleurs, qq part sur votre machine. Pratique pour le développement.
Volumes plus proprement
La commande suivante permet de lister les volumes montés :
docker volume ls
Pour une raison que j'ignore, le volume que l'on a monté dans la commande précédente pour le site web n'est pas listée. On appelle ce genre de volume des volumes "Host". On va créer des volume "Named" :
docker volume create webshare
La précédente commande va créer un volume avec le nom "webshare". Listons les volumes :
docker volume ls
DRIVER VOLUME NAME
local webshare
Inspectons le détail de celui ci :
docker volume inspect webshare
[
{
"CreatedAt": "2020-01-10T08:41:00Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/webshare/_data",
"Name": "webshare",
"Options": {},
"Scope": "local"
}
]
Le mount point est "/var/lib/docker/volumes/webshare/_data", nous on voudrait avoir un path windows "D:\Docker\webshare"
TODO Comment modifier ce mountpoint ???
On va maintenant relancer notre serveur avec ce volume (pensez à faire un stop et un rm de votre précédent container)
docker run -tid --name web -p 8080:80 --mount source=webshare,target=/usr/share/nginx/html nginx:latest
Dockerfile
Le dockerfile est un fichier de configuration permettant d'executer un ensemble de commande pour créer une image docker spécifique à nos besoins.
Par exemple, pour monter un serveur web avec wordpress, on va avoir besoin de wordpress (fichiers code source php), d'un serveur web (nginx par exemple), de php7, d'une base de donnée (mySQL) d'un OS (debian par exemple) et peut être d'un ensemble d'outil (VIM, ...)
Tout ces éléments peuvent être "installé" via un dockerfile.
L'avantage c'est que ce fichier une fois en place permet d'être réutilisé facilement et reconstitura un environnement identique. L'image n'étant plus physique et volumineuse mais représentative et très légère. On peut partager un dockerfile par email alors qu'une image disk non.
Voici un example de dockerfile
FROM debian
LABEL Yann <yannvasseur@reactor.Fr>
RUN apt-get update
RUN apt-get install -y nginx
Ce docker file se base sur une image debian.
Label (anciennement MAINTAINER) identifie l'auteur de cette image docker
Run lance une commande. Dans un premier temps on va mettre a jour l'existant, puis installer nginx (le -y permet de répondre yes aux questions demandées).
Pour construire notre image, on va utiliser la commande docker build. Rendez vous dans le dossier où se trouve votre dockerfile (moi D:\Docker\dockerfiles), puis :
docker build -t yann/myctn .
Cette commande construit une image avec un nom yann/myctn (autheur/nom image, une convention). Le point permet de d'indiquer le répertoire courant. Lister les images de votre host :
docker image ls
Vous devriez la voir dans la liste. Maintenant lancer le container et un shell sur votre container :
docker run -tid --name myctn yann/myctn
docker exec -ti myctn sh
Ca y est, votre container est lancé et vous avez un shell dessus. Rapide !
Docker-Compose
Docker-Compose est une autre façon de créer des conteneurs. L'idée est monter plusieurs containers en une seule fois avec un fichier docker-compose.yml.
Par exemple, essayons de monter un site web wordpress. Dans mon exemple je vais prendre mon site web reactor.fr
Pour que wordpress fonctionne, il faut php + fichier php (wordpress) + mysql (base de donnée) et un serveur web.
version: '2'
services:
db:
image: mysql:5.7
container_name: db_server
volumes:
- ./reactorwp.db.sql:/docker-entrypoint-initdb.d/reactorwp.db.sql
ports:
- 3306:3306
restart: always
environment:
MYSQL_ROOT_PASSWORD: Passw0rd # any random string will do
MYSQL_DATABASE: wordpress782 # the name of your mysql database
MYSQL_USER: wordpressuser782 # the name of the database user
MYSQL_PASSWORD: 123456 # the password of the mysql user
wordpress:
depends_on:
- db
image: wordpress:php7.1 # we're using the image with php7.1
container_name: wp_web
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpressuser782
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wordpress782
ports:
- 8000:80
restart: always
volumes:
- ./src:/var/www/html
Le fichier ci dessus est nommé docker-compose.yml
Pour lancer nos containers on va lancer la commande
docker-compose up
ou
docker-compose up -d
Pour arrêter nos containers:
docker-compose down
Explications :
le fichier docker-compose.yml est composé de deux images
mysql:5.7 https://hub.docker.com/_/mysql (mysql 5.7 debian)
wordpress:php7.1https://hub.docker.com/_/wordpress/ (php7 apache alpine)
On va donc obtenir deux containers différents
Notons les deux volumes, le premier concernant la base de donnée :
volumes:
- ./reactorwp.db.sql:/docker-entrypoint-initdb.d/reactorwp.db.sql
Cette ligne permet de charger un fichier sql pour initialiser la base de données avec des données justement. J'ai au préalable effectué un dump de ma base dans un fichier reactorwp.db.sql que j'ai mis dans le répertoire de travail docker sur mon host local.
Lorsque le container va se lancer, ce script sera appelé et permet donc d'alimenter la base. Ceci peut s'avérer pratique dans le cadre d'un développement pour avoir un jeu de données initiale et commun à tous.
Le second volume concerne le site wordpress :
volumes:
- ./src:/var/www/html
J'ai crée un répertoire "src" sur mon host local qui contient le contenu de mon site web en prod que j'ai copié. Ainsi, en montant ce volume, j'indique au container wordpress d'aller me chercher les fichiers du site web non pas habituellement sur /var/www.html mais sur /src, sur mon host.
Tindin ! En tapant l'url localhost:8000 on arrive sur mon site web
A noter qu'au clic sur un des liens on est redirigé vers reactor.fr, mais ceci est un autre problème.
[/vc_column_text][/vc_column][/vc_row]