--- title: Howto Docker categories: docker --- Docker est une solution qui permet de créer, déployer et gérer des conteneurs Linux. Documentation : # Docker Engine ## Installation Il est conseillé d'utiliser le paquet docker-ce des dépôts du projet Docker : ~~~ # apt install apt-transport-https # echo "deb http://download.docker.com/linux/debian stretch stable" > /etc/apt/sources.list.d/docker.list # curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - # apt update # apt install docker-ce ~~~ > *Note* : Pour Debian 8 : > > ~~~ > # echo "deb http://apt.dockerproject.org/repo debian-jessie main" > /etc/apt/sources.list.d/docker.list > # apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D > # apt update > # apt install docker-engine > ~~~ Sur sa machine de travail, il est utile d'ajouter son utilisateur dans le groupe _docker_ pour pouvoir interagir avec le démon _dockerd_ sans passer root à chaque fois : ~~~ # adduser $USER docker ~~~ ### Configuration #### Changer le chemin de stockage Créer le fichier `/etc/docker/daemon.conf` et y mettre : ~~~ { "graph": "", "storage-driver": "overlay" } ~~~ ### Ansible Le rôle docker-host permet d'installer le docker-engine sur un hôte distant et de l'exposer à l'externe ou non. La documentation concernant l'utilisation du rôle est située dans son répertoire. #### TLS Lorsque le docker-engine est exposé, il est important de le sécuriser avec TLS. Au moment de l'installation, une version altérée de shellpki est copiée dans le répertoire docker/tls. Ensuite, les certificats et la clé sont créés pour le serveur. (`shellpki init`) Pour autoriser des hôtes à se connecter à l'engine, il faut leur créer une clé et un certificat. Pour ce faire, il suffit de lancer le script: ~~~ /home/docker/tls$ ./shellpki create ~~~ Les fichiers seront créés, par défaut, dans le répertoire `/home/docker/tls/files/$CN` ## Utilisation de base Une image Docker contient un système minimal avec un ou plusieurs services. Un conteneur quant à lui est une instance (créée à partir d'une image) en cours d'exécution. ### Gérer les conteneurs #### Lister les conteneurs ~~~ $ docker ps ~~~ Options utiles : ~~~ -a : lister tous les conteneurs -l : lister les conteneurs récemment lancés -q : lister uniquement les ID des conteneurs ~~~ #### Instancier un nouveau conteneur ~~~ $ docker run [commande] ~~~ Options utiles : ~~~ --name="nom" : donner un nom au conteneur -p port_hôte:port_conteneur : rendre un port accessible depuis l'hôte -d : lancer le conteneur en mode 'détaché' -it : lancer le conteneur en mode intéractif avec tty ~~~ #### Démarrer un conteneur existant Un conteneur existant est un conteneur précédemment instancié avec `docker run`. ~~~ $ docker start ~~~ #### Éteindre ou tuer un conteneur ~~~ $ docker stop|kill ~~~ Lorsque le conteneur n'est plus en fonction, il existe toujours et peut être lister à l'aide de la commande `docker ps -a` #### Supprimer un conteneur ~~~ $ docker rm ~~~ #### Exécuter des commandes dans un conteneur en fonction ~~~ $ docker exec ~~~ Options utiles : ~~~ -t : alloue un TTY -i : attache stdin (mode interractif) ~~~ On utilise habituellement la commande suivante pour obtenir un shell dans un conteneur en fonction : ~~~ $ docker exec -ti bash ~~~ #### Visionner les journaux d'un conteneur Il s'agit en fait de la sortie standard et la sortie d'erreur du processus lancé à l'intérieur du conteneur : ~~~ $ docker logs ~~~ Options utiles : ~~~ -f : suivre les logs en direct -t : afficher un timestamp devant chaque ligne ~~~ #### Afficher les informations d'un conteneur ~~~ $ docker inspect ~~~ Cette commande s'applique généralement à n'importe quel objet Docker (conteneur, image, service, réseau…) et donne une liste exhaustive des attributs de l'objet, formaté en JSON. ### Gérer les images #### Lister les images locales ~~~ $ docker image ls ~~~ #### Construire une image Pour construire ou mettre à jour une image : ~~~ $ docker build ~~~ Le répertoire doit contenir un fichier _Dockerfile_ décrivant l'image à construire. Option utiles : ~~~ -t : ajoute un tag à l'image ~~~ #### Ajouter un tag à une image existante ~~~ $ docker tag ~~~ #### Pousser une image sur un dépôt distant ~~~ $ docker push ~~~ Avant de pousser une image, il est nécessaire de lui attribuer le bon _tag_ qui doit contenir l'adresse du dépôt distant. Par exemple pour pousser l'image _foo-image_ sur le dépôt Docker _registry.example.net:5000_ : ~~~ $ docker tag foo-image registry.example.net:5000/foo-image $ docker push registry.example.net:5000/foo-image ~~~ #### Récupérer une image d'un dépôt distant ~~~ $ docker pull ~~~ ### Astuces Éteindre/Tuer/Supprimer tous les conteneurs : ~~~ $ docker stop|kill|rm $(docker ps -aq) ~~~ Supprimer toutes les images : ~~~ $ docker rmi $(docker images -q) ~~~ Démarrer un conteneur avec un shell bash : ~~~ $ docker run -it IMAGE bash ~~~ ### Dépannage #### Problème de connectivité à l'intérieur des conteneurs Solution: Redémarrer le service docker #### Espace insuffisant lors d'un build Solutions: - Vérifier que le "build context" n'est pas trop grand. - Modifier la variable d'environnement DOCKER_TMPDIR . - Créer un fichier .dockerignore pour exclure des fichiers et répertoires du "build context" *Build context: Tout ce qui se trouve à la racine du Dockerfile.* ## Dockerfile Exemple : ~~~ FROM debian:stretch MAINTAINER John Doe ENV DEBIAN_FRONTEND noninteractive RUN (apt-get update && apt-get upgrade -y -q && apt-get dist-upgrade -y -q && apt-get -y -q autoclean && apt-get -y -q autoremove) RUN apt-get install -y -q mariadb-server EXPOSE 3306 CMD ["mysqld"] ~~~ ~~~ # ls Dockerfile # docker build -t mariadb . # docker images REPOSITORY TAG IMAGE ID CREATED SIZE mariadb latest 4bea99cda08c 8 minutes ago 470MB debian stretch 5b712ae16dd7 3 days ago 100MB ~~~ ## Utilisation avancée ### Swarm Swarm permet de mettre en communication plusieurs hôtes Docker afin d'en former un cluster. On pourra ainsi déployer des applications multi-conteneurs sur plusieurs machines. #### Initialiser le cluster ~~~ docker0# docker swarm init ~~~ Joindre les autres machines au cluster créé (il vous suffit généralement de copier-coller la commande retournée par `docker swarm init` : ~~~ docker1# docker swarm join --token ~~~ Par défaut la machine sur laquelle le cluster a été initialisée a le rôle de _manager_, et les suivantes ont le rôle de _worker_. On ne peut déployer de nouveaux services que depuis les _managers_. Les _workers_ se contentent de recevoir les services à rouler. Pour ajouter des machines plus tard, il suffit de générer un nouveau token : ~~~ docker0# docker swarm join-token ~~~ #### Lister les machines du cluster ~~~ # docker node ls ~~~ #### Ajouter des labels à une machine ~~~ # docker node update --label-add = ~~~ Les _labels_ servent notamment à définir des contraintes de placement des services lors de l'utilisation de _docker stack_. ### Compose/stack (docker stack) Docker permet de déployer des infrastructures multi-conteneurs (_stacks_) simplement à l'aide de `docker stack` (anciennement Docker Compose, logiciel tier). Il est très utile dans le cadre de déploiement sur un cluster Swarm. L'infra est à décrire dans un fichier YAML. Déployer (ou mettre à jour à chaud) une nouvelle _stack_ : ~~~ # docker stack deploy -c ~~~ Lister les _stacks_ : ~~~ # docker stack ls ~~~ Lister les _services_, toutes _stacks_ confondues ou pour une _stack_ donnée : ~~~ # docker service ls # docker stack services ~~~ Lister les _tasks_ (replicas) d'une _stack_ ou d'un _service donnée : ~~~ # docker stack ps # docker service ps ~~~ Supprimer une _stack_ : ~~~ # docker stack rm ~~~ ### Réseaux (docker network) Docker permet de gérer différentes topologies de réseaux pour connecter les conteneurs entre eux à l'aide de `docker network`. _drivers_ réseau supportés : - _bridge_ : utilise les bridges Linux ; - _overlay_ : utilisé dans le cas d'un cluster Swarm, permet d'avoir un réseau unique partagé entre tous les hôtes Docker et permet de faire du load-balancing entre les conteneurs (replicas) d'un service ; - _macvlan_ : permet d'assigner directement des adresses IP publiques aux conteneurs, donc aucun NAT n'est fait contrairement aux précédents. Créer un réseau : ~~~ # docker create -d […] ~~~ Lister les réseaux créés : ~~~ # docker network ls ~~~ Informations détaillées sur un réseau : ~~~ # docker network inspect ~~~ ### Volumes (docker volume) ### Fichiers de configuration (docker config) ### Fichiers sensibles (docker secrets)