Docker – Les commandes utiles

Informations

Ce mémo évolue au fil de mes besoins.
Les ressources sont multiples. Notamment en provenance de la documentation officielle sur https://docs.docker.com/.
Les autres ressources seront affichées au fur et à mesure.

Concept

L’instance d’une image est un container.

Une image est créée avec la commande build et les instructions présentes dans le fichier « Dockerfile »
Elle produit un container lorsqu’elle est exécutée.

Docker information

Connaitre votre configuration Docker :

Utiliser les tags spécifiés sur la page https://hub.docker.com/_/debian/  pour télécharger d’autres images.
Ex avec la version sid :

docker pull debian:sid

Exécuter une image pour vérifier qu’elle fonctionne et rentrer dans le dockerfiles:

docker run -ti debian:latest bash

OU

docker run -ti debian:sid bash
Résultat :
docker run -ti debian:latest bash
 
root@5ad9be283549:/# cat /etc/debian_version 
8.7
root@5ad9be283549:/# exit

OU

docker run -ti debian:sid bash
 
root@1b8e7eea016f:/# cat /etc/debian_version 
9.0
root@1b8e7eea016f:/# exit

Étapes simples pour utiliser un container

  1. Créer le fichier « Dockerfile » avec les spécifications de l’image
  2. Créer une image  : build
  3. Démarrer un container (instance de l’image) : run
  4. Modifier le container
  5. Enregistrer les modifications du container dans une nouvelle image : commit

Dockerfile

Dans un répertoire donné, créer un fichier « Dockerfile ».

Exemple de contenu le plus simple :

FROM debian:jessie

Build

Pour créer une machine basée sur Debian dans un répertoire ./jbnet-test :

mkdir jbnet-test
cd jbnet-test
echo "FROM debian:jessie" > Dockerfile
docker build -t jbnet-test .
Résultat :
Sending build context to Docker daemon 2.048 kB
Step 1/1 : FROM debian:jessie
jessie: Pulling from library/debian
cd0a524342ef: Pull complete 
Digest: sha256:c3f000ba6bbe71906ca249be92bd04dc3f514d2dd905e0c5f226e8035ee55031
Status: Downloaded newer image for debian:jessie
 ---> 054abe38b1e6
Successfully built 054abe38b1e6

Vérifier que les images jbnet-test et debian (sur laquelle jbnet-test est basée) sont disponibles :

docker images -a
Résultat

2
3
REPOSITORY  TAG     IMAGE ID      CREATED      SIZE
debian      jessie  054abe38b1e6  13 days ago  123 MB
jbnet-test  latest  054abe38b1e6  13 days ago  123 MB

Liste du ou des container créés :

docker container ls -a

Version dépréciée :

docker ps -a

Résultat : aucun container puis-qu’aucune exécution n’a été encore lancée.

Run

Lancer en mode interactif un container nommé jbnet-container basé sur l’image jbnet-test et exécuter le bash :

docker run -ti --name jbnet-container jbnet-test bash

Utiliser Ctrl+d pour se déconnecter

docker container ls -a
Résultat :
	
CONTAINER ID  IMAGE       COMMAND  CREATED        STATUS                    PORTS  NAMES
010947f73b0b  jbnet-test  "bash"   5 minutes ago  Exited (0) 5 minutes ago         jbnet-container

Si une nouvelle commande de lancement est exécutée, il y aura 2 container dans la liste.
D’où la nécessité de faire du ménage régulièrement avec les commandes dans le paragraphe « Gérer le container et les images ».
Sinon, le disque risque d’être plein rapidement.

Modifier le contenu du conteneur

Ce sont toutes les commandes que je vais exécuter à l’intérieur, comme un « apt update && apt upgrade ».

Commit

Attention, toutes modifications appliquées dans ces container seront supprimées.
Comme pour git, il faut faire un commit pour appliquer les modifications d’un container à une image.

docker commit 83988038ac5b jbnet-test:v1
docker images -a
 
REPOSITORY  TAG     IMAGE ID      CREATED        SIZE
jbnet-test  v1      ee4010a4d74a  7 seconds ago  184 MB
jbnet-test  latest  040fa6b1044b  5 minutes ago  174 MB
debian      jessie  054abe38b1e6  13 days ago    123 MB

Même exemple en créant une nouvelle image jbnet-test2 :

docker commit e5cbcba3dde6 jbnet-test2:v1
docker images -a
 
REPOSITORY   TAG     IMAGE ID      CREATED        SIZE
jbnet-test2  v1      54ea5a353fc3  3 seconds ago  184 MB
jbnet-test   v1      ee4010a4d74a  2 minutes ago  184 MB
jbnet-test   latest  040fa6b1044b  8 minutes ago  174 MB
debian       jessie  054abe38b1e6  13 days ago    123 MB

Gérer les container et images

 

Liste des images :
docker images -a
Supprimer une image :
docker rmi <image_id>
Supprimer toutes les images :
docker rmi $(docker images -q)
Liste les id des images :
docker images -q
docker container ls
Liste des container actifs :
Liste de tous les container :
docker ps -a
Supprimer un container :
docker rm <container_id>
Supprimer tous les container :
docker rm $(docker ps -a -q)
Appliquer les changements d’un container à une image :
docker commit container_id image_name

 

Réseau

Afficher les réseaux par défaut :
docker network ls
Afficher les paramètres du réseau bridge :
docker network inspect bridge

Par défaut, les container sont sur le même réseau.

Tester l’accès réseau bridge sur un container en exécutant 2 container (debian dans l’exemple) :
docker run -itd --name=networktest debian
docker run -itd --name=networktest2 debian
Puis regarder la section « Containers » dans le résultat :
docker network inspect bridge
Résultat :
[
    {
        "Name": "bridge",
        "Id": "24198ec9e317da0bb806d6e9426a36137b45d706842dc739265691fd2a38eacd",
        "Created": "2017-05-08T09:07:03.192377178+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "33146aa71ea54d10d789130a015f552ad81a768851104b6f411d031719463845": {
                "Name": "networktest2",
                "EndpointID": "c44d5ba85e6df3dcb62fc6fcb75efc9fd714ab1d01175273f5cb7618dffba94d",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "b34b0f3896ba650739922f2d270016600611d57fb3ff99292ca21140ca4f9103": {
                "Name": "networktest",
                "EndpointID": "2ce2243097aa0e8a41e12a71705462821b5699c8426ec702c60c3311c3baeecb",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
Déconnecter le container networktest du réseau bridge :
docker network disconnect bridge networktest
Créer son propre réseau bridge et vérifier sa configuration :
docker network create -d bridge mon_reseau
docker network ls
docker network inspect mon_reseau
Exécuter un container en utilisant ce réseau :
docker run --network=mon_reseau -itd --name=networktest3 debian
docker network inspect mon_reseau
[
    {
        "Name": "mon_reseau",
        "Id": "73702e00f0a7464cd18e470b32309c3b61538f1fc1bc5590b13df6a201631aba",
        "Created": "2017-05-08T15:37:00.162729809+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "eb4c4bd328bfaf7d21474e2fdbda667fa6d305651a7380243a11a1f4f593d037": {
                "Name": "networktest3",
                "EndpointID": "e70574fed4a8a8bc02e505052b9746278091cd7d43f75619699b5e6b114781a5",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Plus d’info : https://docs.docker.com/engine/userguide/networking/#user-defined-networks

 

Migration de dockerfile entre 2 instances dockers :

 

 

 

Lignes de commande et Snippets :

Utiliser Docker c’est maitriser l’ensemble des commandes, pour manipuler les containers Docker. Je vais passer en revue les commandes que propose Docker et les améliorer en créeant un ensemble de Docker snippets, pour simplifier l’exploitation quotidienne de Docker.

Lors du précédent tutorial Débuter avec Docker, j’ai présenter quelques commandes de base, mais nous allons poursuivre cette découverte des commandes CLI de Docker, pour exploiter et maitriser Docker.

Liste des commandes de Docker CLI

Je vais rapidement lister les commandes Docker disponibles, en expliquant leurs rôles (informations issues des manpages Docker)

  • docker attach : Joindre à un conteneur en cours d’exécution
  • docker build : Construire une nouvelle image à partir du code source dans le PATH
  • docker commit : Créer une nouvelle image à partir des changements d’un conteneur
  • docker cp : Copier des fichiers ou des dossiers depuis le PATH d’un conteneur vers le HOSTDIR ou vers STDOUT
  • docker create : Créer un nouveau conteneur
  • docker diff : Inspectez changements sur le système de fichiers d’un conteneur
  • docker events : Obtenir des événements en temps réel depuis le serveur
  • docker exec : Exécuter une commande dans le conteneur en cours d’exécution
  • docker exec -it [container-id] bash : Entrer dans le terminal du CT
  • docker export : Exporter le contenu d’un système de fichiers d’une archive tar vers STDOUT
  • docker history : Afficher l’historique d’une image Docker
  • docker images : Lister des images
  • docker import : Créer une image de système de fichiers vide et y importer le contenu d’une l’archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz), puis éventuellement y ajouter une étiquette (tag)
  • docker info : Afficher l’ensemble des informations système
  • docker inspect : Afficher les informations de bas niveau sur un conteneur ou une image Docker
  • docker kill : Tuer un conteneur en cours d’exécution en utilisant SIGKILL ou un signal spécifié
  • docker load : Chargez une image à partir d’une archive tar sur STDIN
  • docker login : Inscrivez-vous ou connectez-vous à le Docker Register (HUB)
  • docker logout : Déconnexion du Docker Register (HUB)
  • docker logs : Fetch des journaux d’un conteneur
  • docker pause : Mettre en pause tous les processus dans un conteneur
  • docker port : Liste les ports d’un conteneur, ou rechercher les ports “public” NATé vers un PRIVATE_PORT
  • docker ps : Liste de conteneurs
  • docker pull : Récupérer une image ou un repository à partir du Docker HUB
  • docker push : Publier une image ou un repository vers le Docker HUB
  • docker rename : Renommer un conteneur Docker
  • docker restart : Redémarrez un conteneur en cours d’exécution
  • docker rm : Supprimer une ou plusieurs conteneurs
  • docker rmi : Supprimer une ou plusieurs images
  • docker run : Exécuter une commande dans un nouveau conteneur
  • docker save : Enregistrer une image dans une archive tar (streaming vers STDOUT par défaut)
  • docker search : Rechercher des images sur le Docker Hub
  • docker start : Lancer un ou plusieurs conteneurs arrêtés
  • docker stats : Afficher l’utilisation des ressources d’un ou plusieurs conteneurs sous la forme d’un flux
  • docker stop : Arrêtez un conteneur en cours d’exécution en envoyant SIGTERM et SIGKILL après une période de grâce
  • docker tag : Étiqueter une image dans un repository
  • docker top : Afficher les processus en cours d’exécution d’un conteneur
  • docker unpause : Réactiver tous les processus dans un conteneur
  • docker version : Afficher les informations de version Docker
  • docker wait : Bloquer jusqu’à l’arrêt du conteneur, puis imprime son code de sortie

Construction d’une image Docker :

Construir une image Docker
docker build -t itwars/test1 .

En phase de développement d’une image, il arrive très souvent que sa création échoue (erreurs dans le Dockerfile) et on voit aparaitre à l’écran des choses curieuses quand nous lançons les commandes Docker suivantes :

docker images
docker ps -a

Que ce passe-t-il quand la création d’une Image Docker échoue ?

  1. Docker crée des containers à la volée pour créer des images. Si la création se passe bien, à la fin du processus, Docker “nettoie” ses containers de build
  2. Docker crée également des images intermédiaires, pour créer une image finale, quand la création va à son terme, Docker, là encore “nettoie” ses images build

Donc c’est à nous de faire le ménage pour Docker (personnellement, j’ai créé un alias dans mon .bashrc) !

docker rm  $(docker ps -a  -q --filter "status=exited") &&
docker rmi $(docker images -q --filter "dangling=true")
Docker nous indique la liste des containers supprimés, puis la liste des images supprimées :
175887c21be4
cf1f1c3aa329
c0a941a8ddc3
Deleted:dbf3ced60ed89a1b7bacb0eb639bbbeb925253288f732a937bf61a8fb2fa3ced
Deleted:4101ab020eae1c6141f775cb1392f1e12fcd39520d7f637b69e2d766aaf0d2c6

Quelques snippets Docker radicales

  • Stopper tous les containers Docker : docker stop $(docker ps -a -q)
  • Supprimer toutes les Docker images : docker rmi $(docker images -a -q)
  • Stopper et supprimer tous les containers Docker : docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)
  • Stopper et supprimer tous containers Docker + Supprimer toutes les docker images : docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q) && docker rmi $(docker images -a -q)

Monitoring basic des containers Docker

En ce connectant à la machine hôte qui fait fonctionner le daemon Docker, vous disposez de plusieurs solutions, pour monitorer simplement vos containers Docker :

Utilisation de docker stats

On peut afficher les statisques des containers actifs, un peu comme avec la commande “top” :

docker stats $(docker ps -q)

Utilisation des cgroup

Pour tout ce qui touche à la gestion, restriction, informations sur les ressources, Dockers’appuie sur les cgroup du kernel Linux. Dans le script qui suit, j’affiche la mémoire utilisée par chaque containers actifs :

for line in `docker ps | awk '{print $1}' | grep -v CONTAINER`; do docker ps | grep $line | awk '{printf $NF" "}' && echo $(( `cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes` / 1024 / 1024 ))MB ; done

Pour un container en particulier en Mo avec l’utilisation de jq (voir plus bas):

echo $( cat /sys/fs/cgroup/memory/docker/$(docker ps -q --no-trunc=true --filter "name=bind")/memory.usage_in_bytes ) | jq "./1024/1024" | jq "floor"

Utilisation de l’API Docker

Docker quand il démarre, ouvre un socket Unix qui se trouve dans /var/run/docker.sock, on peut lui envoyer des commandes http, pour réaliser une multitude d’actions. Je vous conseille de lire la documentation Docker API.

Ici je récupère l’ensemble des informations concernant les images gérés par ce daemon Docker
echo -e "GET /images/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock |  tail -n +5  | python -m json.tool | less
Dans l’exemple ci-dessous, je demande le flux des statistiques du container ayant pour ID: 3e33d469abac
echo -e "GET /containers/3e33d469abac/stats HTTP/1.0\r\n" | nc -U /var/run/docker.sock
On peut le rendre plus facile à utiliser pour les humains en faisant la même requête à partir du nom du container :
echo -e "GET /containers/"$(docker ps -q --filter "name=bind")"/stats HTTP/1.0\r\n" | nc -U /var/run/docker.sock
En utilisant jq, on peut filter le stream JSON pour avoir un champ particulier, ici par exemple la mémoire utilisée :
echo -e "GET /containers/"$(docker ps -q --filter "name=bind")"/stats HTTP/1.0\r\n" | nc -U /var/run/docker.sock | tail -n +5 | jq -r '.memory_stats.usage'

Facilité la création de Dockerfile avec Vim

Comme je suis un inconditionnel de Vim (en fait NeoVim), je me suis créé un petit template pour ne rien oublier dans mes Dockerfiles. Dans mon fichier de configuration .vimrc, j’ai ajouté la commande suivante, qui insère automatiquement le template lorsque j’édite un fichier Dockerfile vide :

au BufNewFile Dockerfile r ~/mysetup/templates/Dockerfile.txt
Mon fichier de template est le suivant :
#┌───────────────────┐
#│ Pull base image   │
#└───────────────────┘
FROM resin/rpi-raspbian:wheezy
MAINTAINER Vincent RABAH <vincent.rabah@gmail.com>

#┌─────────────────────┐
#│   Install + CLeanup │
#└─────────────────────┘
RUN \
   apt-get update && \
   apt-get -y dist-upgrade && \
   
   apt-get install -y XXX  && \
   
   apt-get clean -y && \
   apt-get autoclean -y && \
   apt-get autoremove -y && \
   rm -rf /tmp/*
   rm -rf /var/lib/{apt,dpkg,cache,log,tmp}/*

#┌────────────────────────────┐
#│   Define working directory │
#└────────────────────────────┘
WORKDIR /data

#┌─────────────────────────────┐
#│   Expose some tcp/udp ports │
#└─────────────────────────────┘
EXPOSE 53
EXPOSE 53/udp


#┌──────────────────────────┐
#│   Define default command │
#└──────────────────────────┘
CMD ["bash"]

 

Conclusion sur les commandes Docker

Voilà, pour ce nouveau tutorial Docker sur l’utilisation et la simplification de l’exploitation au quotidien de Docker.

N’hésitez pas à laisser des commentaires pour partager ! Merci.

 

 

 

Source

Source