Docker

Introduction à nftables le remplaçant de iptables

Installation de nftables

Visualisation des règles (rules)

nft list ruleset


#Si vous avez le message même en étant root :

netlink: Error: cache initialization failed: Operation not permitted 

#il faut lancer le container avec le flag --privileged

docker run --privileged -it <image_docker>

Rien n’apparait, il n’y a pas de règles on va en créer une, d’abord on va créer une table

nft add table inet filter

puis nft list ruleset

table inet filter {
}

C’est vide pour l’instant, on va ajouter une règle pour autoriser les connexion sur le port 22

nft add rule inet filter input tcp dport 22 accept

mais vous risquez d'avoir l'erreur

Error: Could not process rule: No such file or directory
add rule inet filter input tcp dport 22 accept
                     ^^^^^                                                         

Comment ajouter une règle

nftable organise les règle en hiérarchie : table (conteneur de niveau supérieur) > chaine (groupe de règle dans une table) > règle (instruction de filtrage)

Types de tables:

  • ip : ipv4
  • ip6 : ipv6
  • inet : ipv4 + ipv6
  • arp : ARP
  • bridge : bridge
  • netdev : interface réseau

Création table puis chaine puis règle

# Créer la table inet filter (on vient de le faire)
nft add table inet filter

# Créer la chaîne input
nft add chain inet filter input { type filter hook input priority 0 \; policy accept \; }

# Maintenant ajouter votre règle SSH
nft add rule inet filter input tcp dport 22 accept

# lister les règles
nft list ruleset

table inet filter {
        chain input {
                type filter hook input priority filter; policy accept;
                tcp dport 22 accept
        }
}

Commandes de diagnostic

# voir une table spécifique
nft list table inet filter

# Voir le contenu d'une table spécifique
nft list table inet filter

# Voir les chaînes d'une table
nft list chains inet filter

# Voir une chaîne spécifique
nft list chain inet filter input

Faire tourner une distribution Debian dans un container docker

Etudier Linux depuis un container docker peut être intéressant pour apprendre en même temps Docker. Nous allons voir comme créer un container docker qui contient Debian, et nous allons commencer par nous familiariser avec Docker.

Téléchargement de l’image Docker officielle Debian

Pour télécharger l’image officielle de Debian faites la commande suivante (démarrer Docker Desktop avant)

docker pull debian

Démarrage de l’image docker debian

Une fois que l’image est téléchargée on peut démarrer le container docker

docker run -it debian


//alternativement démarrage avec un container nommé
docker run -it --name not-ubuntu debian

// voir les dockers en fonctionnement
// depuis un autre terminal, pour visualiser les docker qui tournent
docker ps

CONTAINER ID   IMAGE     COMMAND   CREATED       STATUS          PORTS     NAMES
a3de0ee8e2ba   debian    "bash"    2 hours ago   Up 54 minutes             not-ubuntu

Sortir d’un docker

Pour sortir d’un docker quand vous êtes en mode interactif, c’est à dire que vous êtes dedans, vous pouvez faire la combinaison de touche CTRL + D, ou faire la commande exit.

Quand vous avez démarré votre container docker avec docker run, vous pouvez voir les container actif avec docker ps, mais un fois que vous êtes sorti du container ou que le container est stoppé, docker ps ne donne rien, c’est alors qu’il vous faut faire la commande docker ps -a

Stopper un container

Vous pouvez stopper un container à partir d’un autre terminal

docker stop <ID CONTAINER>

Une fois le container stoppé, il ne sera plus visible avec docker ps, mais avec docker ps -a.

docker ps -a

CONTAINER ID   IMAGE     COMMAND   CREATED       STATUS                       PORTS     NAMES
a3de0ee8e2ba   debian    "bash"    2 hours ago   Exited (137) 5 minutes ago             not-ubuntu

Redémarrer un container « Exited »

Pour redémarrer un container éteint, il faut faire docker start <nom_container>. Le problème c’est que vous ne pouvez pas le redémarrer en mode interactif. Il faut le redémarrer et y entrer avec docker exec.

docker start not-ubuntu

//  entrée dans le docker avec un shell bash
docker exec -it not-ubuntu bash

Construire sa propre image docker de Debian

Pourquoi cette manipulation? L’image officielle de Debian ne contient que Debian. Si vous démarrez cette image, il faut tout installer (Proftpd, curl,wget etc). Nous voudrions une image qui contient tout ces logiciels. Bien sûr vous pouvez démarrer un container nommé afin de persister les installations. Mais votre image n’est pas distribuable car elle sera modifiée. Nous allons donc confectionner une image Docker de Debian customisée avec des logiciel préinstallés, un utilisateur créé. Qu’on va pusher sur le registry gratuit de Docker, qu’on pourra distribuer.

Créer un fichier Dockerfile de configuration

Créer un répertoire où vous allez mettre le fichier Dockerfile, dont voici le contenu:

# Utilise l’image officielle Debian
FROM debian:bullseye

# Évite les questions interactives lors des installations
ENV DEBIAN_FRONTEND=noninteractive

# Mise à jour et installation de paquets de base
RUN apt-get update && \
    apt-get install -y \
    curl \
    wget \
    vim \
    git \
    ca-certificates \
    sudo \
    bash \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Crée un utilisateur non-root
RUN useradd -ms /bin/bash devuser && \
    echo "devuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# Bascule sur l’utilisateur
USER devuser

# Répertoire de travail
WORKDIR /home/devuser

# Commande par défaut (ouvre un terminal interactif)
CMD [ "bash" ]

La commande apt-get clean permet d’effacer les fichier temporaire pour gagner de l’espace, vous aurez une image Docker plus petite.

Ensuite depuis el répertoire où il y a le Dockerfile lancez la commande :

docker build -t debian_custom .

debian_custom est le nom de la nouvelle image, le . est le répertoire où se trouve le fichier Dockerfile (répertoire courant)

Pour tester l'image nous allons démarrer le container:
docker run -it debian_custom

Normalement tout fonctionne normalement, et vous êtes connecté en devuser. Maintenant nous allons pousser cette image dans notre repository Docker, si vous n’avez pas de compte c’est le moment d’en créer un.

docker tag debian_custom refschool/debian_custom:latest

docker push refschool/debian_custom:latest

The push refers to repository [docker.io/refschool/debian_custom]
5f70bf18a086: Preparing 
34d4f9b85dd7: Pushing [==================================================>]  350.7kB
e5f126b4d117: Preparing 
46cd9334c732: Preparing 


puis quand c'est terminé

5f70bf18a086: Mounted from library/wordpress 
34d4f9b85dd7: Pushed 
e5f126b4d117: Pushed 
46cd9334c732: Mounted from library/debian 
latest: digest: sha256:fa443c6962fb73b4863bb10c46e41aef3db2c255604babcf83d89d41f1fbbb size: 1155


Allez sur le site https://hub.docker.com/repositories/refschool pour voir votre image en ligne ou allez dans le Docker Desktop.

Divers commandes docker

Les images qui n’ont plus de container actif peuvent être enlevé si elles ne servent plus. Les volumes de containers stoppés ou enlevés, les caches de builds.

Enlever une image par le nom ou par l’ID

docker images

ebian_custom                                             latest                                                                       48c43ff6050a   34 minutes ago   271MB
refschool/debian_custom                                   latest                                                                       48c43ff6050a   34 minutes ago   271MB
debian                                                    latest                                                                       b2ab84c007fe   4 weeks ago      117MB
<none>                                                    <none>                                                                       9f0461ec704d   3 months ago     53.3MB
<none>                                                    <none>                                                                       eb50ff518c13   3 months ago     47.9MB
test                                                      latest                                                                       d5aa53c2ffcd   3 months ago     47.9MB
evashen                                                   latest                                                                       bc040446118f   3 months ago     53.3MB
hubproxy.docker.internal:5555/docker/desktop-kubernetes   kubernetes-v1.27.2-cni-v1.2.0-critools-v1.27.0-cri-dockerd-v0.3.2-1-debian   c763812a4530   24 months ago    418MB
registry.k8s.io/kube-apiserver                            v1.27.2                                                                      c5b13e4f7806   2 years ago      121MB
registry.k8s.io/kube-scheduler                            v1.27.2                                                                      89e70da428d2   2 years ago      58.4MB
registry.k8s.io/kube-controller-manager                   v1.27.2                                                                      ac2b7465ebba   2 years ago      112MB
registry.k8s.io/kube-proxy                                v1.27.2                                                                      b8aa50768fd6   2 years ago      71.1MB
docker/desktop-vpnkit-controller                          dc331cb22850be0cdd97c84a9cfecaf44a1afb6e                                     556098075b3d   2 years ago      36.2MB
registry.k8s.io/coredns/coredns                           v1.10.1                                                                      ead0a4a53df8   2 years ago      53.6MB
registry.k8s.io/etcd                                      3.5.7-0                                                                      86b6af7dd652   2 years ago      296MB
registry.k8s.io/pause                                     3.9                                                                          e6f181688397   2 years ago      744kB
docker/desktop-storage-provisioner                        v2.0                                                                         99f89471f470   4 years ago      41.9MB


docker rmi 9f0461ec704d  // on enlève par l'ID
docker rmi evashen.   // on enlève par le nom


Pour aller plus vite vous avez la commande:

docker image prune -a

// qui va tout enlever après confirmation 

Débuter avec Docker avec un déploiement simple

Pour tout ce qui suit, il faut avoir sous Windows ou MacOS démarré Docker Desktop.

Déploiement d’un site pur front end mono container

C’est le cas le plus simple.

Pour rappeler une image Docker est construite en copiant les fichiers d’un projet vers une image qui sera « buildée ». Cette image sera runnée pour devenir un container.

Déploiement d’une application PHP/MySQL multicontainer

Une application PHP/MySQL est fait d’un script PHP et d’une base de données. On ne peut pas mettre dans une seule image, donc il nous faudra deux images, les runner sous forme de deux containers. Il faut que la bse de données soit disponible avant que le script PHP ne soit exécuté.

Le script PHP va faire une requête en base de donnée, donc il faut que les deux containers puissent communiquer entre eux.

Enfin on doit pouvoir visiter l’application PHP depui snotre ordinateur hôte.

FROM php:7.3-apache

#Install git and MySQL extensions for PHP

RUN apt-get update && apt-get install -y git
RUN docker-php-ext-install pdo pdo_mysql mysqli
RUN a2enmod rewrite

COPY src /var/www/html/
EXPOSE 80/tcp
EXPOSE 443/tcp

On va builder une image pour le projet PHP, pour l’image de MySQL on va prendre l’image officielle de MySQL.

Et pour mettre en musique les deux images, on a le fichier docker-compose.yml

version: '3.8'

volumes:
  mysql_data:
    # Persistent storage for MySQL data

services:
  mysql:
    image: mysql:8.0
    container_name: mysql8
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: app_db # Create a default database
      MYSQL_USER: app_user # Create a non-root user
      MYSQL_PASSWORD: app_password # Password for the non-root user
    ports:
      - "3306:3306" # Optional: Expose MySQL port to host
    volumes:
      - mysql_data:/var/lib/mysql # Persist database files
    restart: always

  php:
    container_name: php_app
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:80" # Map port 80 in the container to port 8080 on the host
    depends_on:
      - mysql # Ensure MySQL starts before PHP
    environment:
      MYSQL_DB_HOST: mysql # MySQL service hostname
      MYSQL_DB_PORT: 3306
      MYSQL_DB_USER: app_user
      MYSQL_DB_PASS: app_password
      MYSQL_DB_NAME: app_db

Ne soyez pas effrayés par la syntaxe, il y a un formalisme qui reste le même pour ce genre de fichier.

Ici on a deux images, l’image de Mysql est configurée avec le mot de passe root, nom de la bdd, du user et le mot de passe du user non root. On mappe le port 3306 de l’hôte (à gauche des deux points) à celui du container (à droite).

Pour le container de l’application PHP, on définit des variables d’environnement qui sont bien sûr un peu identique aux pramétrage de du container MySQL, mais on n’est pas obligé de les avoir et on peut coder en dur dans le script les mots de passe et autre nom de base de donnée. On mappe le port 8080 de l’hôte au port 80 du container. Pour lancer l amachinerie faites :

docker-compose up

docker-compose docn pour arrêter

# et si vous faites des modifications il faut rebuilder l'image

Vous allez peut être rencontrer un soucis pour la connexion à la base de données, MySQL8, qui utiliser un hashage nouveau, il vous faudra rentrer dans le docker de MySQL et taper la commande suivante:

docker exec -it mysql8 mysql -uroot -psecret

//mysql native password use sha1, newer method use sha2 but not supported by PDO, so roll back to native password
//et une fois dans le prompt de MySQL:
//exécutez la requêtes SLQ suivante :
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'secret';
FLUSH PRIVILEGES;

Cette commande a pour but d’utiliser l’ancien algorithme de hashage de mot de passe.

Le script PHP

C’est un simple script qui fait une connexion à al base de donnée et va dumper l’objet PDO

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Show databases in MySQL server</title>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <h1>Show databases in MySQL server</h1>
        <?php
        $dsn = 'mysql:host=mysql;dbname=app_db';
        $user = "root";
        $pass = "secret";
        // Création de l'objet de connexion qui va nous permettre de faire des requêtes SQL
        $pdo = new \PDO($dsn, $user, $pass);
        $result = $pdo->exec("SET CHARACTER SET utf8");
        var_dump($pdo);
   
        ?>
    </div>
</body>

</html>

Docker denied: requested access to the resource is denied

The push refers to repository [docker.io/yvonhuynh/hello2]
An image does not exist locally with the tag: yvonhuynh/hello2

Si vous venez de commencer récemment à suivre un tutoriel Docker et que vous avez ce message, alors il y a peut être deux raisons, la seconde raison est plus probable.

Le contexte :

vous avez construit une image docker et vous aimeriez la pousser ver le hub de docker, mais vous rencontrez ce message lorsque vous poussez votre image soit depuis le Docker Desktop, soit depuis la ligne de commande.

Le dockerfile:

FROM node:alpine
COPY . /app
WORKDIR /app
CMD node app.js

Le projet javascript:

console.log('bonjour version 2')

Première raison possible :

Vos identifiants de connexion ne son tpas les bon

Cette raison est à titre préventif, il est fort à parier que ce n’est pas le cas.

docker logout
docker login
// renseignez vos identifiants.

Seconde raison possible:

Vous n’avez pas donné un tag à votre image

Vous avez buildé une image avec la commande:

docker build -t hello2
docker tag nom_image NOM_DOCKERHUB/nom_image



docker tag hello2 yvonhuynh/hello2


docker push  yvonhuynh/hello2

Le nom de l’image s’appelle hello2 dans le hub docker.

yvonhuynh est le login de votre registry docker sur le site docker.com (dans notre cas mais il existe d’autres registry). un registry est comme un repository git.

Retour en haut