Outils pour utilisateurs

Outils du site


informatique:docker

Ceci est une ancienne révision du document !


Docker

Utilisateurs et permissions

:!: A COMPLETER

Pour lancer un conteneur avec un autre utilisateur :

docker run -d --name MyC1 -u benoit httpd

Création d'image sous Docker

Docker commit

Permet de créer des images à partir d'un conteneur. Il est recommandé de l'utiliser que dans des cas spécifiques. Par exemple dans les cas suivants :

  • Snapshot ponctuel du conteneur
  • Faire un fix rapide dans le conteneur mais non durable
  • Tester et debugguer

Pour des modifications plus durable, il vaut mieux s'appuyer sur un Dockerfile.

Pour commencer démarrer un conteneur debian qui lance la commande sleep infinity :

docker run -d --name c1 debian sleep infinity

On peut se connecter au conteneur, y apporter les modifications que l'on souhaite et le quitter, par exemple :

docker exec -ti c1 bash
echo "toto" > /var/lib/toto.txt
...
exit

On peut donc créer une image de l'état du conteneur ainsi :

docker commit c1 myimage-c1:v1.0

Avec la commande…

docker image ls

…On peut voir

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
myimage-c1   v1.0      0b486f336e68   6 minutes ago    117MB
debian       latest    0ce03c8a15ec   42 minutes ago   117MB

On peut de nouveau créer un nouveau conteneur à partir de cette image ainsi :

docker run -d --name c2 myimage-c1:v1.0

En listant les processus Docker en fonctionnement…

docker ps

…On constate que les 2 conteneurs sont en fonctionnement avec la commande sleep infinity :

CONTAINER ID   IMAGE             COMMAND            CREATED              STATUS              PORTS     NAMES
a9b8064f9bcb   myimage-c1:v1.0   "sleep infinity"   About a minute ago   Up About a minute             c2
1600fa08b0a1   debian            "sleep infinity"   12 minutes ago       Up 12 minutes                 c1

:!: Pourtant le conteneur c2 n'a pas été lancé avec la commande sleep infinity. Ceci montre que la création de l'image prend en compte les processus actifs. Ces mêmes processus seront actif lorsqu'un conteneur est créé à partir de l'image “commitée”.

On peut ajouter d'autres options pour créer l'image, comme un commentaire et ajouter l'auteur de l'image :

docker commit --message "mes commentaires" --author "Benoit" c1 myimage-c1:v1.1

On peut retrouver ces informations ainsi dans l'image :

docker inspect -f "{{.Author}} {{.Comment}}" myimage-c1:v1.1

On peut lister l'historique des commit d'une image ainsi :

docker history myimage-c1:v1.1

Exemple de résultat :

IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
a1b6eff85cc8   8 minutes ago       sleep infinity                                  76B       mes commentaires
0ce03c8a15ec   About an hour ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      About an hour ago   /bin/sh -c #(nop) ADD file:39d17d28c5de0bd62…   117MB

On peut ajouter des modifications/instructions à lancer pour notre image. Par exemple on ajoute un variable d'environnement MYVAR=Benoit :

docker commit --change "ENV MYVAR=Benoit" c1 myimage-c1:v1.2

Lorsque l'on créé un conteneur à partir de cette nouvelle image on constate que la variable est bien active :

docker run -d --name c3 myimage-c1:v1.2
docker exec c3 env

Résultat :

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=1f8770a8bb5b
MYVAR=Benoit
HOME=/root

Dockerfile

L'objectif est de créer une image Docker qui permettra de faire fonctionner un conteneur avec notre application.

L'idée est de partir sur un système de base, d'y inclure les prérequis de notre application, installer notre application et les commandes pour exécuter notre application au lancement du conteneur.

Bonnes pratiques

Les bonnes pratiques pour créer une image sont les suivantes :

  • Utiliser une image de base fiable et légère
    • Vérifier la source de la registry sur Docker Hub par exemple.
    • Eviter d'utiliser une image:latest.
    • Spécifier le TAG de l'image. Cela permet d'éviter d'être surpris par des bug de version.
    • Ou bien utiliser la référence digest pour cibler la version à déployer
  • Garder une image légère
    • Grouper les commandes d'installation et de purge dans une seule instruction RUN pour éviter de surcharger la taille de l'image
    • Supprimer les caches d'installation.
    • Exemple: apt update -qq && apt install -qq -y apache2 && apt clean && rm -rf /var/lib/apt/lists/*.
    • Eviter d'installer des outils de debug comme telnet, tcpdump.
    • Supprimer les paquets non requis
    • Faire un build multi-stage
  • Créer un dossier dédié pour y préparer les fichiers, app à copier dans notre image
    • Utiliser une fichier .dockerignore pour exclure des fichiers de la copie. Exclure par exemple le Dockerfile.
    • Utiliser l'instruction COPY plutôt que ADD.
    • Utiliser ADD uniquement pour télécharger des contenus externes au dossier dédié
    • Attention de ne pas laisser des fichiers confidentiels
    • Eviter par exemple : COPY . .
  • Bien penser l'environnement de fonctionnement de l'application dans le conteneur
    • Créer un utilisateur par défaut pour éviter de faire tourner l'application en tant que root
    • Penser à basculer sur l'utilisateur non root au lancement de l'application du conteneur.
    • Penser à utiliser des variables d'environnement ENV
    • Penser à définir le répertoire de travail par défaut du conteneur WORKDIR
  • Versionner les éléments installés
  • Eviter de créer une image contenant plusieurs brique applicatives. * Exemple : Application + Base de données * Identifier le “registry” pour pousser l'image créée**

Création du Dockerfile

En exemple, Nous allons simplement créer une image contenant un serveur Web apache basé sur une image Debian.

Pour commencer, créer un dossier de travail et aller dedans :

mkdir myapp
cd myapp

Créer dans le dossier créer un fichier '.dockerignore' et on ajouter la ligne suivante pour ignorer le fichier Dockerfile :

Dockerfile

On va créer un dossier app et y mettre une page html.

mkdir app
echo "Apache dans conteneur" > app/index.html

Créer le Dockerfile suivant :

vim Dockerfile

Contenu en exemple :

# Source pour l'image de base
FROM debian:bullseye-slim
# On peut également cibler l'image ainsi avec le Digest SHA256
#FROM debian@sha256:9af4db29e828a4d08c7819f9e0972e2dbdac575e73c6438630c83bd79f49c8aa

# Labels pour identifier notre image
LABEL version=1.0
LABEL auteur=Benoit

# On défini quelque variable d'environnement au sein du conteneur
ENV APP_ENV="PreProd"
ENV APP_NAME="MyWEB"
ENV APP_VER="1.0"

# On définir des variable à utilsier dans le Dockerfile
ARG APP_USER="benoit"

# Création de l'utilisateur
RUN adduser ${APP_USER}

# Intallation des paquetages requis
# A noter qu'on lance l'installation et le nettoyage d'APT pour éviter de surcharger notre image par des Layers
RUN apt update && apt install -y apache2 && apt clean && rm -rf /var/lib/apt/lists/*
# On execute les prerequis pour lancer notre serveur Apache2
RUN mkdir -p /var/run/apache2 && . /etc/apache2/envvars

# On lance apache2
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

# Répertoire de travail de l'App
WORKDIR /var/www/html

# Ci-dessous la directive pour faire tourner l'application autre que root
#USER ${APP_USER}

# On copie les fichiers locaux sur le WORKDIR du conteneur
COPY app/* .
# Exemple ci-dessous en spécifiant les permissions
#COPY --chown=${APP_USER} app/* .

# On expose le port 80
EXPOSE 80

Lancer le build de l'image

docker build -t webapp:v1 .

Pour lancer un conteneur à partir de notre image :

docker run -d --name c1 -p 8080:80 webapp:v1

Exemple de Dockerfile multi-stages

Le build multistage permet de reprendre des éléments d'une autre image pour créer l'image.

# Build 0
FROM debian:latest
# On crée un fichier  /var/toto.1
RUN echo "toto" > /var/toto.1

# Build 1
# On peut définir un alias par exemple b1 pour la source
FROM debian:latest AS b1
# On crée le fichier /var/toto.2
RUN echo "toto" > /var/toto.2
# On recopie à partir du build 0 le fichier /var/toto.1 que l'on copie dans /
COPY --from=0 /var/toto.1 /

# Build 2
FROM debian:latest
# On crée le fichier /var/toto.3
RUN echo "toto" > /var/toto.3
# On recopie à partir du build 1 le fichier /var/toto.2 que l'on copie dans / en indiquant l'alias en source
COPY --from=b1 /var/toto.2 /
# On peut aussi copier un fichier depuis une image existante
COPY --from=httpd:latest /usr/local/apache2/conf/httpd.conf /etc

On final dans ce build on retrouvera uniquement les fichiers suivants :

  • /toto.2
  • /var/toto.3
  • /etc/httpd.conf

Exemple de Dockerfile multi-stages conditionnel

Le Dockerfile :

# DECLARATION VARIABLE POUR LE BUILD AVEC VALEUR PAR DEFAUT
ARG TYPE=development

# IMAGE DE BASE
FROM debian:latest AS base
RUN echo "Base" > /var/info.txt

# IMAGE AVEC LES ELEMENTS DE DEV
FROM base AS branch-version-development
# Tous les élements requis pour l'environnement de Dev
RUN echo "dev" >> /var/info.txt
ENV ENV=development

# IMAGE AVEC LES ELEMENTS DE PROD
FROM base AS branch-version-production
# Tous les élements requis pour l'environnement de Prod
RUN echo "production" >> /var/info.txt
ENV ENV=production

# IMAGE AVEC LES ELEMENTS DE DEV OU PROD EN FONCTION DE LA VARIABLE TYPE
FROM branch-version-${TYPE} AS final
UN echo "fin" >> /var/info.txt

Si on souhaite créer une image avec les éléments de dev :

docker build -t myapp:v1 --build-arg TYPE=development .

Et pour la prod :

docker build -t myapp:v1 --build-arg TYPE=production .

On peut aussi lancer le build de la base uniquement :

docker build -t myapp:v1 --target base
informatique/docker.1700732425.txt.gz · Dernière modification: 2023/11/23 10:40 par benoit