Archives de catégorie : Docker

Docker – changer les ip par défaut

Docker c’est bien mais il se met bien à l’ aise sur la machine où il se situe. J’entends par là qu’il se créé son interface docker0 avec son range d’ip 172.17.0.0. Mais parfois on veut un peu plus contrôler le scope d’ip de docker car il peut entrer en concurrence avec une ip d’un réseau interne.

Vous pouvez retrouver le bridge docker0 de différente manière :

route -n
docker network inspect
iptables -L

Mais docker est prévoyant et il est tout à fait possbile de paramétrer les ip que docker utilise pour son bridge docker0.

Pour celà c’est très simple, il suffit d’éditer ou créer un fichier /etc/docker/daemon.json de la manière suivante :

{
"bip": "192.168.1.1/24"
}

Dans notre cas docker0 utilisera un /24 sur 192.168.x.x.

Une fois ce fichier modifié, lancez :

systemctl daemon-reload
service docker restart

Vérifiez ensuite le changement du scope de docker0 :

ip a

Si l’interface docker0 est monté deux fois vous pouvez supprimer celle inactive grâce à cette commande :

ip link del docker0

[Docker] : Comment prendre en compte un proxy pour puller/pusher et comment le passer dans un conteneur ?

 

Docker, c’est un sujet que j’ai l’occasion de creuser un peu en ce moment. Les pros de docker comme les devops savent faire cela les doigts dans le nez mais pour les débutants c’est un petit moment de recherche.

Lorsque l’on parle de docker et de proxy, deux questions reviennent souvent :

  • Comment prendre en compte un proxy sur la machine host pour puller/pusher des images ?
  • Comment faire pour que mon conteneur utilise un proxy ?

1. Utilisation d’un proxy sur la machine host de docker

Pour prendre en compte un proxy et éviter d’y revenir, il est nécessaire d’éditer la configuration de docker. Ainsi, comme si vous paramétiez votre proxy pour une utilisation par apt, vous allez vous rendre dans /etc/systemd/system/docker.service.d/ et créer un fichier de conf.

Par exemple, nous allons créer un fichier intitulé https-proxy.conf. Et nous allons ajouter dedans l’adresse de notre proxy en variable d’environnement (pour le service docker donc) :

[Service]
Environment="HTTPS_PROXY=http://monproxy:sonport"

Une fois ceci réalisé, le premier réflexe est de redémarrer le service docker… C’est pas faux mais dans notre cas on vient de modifier la conf de docker au niveau de systemd. donc il faut tout d’abord redémarrer le démond :

systemctl daemon-reload
service docker restart

Et voilà pour la première partie, vous pouvez utiliser votre proxy avec docker pour faire des pull et des push vers votre repository (dockerhub ou autre). Mais attention si vous être sur votre laptop, il se peut que vous ayez besoin de switcher (avec ou sans proxy), je vous invite donc à faire les fonctions qui vont bien ou alias pour vous faciliter la vie. L’idée c’est d’utiliser :

echo "Environment=\"HTTP_PROXY=http://monproxy:monport\"" | 
sudo tee --append /etc/systemd/system/docker.service.d/http-proxy.conf

2. Passer la conf de votre proxy dans un conteneur

C’est indispensable si vous êtes derrière un proxy sinon pas d’update ou d’installation possible sur le conteneur.

Et là docker est tout simplement génial car il permet de passer des variables d’environnement dans le conteneur à son lancement (son run). Remarque : si cela est plus durable vous pouvez faire cela directement dans votre Dockerfile.

Comment passer votre variable de proxy ? comme ceci :

docker run -tid -e http_proxy="http://monproxymonport" 
--name nom_conteneur nom_image

Et le tour est joué. Vous pouvez aussi passer un serveur dns avec –dns= »monipdns ».

Si vous voulez que votre image contienne toujours cette variable, vous devez la builder avec cette variable. Là encore c’est pas compliqué à ajouter dans le dockerfile :

ENV http_proxy="http://monproxymonport"

Vous pouvez consulter ce bon article sur les variables docker.

[Docker] : mettre à jour toutes les images en une seule ligne de commande

Potentiellement, un serveur docker peut faire appel à de nombreuses images. Il arrive un moment où on peut être intéressé pour faire une mise à jour globale de ces images. Pourquoi pas automatiser cela si les images ne sont pas risquées en terme de modification ?

Cette commande est donc à lancer avec des pincettes et lorsque l’on a bien conscience de ce que l’on fait (ça vaut toujours le coup de le rappeler).

docker images | grep -v REPOSITORY | awk '{print $1}' | xargs -L1 docker pull

Donc :

  • on liste les images
  • on vire la première ligne avec un grep
  • on garde la première colonne avec un awk
  • on utilise xargs pour passer un docker pull sur les noms des images.vignette_docker

[docker] : copier un fichier de votre host vers un container avec tar

Docker est quand même très pratique. Les commandes sont pensées avec simplicité.  Là par exemple nous allons voir comment très simplement passer un fichier où le contenu d’un tar directement du serveur qui porte docker vers le conteneur.

En fait c’est ultra simple :

docker cp /chemin/source +nom_conteneur+:/conteneur/chemin/

C’est donc comme si on passait un bon vieux cp c’est fou ça ?

Et l’inverse est vrai :

docker cp :/conteneur/chemin/ /chemin/source

Alors avec un tar comment faire ?

tar -cv * | docker exec -i +conteneur+ tar x -C /var/www>

Donc :

  • tar -cv : on créé une archive en mode verbose
  • on exécute un tar dans le conteneur
  • on extrait l’archive (x)

Et vous, comment faites vous pour faire ce genre de copie de fichier ?

[Docker] : comment créer une image à partir d’un conteneur et la pousser ?

Comme dirait l’autre ça va finir par rentrer, nom d’une pipe. Mais cela fait plusieurs fois que je fais cette manip et comme écrire un article m’aide à retenir les choses je vais vous faire partager une manip docker.

Le but aujourd’hui c’est de savoir comment créer une image à partir d’un conteneur existant que vous avez ajustez à votre guise. Dans mon cas c’est un conteneur qui permet d’avoir une debian stretch avec systemd, openssh, sudo et vim. La grosse subtilité c’est d’avoir systemd mais je ne vais pas vous détailler cela aujourd’hui.

docker-image-conteneur

Démo en vidéo :

La première chose à faire c’est de connaître l’id de son conteneur avec un bon docker ps :

└─ $ ▶ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bbb5c547002c debian-systemd "/lib/systemd/systemd" 31 minutes ago Up 31 minutes competent_vaughan

Ensuite il faut commiter tout ceci dans une nouvelle image avec un docker commit (à partir de l’ID de l’image) :

└─ $ ▶ docker commit -m "image stretch + systemd + openssh" bbb5c547002c priximmo/stretch-systemd-ssh

Sivous faite un docker image ls, vous pouvez déjà voir votre image sur votre pc en local.

Puis si vous le souhaitez vous pouvez pousser ceci sur dockerhub ou un autre repository.

docker login
docker push priximmo/stretch-systemd-ssh

Et voilà vous disposez de votre image en local et sur votre dépôt.

Retrouvez l’image en question sur docker hub.

[Docker][Ansible] : comment se créer un mini datacenter de test sans VM ? (parc de conteneurs)

Datacenter, le terme est bien prétencieux car il ne s’agit ni de machines physiques, ni de vm mais de simples conteneurs docker. L’idée est très simple et je sais que certains d’entre vous ont besoin de ce genre de script : comment créer facilement, à la volée, une série de conteneurs identiques pour reproduire des actions à la manière d’un centre serveur (orchestration, scheduler…).

Attention, ce qui est fait dans ce script et l’image utilisée (que j’ai adapté pour l’occasion) ne prennent pas en compte la sécurité nécessaire pour faire de la production. L’idée est de créer ce mini pool de conteneurs et de le supprimer une fois les manipulations réalisées. En moins de 5 minutes vous avez autant de machine que vous voulez sous la main et dans le même réseau.

Le besoin ? faire des tests sur un parc de « machines »

Pourquoi moins sécurisé que d’autres ? Par exemple, je permets de faire du ssh sur le user root depuis l’extérieur du conteneur. Je mets en place un mot de passe unique pour root et le user. Tout cela pour faire comme si il s’agissait d’une vm ou une machine physique donc de ne plus passer par un « docker exec » pour accéder à root.

Pourquoi faire ? des tests. Dans mon cas, je vais m’en servir pour me faire la main sur Ansible et runner des playbooks sur tout le parc ou sur une partie.

L’intérêt comme je l’ai déjà dit :

  • pouvoir casser et repartir avec des machines vierges en 2 minutes
  • pouvoir en lancer une bonne dizaine (voir plusieurs) sur mon pc
  • avoir un réseau facilement opérationnel
  • switcher d’OS ou d’image à volonté
  • cela reste léger car il n’y a pas de noyau embarqué

Dans le détail du conteneur

De base, j’utilise une image que j’ai créé et mis à disposition sur mon compte dockerhub (priximmo/debian-sshd). Il s’agit d’une image debian officielle à laquelle j’ai ajouté un openssh-server et dont j’ai permis la connexion en ssh sur le user root. C’est ce point qui aura été le plus difficile car je ne voyais pas pourquoi je ne pouvais pas passer root sur les conteneurs docker. Il suffit d’ouvrir /etc/ssh/sshd_config et de passer la clause PermitRootLogin à « yes ».

Le mot de passe root est aussi configuré mais je vous invite à le modifier à l’aide d’une commande docker (en lançant chgpasswd). Mais comme le but est de ne pas garder les conteneurs en fonction hors des phases de test c’est moins grave.

Le script ? c’est du shell et il est dispo sur le github

Quatre options :

  • –proxy : utilisation perso mais à vous de l’adapter vous pouvez avec prévoir d’ajouter votre proxy dans http-proxy.conf
  • –create : par défaut il créé 2 conteneurs mais vous pouvez en mettre autant que vous souhaitez
  • — drop : pour nettoyer les conteneurs créés
  • –infos : donne les ips,users des conteneurs

Dans le create, vous pouvez voir que l’on créé un user du même nom que votre utilisateur courant et on pousse votre clé publique dans le conteneur. On installe aussi python-minimal et sudo, nécessaires pour faire du ansible dans mon cas. Et à la fin de la création j’utilise docker inspect pour récupérer les ip des conteneurs pour donner un petit récapitulatif.

#!/bin/bash

###############################################################
#  TITRE: parc de conteneurs
#
#  AUTEUR:   Xavier
#  VERSION: 1.1
#  CREATION:  17/09/2018
#  MODIFIE: 
#
#  DESCRIPTION: 
#   mot de passe obtenu par :
#          perl -e 'print crypt("password", "salt"),"\n"'
###############################################################

USERNAME=$(id -nu)

if [ "$1" == "--proxy" ];then
	
	if [ -f /etc/systemd/system/docker.service.d/http-proxy.conf ];then
		sudo rm -f /etc/systemd/system/docker.service.d/http-proxy.conf
		sudo service docker restart
	fi 

fi


if [ "$1" == "--create" ];then
	
	nbserv=$2
	[ "$nbserv" == "" ] && nbserv=2
	
	# rapatriement de l'image si elle n'exsiste pas
	echo "Installation de l'image "
	docker pull priximmo/stretch-systemd-ssh:v3.1

	# création des conteneurs
	echo "Création : ${nbserv} conteneurs..."

	# détermination de l'id mini
  id_first=$(docker ps -a --format "{{ .Names }}" |grep "oki-vmparc" | sed s/".*-vmparc"//g  | sort -nr | head -1)
	id_min=$(($id_first+1))

	#détermination de l'id max
	id_max=$(($nbserv + $id_min - 1))

	for i in $( seq $id_min $id_max );do
		echo ""
		echo "=> conteneur ${USERNAME}-vmparc${i}"
    docker run -tid -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name ${USERNAME}-vmparc${i} priximmo/stretch-systemd-ssh:v3.1
		echo "    => création de l'utilisateur ${USERNAME}"
		docker exec -ti ${USERNAME}-vmparc${i} /bin/bash -c "useradd -m -p sa3tHJ3/KuYvI ${USERNAME}"
		echo "Installation de votre clé publique ${HOME}/.ssh/id_rsa.pub"
		docker exec -ti ${USERNAME}-vmparc${i} /bin/bash -c "mkdir  ${HOME}/.ssh && chmod 700 ${HOME}/.ssh && chown ${USERNAME}:${USERNAME} $HOME/.ssh"
		docker cp ${HOME}/.ssh/id_rsa.pub ${USERNAME}-vmparc${i}:${HOME}/.ssh/authorized_keys
		docker exec -ti ${USERNAME}-vmparc${i} /bin/bash -c "chmod 600 ${HOME}/.ssh/authorized_keys && chown ${USERNAME}:${USERNAME} ${HOME}/.ssh/authorized_keys"
		docker exec -ti ${USERNAME}-vmparc${i} /bin/bash -c "echo '${USERNAME}   ALL=(ALL) NOPASSWD: ALL'>>/etc/sudoers"
		docker exec -ti ${USERNAME}-vmparc${i} /bin/bash -c "service ssh start"
	done
	echo ""
	echo "Liste des ip  attribuées :"
	for i in $( seq $id_min $id_max );do

	infos_conteneur=$(docker inspect -f '   => {{.Name}} - {{.NetworkSettings.IPAddress }}' ${USERNAME}-vmparc${i})
	echo "${infos_conteneur} - Utilisteur : ${USERNAME} / mdp:password"
	
	done

fi

if [ "$1" == "--drop" ];then

	for i in $(docker ps -a --format "{{ .Names }}" |grep "${USERNAME}-vmparc" );do
		echo "     --Arrêt de ${i}..."
		docker stop $i
		echo "     --Suppression de ${i}..."
		docker rm $i
		done

fi

if [ "$1" == "--infos" ]; then

	for i in $(docker ps -a --format "{{ .Names }}" |grep "vmparc" );do
		infos_conteneur=$(docker inspect -f '   => {{.Name}} - {{.NetworkSettings.IPAddress }}' ${i})
		echo "${infos_conteneur} - Utilisteur : ${USERNAME} / mdp:password"
	done

fi

if [ "$1" == "--start" ];then
	
	sudo /etc/init.d/docker start

	
        for i in $(docker ps -a --format "{{ .Names }}" |grep "vmparc" );do
                echo "     --Démarrage de ${i}..."
                docker start $i
                #echo "     --Démarrage de sshd sur ${i}"
                #docker exec -ti ${i} /bin/bash -c "sudo service ssh start"
        done
echo ""
echo "#### Récap des infos ####"
echo ""


	for i in $(docker ps -a --format "{{ .Names }}" |grep "${USERNAME}-vmparc" );do
                infos_conteneur=$(docker inspect -f '   => {{.Name}} - {{.NetworkSettings.IPAddress }}' ${i})
                echo "${infos_conteneur} - Utilisteur : ${USERNAME} / mdp:password"
        done


fi

[Docker] : supprimer les images non taggées

Ah cela m’est arrivé plusieurs fois, on créé des images sans faire gaffe. Au bout d’un moment ça devient le boxon et il est temps de faire le ménage. Mais lorsque l’on fait le ménage dans les images docker, on se retrouve avec une tripoté d’images sans tag. Que faire ? les supprimer car c’est moche et ça ne sert à rien.

Mais comment supprimer des images qui ne sont pas taggées ?

Pas si compliqué :

docker rmi $(docker images -f "dangling=true" -q)

Donc :

  • docker images : on liste les images en filtrant sur les « non-taggées » soit dangling = true
  • docker rmi : on applique une suppression d’image par l’ID
arrows box business chalk

Photo by Pixabay on Pexels.com

[Docker] : Swarm – lister les services et les nodes en 1 ligne

Là c’est pas bien compliqué. Mais bon comme j’en ai marre de commencer par chercher les ID des service pour pouvoir faire un docker ps dessus, je me suis créé un alias qui fait le taff.

Vous êtes pas obligé d’ajouter ça dans votre bashrc mais je vous le recommande pour plus de faciliter.

En gros on combine un docker service ls et un docker service ps :

alias dserv='for id in $(docker service ls --format "{{.ID}}");do docker service ps $id;done'

Je pense que vous devez avoir aussi vos petites astuces de ce genre. N’hésitez pas à les laisser en commentaire.

[Mysql] [Docker] : Sauvegarde mysql pour conteneurs Docker

Je publie ce code car je le trouve bien pratique. Le raisonnement me semble logique et j’ai apprécié le rédiger alors cela peut surement vous inspirer. Si vous êtes curieux, vous pouvez retrouver mes commandes docker sur cette page.

Alors je vous dresse les points essentiels du code car le mien fait intègre aussi postgres et mariadb (identique à mysql exactement).

Premièrement on liste les ID, les noms et les images des conteneurs. Comme on log tout cela cela permet de recréer aussi très rapidement un conteneur Docker identique. Et puis cela permet aussi de tester le dump facilement.

docker ps --format "{{ .ID }}|\
{{ .Names }}|\
{{.Image}}" |\
while IFS="|" read var1 var2 var3;\
do

Ensuite on nettoie le nom du conteneur car Docker ajoute un sha pour le rendre unique et c’est pas très causant. et on peut se créer un répertoire local de backup (mais cela peut aussi être un point de montage.

var2=$(echo $var2 | sed -e 's/\(.*\)\..*$//g')
BACKUP_DIR="/dir_export/"
DUMP_DIR=${BACKUP_DIR}${var2}/
DUMP=BACKUP_DIR="/export/sgbd-dumps/"
DATEDUMP=$(date +%Y-%m-%d)
DUMP=${DATEDUMP}.${var2}

et on commence par logger quelques infos :

echo "---- ${DATEDUMP} /  Dump du container ${var2}    -----" > ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-name >>"$var2 >> ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-image >>"$var3 >> ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-dump >>"${DUMP_DIR} >> ${DUMP_DIR}${DUMP}.log

Et c’est parti on lance la sauvegarde mysqldump en lancant un docker exec sur l’ID du conteneur recueilli.

echo ""
echo "---- ${DATEDUMP} /  Dump du container ${var2}    -----"
docker exec ${var1} mysqldump -u  --password= --all-databases  > ${DUMP_DIR}${DUMP}.sql

Alors on aurait pu ajouter un gzip directement dessus et ne sauvegarder qu’une seule base. Personnellement on ne sait on part sur un truc complet. Et pui savant de gzippé on vérifie le boulot 😉

Alors comment on fait pour tester notre dump ???

C’est simple. On créé un conteneur identique et ensuite on importe notre dump dedans. N’ayez pas peur c’est hyper facile.

docker run --name testsgbd -e MYSQL_ROOT_PASSWORD= -tid $var3 | grep -vi warning
sleep 40

On voit que $var3 nous permet de lancer la même image que dans le conteneur sauvegardé. Et on met tout cela en pause durant 40 secondes. C’est beaucoup mais on s’assure que le conteneur est bien lancé (ou au moins à eu le temps).

Et la on importe mais pas n’importe comment. On fait un test (un if) sur la commande d’import mysql lancée à travers docker. Si aucun message d’erreur on à ainsi un dump conforme sinon KO. Et si OK on gzip

if [ -n "$(docker exec -i testsgbd mysql -uroot -ppassRoot <${DUMP_DIR}${DUMP}.sql 2>&1 | grep -vi Warning )" ];then
                       echo " >>> ${DATEDUMP} : [Error]" >> ${DUMP_DIR}${DUMP}.log
                      echo "[Pb import]"
                        rm -f ${DUMP_DIR}${DUMP}
                else
                        echo " >>> ${DATEDUMP} : [OK]" >> ${DUMP_DIR}${DUMP}.log
                        echo "[Import OK]"
                        echo "Gzip..."
                        gzip ${DUMP_DIR}${DUMP}*.sql
                        echo "fin"
                fi

et surtout on oublie pas de nettoyer en supprimant l’image créée.

docker rm -f testsgbd

Alors c’est pas simple tout cela ?

Je trouve que si et que ça mérite d’être partagé, c’est pour cela que cela valait bien un article.