449 lines
10 KiB
Markdown
449 lines
10 KiB
Markdown
---
|
|
title: Howto Docker
|
|
categories: docker
|
|
---
|
|
|
|
Docker est une solution qui permet de créer, déployer et gérer des conteneurs
|
|
Linux.
|
|
|
|
Documentation : <https://docs.docker.com/>
|
|
|
|
# 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": "<VOTRE_CHEMIN>",
|
|
"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 <image> [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 <ID ou nom du conteneur>
|
|
~~~
|
|
|
|
#### Éteindre ou tuer un conteneur
|
|
|
|
~~~
|
|
$ docker stop|kill <ID ou nom du conteneur>
|
|
~~~
|
|
|
|
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 <ID ou nom du conteneur>
|
|
~~~
|
|
|
|
#### Exécuter des commandes dans un conteneur en fonction
|
|
|
|
~~~
|
|
$ docker exec <ID ou nom du conteneur> <commande>
|
|
~~~
|
|
|
|
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 <conteneur> 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 <ID ou nom du conteneur>
|
|
~~~
|
|
|
|
Options utiles :
|
|
|
|
~~~
|
|
-f : suivre les logs en direct
|
|
-t : afficher un timestamp devant chaque ligne
|
|
~~~
|
|
|
|
#### Afficher les informations d'un conteneur
|
|
|
|
~~~
|
|
$ docker inspect <ID ou nom>
|
|
~~~
|
|
|
|
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 <repertoire>
|
|
~~~
|
|
|
|
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 <tag actuel> <nouveau tag>
|
|
~~~
|
|
|
|
#### Pousser une image sur un dépôt distant
|
|
|
|
~~~
|
|
$ docker push <image>
|
|
~~~
|
|
|
|
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 <image>
|
|
~~~
|
|
|
|
### 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 existant avec un shell bash (pour des fins de debug par exemple) :
|
|
|
|
~~~
|
|
$ 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 <jdoe@example.com>
|
|
|
|
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 <token> <IP du premier node>
|
|
~~~
|
|
|
|
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 <manager|worker>
|
|
~~~
|
|
|
|
#### Lister les machines du cluster
|
|
|
|
~~~
|
|
# docker node ls
|
|
~~~
|
|
|
|
#### Ajouter des labels à une machine
|
|
|
|
~~~
|
|
# docker node update --label-add <clé>=<valeur> <machine>
|
|
~~~
|
|
|
|
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 <stack_name.yml> <stack name>
|
|
~~~
|
|
|
|
Lister les _stacks_ :
|
|
|
|
~~~
|
|
# docker stack ls
|
|
~~~
|
|
|
|
Lister les _services_, toutes _stacks_ confondues ou pour une _stack_ donnée :
|
|
|
|
~~~
|
|
# docker service ls
|
|
# docker stack services <stack name>
|
|
~~~
|
|
|
|
Lister les _tasks_ (replicas) d'une _stack_ ou d'un _service donnée :
|
|
|
|
~~~
|
|
# docker stack ps <stack name>
|
|
# docker service ps <service name>
|
|
~~~
|
|
|
|
Supprimer une _stack_ :
|
|
|
|
~~~
|
|
# docker stack rm <stack name>
|
|
~~~
|
|
|
|
### 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 <driver> […] <network name>
|
|
~~~
|
|
|
|
Lister les réseaux créés :
|
|
|
|
~~~
|
|
# docker network ls
|
|
~~~
|
|
|
|
Informations détaillées sur un réseau :
|
|
|
|
~~~
|
|
# docker network inspect <network name>
|
|
~~~
|
|
|
|
### Volumes (docker volume)
|
|
### Fichiers de configuration (docker config)
|
|
### Fichiers sensibles (docker secrets)
|
|
|
|
## FAQ
|
|
|
|
> Lors d'un redéploiement d'une stack Docker (docker stack deploy), les services ne sont pas redémarrer avec la nouvelle image
|
|
|
|
Vérifier que le tag _latest_ est bien précisé dans le nom de l'image dans le _docker-stack.yml_ :
|
|
|
|
~~~
|
|
image: registrydocker.example.com:5000/foo:latest
|
|
~~~
|
|
|
|
> Est-il possible de ne faire écouter un service d'une stack que sur une interface précise de la machine hôte (par exemple sur un LAN privé) ?
|
|
|
|
Non, Docker ne supporte pas ça.
|
|
Il faut bloquer le port en question dans le pare-feu, dans la chaîne iptables DOCKER-USER.
|
|
|
|
Pour bloquer l'accès au _registry_ Docker depuis l'extérieur par exemple :
|
|
|
|
~~~
|
|
# iptables -A DOCKER-USER -i eth0 -p tcp -m tcp --dport 5000 -j DROP
|
|
~~~
|
|
|
|
> Au sein des conteneurs, un `getent <service>` ou `getent tasks.<service>` ne retourne pas l'adresse IP du service alors que celui-ci est bien lancé.
|
|
|
|
Stopper le conteneur du service avec un `docker stop <conteneur du service>`. Docker stack devrait le relancer automatiquement.
|