Le but ici est de prendre en main docker.
Pour cela j'ai installé une Ubuntu version server sous Virtual Box.
Comme indiqué sur https://docs.docker.com/engine/install/ubuntu/, il faut installer une de ces versions de Ubuntu :
Ensuite, j'ai suivi les tutos vidéo dédiés de Xavki que l'on trouve sur sa playlist, cad https://www.youtube.com/playlist?list=PLn6POgpklwWq0iz59-px2z-qjDdZKEvWd
Donc dans une console sous Linux, installer Docker avec
sudo apt-get install docker.io
Lien vers le fichier : cliquez ici
Quand Docker est installé, cette commande donne une liste de commandes possibles
docker
Lien vers le fichier : cliquez ici
On peut valider que l'installation fonctionne correctement avec
sudo docker run hello-world
Lien vers le fichier : cliquez ici
Docket va chercher le conteneur hello-world et va l'installer si nécessaire
Lister les conteneurs se fait avec la commande suivante.
Le 'a' veut dire all, cad que l'on affichera tout.
docker ps -a
Lien vers le fichier : cliquez ici
Commande | Utilité |
---|---|
docker image ls | Lister les images existantes |
docker ps | Lister tous les conteneurs démarrés |
docker ps -a | Lister les conteneurs (a pour all) |
docker run alpine:latest | Lancer ou créer le conteneur alpine |
docker run -di --name alpinetest alpine:latest | Lancer ou créer le conteneur alpine, le nommer alpinetest et le laisser fonctionner (mode Detach Interactive) |
docker run -di --name alpinetest alpine:latest sleep infinity | Comme au dessus mais en plus on conserve un process qui tourne sur le conteneur |
docker run -tid -p 8080:80 --name monnginx nginx:latest | Lancer le conteneur nginx, le nommer monnginx, le laisser fonctionner. Rediriger son port 80 sur le 8080 de notre machine locale |
docker run -tid --name conteneur2 --link conteneur1 alpine | Lancer un conteneur alpine que l'on nomme conteneur2, le linker avec conteneur1 (conteneur2 pourra pinguer conteneur1) |
docker exec -ti monnginx sh | Se connecter au conteneur nommé monnginx avec le shell et le bach |
docker stop <nom du conteneur> | Arrêter un conteneur |
docker container kill $(docker ps -q) | Tuer tous les conteneurs |
docker start <nom du conteneur> | Démarrer un conteneur |
docker restart <nom du conteneur> | Redémarrer un conteneur |
docker rm -f <nom du conteneur> | Supprimer un conteneur |
docker rm $(docker ps -a -q) | Supprimer tous les conteneurs |
docker inspect <nom du conteneur> | Obtenir les infos sur un conteneur |
docker inspect -f "{{.NetworkSettings.IPAddress}}" <nom du conteneur> | Obtenir l'ip d'un conteneur |
docker logs <CONTAINER ID> | Afficher les logs au moment T. Montre STDOUT et STDERR |
docker network ls | Lister les réseaux de Docker |
docker network inspect <nom du réseau> | Informations sur un réseau de Docker |
docker stats <CONTAINER ID> | Afficher les métriques du conteneur avec CPU, mémoire etc |
--no-cache | Demande à ne pas utiliser le cache. Exemple : RUN apk --no-cache vim. Attention toutes les commandes après seront sans le cache |
docker system prune -a | Clean des images non utilisées |
Par défaut le docker hub est installé.
On peut voir les packages dispos via https://hub.docker.com
On peut commencer à jouer en installant un conteneur minimaliste nommé Alpine.
La commande pour le lancer est donnée sur le site.
Si vous listez les conteneurs, vous verrez qu'Alpine s'est lancé et qu'il s'est arrêté tout de suite car il n'avait rien à faire.
docker ps -a
Lien vers le fichier : cliquez ici
On voit que son état est Exited
Si on avait lancé le conteneur Alpine en ajoutant la commande di pour Detach Interractive, alors il aurait continué de fonctionner.
Notez qu'on peut nommer le conteneur, ici avec alpinetest, pour éviter que Docker ne choisisse un nom par défaut.
docker run -di --name alpinetest alpine:latest
Lien vers le fichier : cliquez ici
Là si on refait un docker ps, on voit qu'il est lancé et qu'il tourne
Pour s'y connecter, utiliser docker exec avec les options tid suivi du nom du conteneur et de sh pour avoir le shell et le bach
docker exec -tid alpinetest sh
Lien vers le fichier : cliquez ici
Ensuite si on execute la commande ps, on voit les process qui tournent dans ce conteneur
ps
Lien vers le fichier : cliquez ici
Pour arrêter un conteneur, utilise la commande
docker stop <nom du conteneur>
Lien vers le fichier : cliquez ici
Et pour le supprimer :
Le 'f' permet de forcer, cad qu'il sera arrêté si nécessaire.
docker rm -f <nom du conteneur>
Lien vers le fichier : cliquez ici
Autre exemple où on lance un conteneur nginx en redirigeant son port 80 sur le 8080 de notre machine locale
docker run -tid -p 8080:80 --name monnginx nginx:latest
Lien vers le fichier : cliquez ici
Un docker inspect d'un conteneur permet d'afficher toutes les infos sur ce dernier.
Exemple
docker inspect monnginx
Lien vers le fichier : cliquez ici
Par exemple on voit ici l'ip du conteneur
Une remarque sur docker inspect, c'est qu'on peut filtrer le contenu qui serait du json si j'en crois https://youtu.be/RX96EugUNDk?t=211
Pour récupérer uniquement l'ip, on pourrait pu faire
docker inspect -f "{{.NetworkSettings.IPAddress}}" monnginx
Lien vers le fichier : cliquez ici
Pour lancer un conteneur tout en présentant un volume persistant, on peut utiliser l'option -v (on verra juste après qu'il y a mieux).
Le répertoire local /srv/dockerdata/nginx de notre machine permettra d'héberger les données du répertoire /usr/share/nginx/html du conteneur
Attention du coup comme /srv/dockerdata/nginx est vide, et bien /usr/share/nginx/html aussi, et il faudrait créer un index.php par exemple dans /srv/dockerdata/nginx
docker rm -f monnginx
mkdir -p /srv/dockerdata/nginx
chmod o+rwx /srv/dockerdata/nginx
docker run -tid -p 80:80 -v /srv/dockerdata/nginx/:/usr/share/nginx/html/ --name monnginx nginx:latest
Lien vers le fichier : cliquez ici
De mon côté, dans un premier temps, la commande a généré une erreur du type
docker: Error response from daemon: error while creating mount source path '/srv/dockerdata/nginx': mkdir /srv/dockerdata: read-only file system.
Je l'ai résolu en mettant à jour Docker
Voici l'erreur que j'ai eu
Notez que si vous n'avez pas la commande ps de disponible quand vous être connecté à un conteneur,
vous pouvez l'obtenir en tapant
apt-get update && apt-get install -y procps
Lien vers le fichier : cliquez ici
Maintenant, au lieu d'utiliser l'option v pour utiliser un volume persistant, il y a
docker volume
Lien vers le fichier : cliquez ici
Pour créer un volume de base nommé monvolume, taper
docker volume create monvolume
Lien vers le fichier : cliquez ici
Et pour lancer un conteneur qui l'utilise, taper
docker rm -f monnginx
docker run -tid -p 80:80 --mount source=monvolume,target=/usr/share/nginx/html --name monnginx nginx:latest
Lien vers le fichier : cliquez ici
Maintenant qu'un conteneur utilise ce volume, si on inspecte le volume
docker volume inspect monvolume
Lien vers le fichier : cliquez ici
On voit qu'il pointe localement sur
/var/snap/docker/common/var-lib-docker/volumes/monvolume/_data
Et si on se rend dans ce répertoire, on retrouve les fichiers utilisés par le conteneur
On va utiliser le conteneur alpine, nommé ici alpinetest, pour montrer qu'on peut passer une variable d'environnement en paramètre.
On utilise pour cela l'option --env
Exemple :
docker rm -f alpinetest
docker run -tid --name alpinetest --env MYVAR="pouet" alpine
docker exec -ti alpinetest sh
Lien vers le fichier : cliquez ici
Une fois connecté au conteneur, on voit avec la commande ENV que notre variable MYVAR a bien été passée
On peut aussi passer les différentes variables via un fichier.
On commence pour cela par créer un fichier nommé ici mesvars.txt
cd
nano mesvars.txt
Lien vers le fichier : cliquez ici
On y place nos variables
Puis on peut détruire et relancer le conteneur en lui disant de lire les variables contenues dans le fichier
docker rm -f alpinetest
docker run -tid --name alpinetest --env-file mesvars.txt alpine
docker exec -ti alpinetest sh
Lien vers le fichier : cliquez ici
Si vous voulez sauvegarder l'état d'un conteneur, vous pouvez.
Pour l'exemple ci-dessous on va créer un conteneur nommé myubuntu qui contient la dernière version de Ubuntu.
Ensuite on s'y connecte, on installe nano qui n'y est pas de base et on quitte le conteneur.
docker rm -f myubuntu
docker run -tid --name myubuntu ubuntu:latest
docker exec -ti myubuntu sh
apt-get update
apt-get install nano
exit
Lien vers le fichier : cliquez ici
Relever le container id du conteneur que vous venez de modifier
Sauvegardez le avec la commande docker commit.
Respectez pour cela ce formalisme :
docker commit -m "Mon commentaire" <container id> nom:version
Lien vers le fichier : cliquez ici
Exemple
On peut ensuite afficher les images qui existent avec
docker image ls
Lien vers le fichier : cliquez ici
On retrouve bien l'image qu'on vient de créer
A noter qu'avec la commande docker diff, on peut voir tout ce qui a été modifié sur un conteneur depuis son téléchargement.
Avec notre image nommée test, cela donne donc
docker diff test
Lien vers le fichier : cliquez ici
On peut maintenant lancer un conteneur en utilisant cette image.
Pour cela il faut indiquer son nom et son tag/version
Dans notre exemple cela donne
docker run -tid --name test myubuntu:V1.0
docker exec -ti test sh
Lien vers le fichier : cliquez ici
On voit qu'on s'est bien connecté sur ce conteneur généré à partir d'une image de Ubuntu que l'on avait sauvegardé, image à laquelle on avait ajouté nano, et qui est toujours présent
On peut effacer l'image qu'on vient de créer.
Pour cela il faut supprimer dans un premier temps les conteneurs qu'on a généré avec cette image, puis supprimer l'image.
A noter que dans notre cas on avait nommé le conteneur test, donc les commandes seront :
docker rm -f test
docker image rm -f myubuntu:V1.0
Lien vers le fichier : cliquez ici
Pour effacer une image avec son id, taper
docker image rm <image id>
Lien vers le fichier : cliquez ici
Pour avoir la séquence de commandes qui ont été exécutées pour créer une image, taper
docker history <container id>
Lien vers le fichier : cliquez ici
On peut aussi créer une image avec docker file.
C'est un fichier de configuration qui permet de créer une image avec une séquence de commandes.
Exemple :
cd
nano dockerfile
Lien vers le fichier : cliquez ici
Y coller ce contenu.
Il indique de faire une image avec la dernière ubuntu,
dire que la personne en charge est roberto,
faire un apt-get update,
installe nano et git
faire un clean et effacer des répertoires.
FROM ubuntu:latest
MAINTAINER roberto
RUN apt-get update \
&& apt-get install -y nano git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Lien vers le fichier : cliquez ici
De là on peut créer une image se basant sur le dockerfile qu'on vient de créer avec la commande docker build.
Le point à la fin symbolise le dockerfile
docker build -t image:version .
Lien vers le fichier : cliquez ici
Exemple de build. Vous remarquerez qu'on donne ici un numéro de version à l'image avec ici V1.0 :
docker build -t imagetest:v1.0 .
Lien vers le fichier : cliquez ici
Ce qui donne visuellement
docker image ls confirme que notre image de test est bien créée
Pour indiquer à cette image V1.0 que c'est la dernière version en date (latest), on peut lui ajouter un tag.
docker tag imagetest:v1.0 imagetest:latest
Lien vers le fichier : cliquez ici
On peut sortir l'historique de toutes les commandes qui ont permises de créer une image avec docker history
Exemple :
docker history imagetest:v1.0
Lien vers le fichier : cliquez ici
Il existe d'autres commandes pour dockerfile avec par exemple
Commande | Utilité |
---|---|
env | Variables d'environnement |
expose 80 | Exposition de ports, ici le 80 |
volume | pour créer des volumes |
workdir /app | Définir le répertoire /app comme répertoire de travail, pour un copy par exemple |
copy . /app | pour copier des fichiers présents dans le répertoire courant du host dans le répertoire /app du conteneur |
entrypoint | Définition du processus maître |
Comme indiqué sur cette vidéo de xavki, par défaut les conteneurs tournent avec le compte root de l'hôte.
Donc les process ou les montages fonctionnent en tant que root, et çà ce n'est pas top niveau sécurité.
Pour éviter cela on utilise le remap de user qui prévu de base dans Docker.
Les opérations à réaliser sont reprises dans le script de xavki, cad https://bit.ly/2Bj6GmE.
Dans ce script, deux groupes/comptes sont créés avec un shell nul pour plus de sécurité (/bin/false).
Sur ces 2 comptes, dockremap sera utilisé par docker.
On force l'utilisation d'un uid élevé, en dehors des uid classiques, pour qu'un attaquant n'ai aucune chance d'avoir des droits autre que celui de cet uid élevé.
Ensuite la commande dockremap sera ajouté au fichier subuid et subgid.
A ce niveau la commande dockremap:500000:65536 fait qu'un fichier appartenant à l'utilisateur 6 dans le conteneur appartiendra à l'utilisateur 500006 sur la machine hôte.
N'importe quel utilisateur de la machine hôte qui fait un docker exec sera "root" dans le conteneur via le user dockremap.
Enfin dans la configuration de docker, le fichier /etc/docker/daemon.json sera édité
Docker l'utilise quand il est renseigné.
On va y indiquer qu'il faut utiliser le remap de user par défaut.
La documentation officielle du remap est sur https://docs.docker.com/engine/security/userns-remap/#enable-userns-remap-on-the-daemon.
#!/bin/bash
###############################################################
# AUTEUR: Xavier
#
# DESCRIPTION: création d'un user spécific pour docker
###############################################################
groupadd -g 500000 dockremap &&
groupadd -g 501000 dockremap-user &&
useradd -u 500000 -g dockremap -s /bin/false dockremap &&
useradd -u 501000 -g dockremap-user -s /bin/false dockremap-user
echo "dockremap:500000:65536" >> /etc/subuid &&
echo "dockremap:500000:65536" >>/etc/subgid
echo "
{
\"userns-remap\": \"default\"
}
" > /etc/docker/daemon.json
systemctl daemon-reload && systemctl restart docker
Lien vers le fichier : cliquez ici
Article(s) suivant(s)
Article(s) en relation(s)