Docker et Portainer part 2 – Stack vsftpd mono-image

Docker et Portainer

Salut à tous, dans le dernier TP on s’est penché sur docker et plus particulièrement son intégration avec Portainer. Aujourd’hui on va regarder comment déployer une Stack vsftpd dans Portainer. L’objectif étant d’avoir un serveur (VS)FTP accessible en read-only pour quelques utilisateurs à la fin du TP.

Rappel des articles de la série « Docker et Portainer » :

Les stacks docker

Les stacks sont une de mes fonctions préférées de docker, elles permettent de définir la configuration d’une ou plusieurs image dans un fichier docker-compose.yml. En effet, si un image docker permet de configurer un système, un logiciel ou encore un ensemble d’application dans un conteneur ; une image n’est pas adaptée à la configuration qui varie entre chaque utilisateur de l’image : création de comptes utilisateur, gestion des variables d’environnements, gestion du réseau, volumes, logging, etc.

C’est là qu’intervient la stack et le fichier docker-compose.yml, qui permettent de spécifier ces éléments pour une image (en accord avec ce qui est prévu par l’image).

Je vais beaucoup utiliser les snacks dans la suite des TP sur docker et Portainer car elles permettent :

  • d’industrialiser facilement les déploiements des conteneurs ;
  • de conserver la configuration de vos images dans un fichier simplifiant backup et mise à jour ;
  • de lier entre-elles plusieurs images dans un seul fichier de configuration.

Dans ce TP je vais vous présenter une stack « mono-conteneur » pour introduire le concept simplement. Vous verrez par la suite que c’est très utile (indispensable) lorsque vos images deviennent complexes (au hasard, un site WordPress avec un nginx, un php, une DB et un serveur de cache qui doivent tous se parler…).

La Stack VSFTPD

Un bon exemple valant toujours mieux qu’un long discours on va s’attaquer à notre Stack VSFTPD sans transition. Mon objectif était d’avoir à la fin un serveur FTP avec les caractéristiques suivantes :

  • Plusieurs utilisateurs ;
  • Accès FTPS sécurisé par certificats ;
  • accès aux logs ; et
  • un répertoire commun à tous les users, en lecture seule.

Trouver un image VSFTPD ou en construire une ?

La première chose à faire avant de construire notre stack c’est déjà de trouver l’image docker qu’on va faire tourner, deux options :

  1. on part de zéro et on construit notre propre image « from scratch » ; ou
  2. on repart d’un image existante sur le hub docker (en vérifiant dans les sources qu’elle ne fait pas n’importe nawak), et si nécessaire en la customisant pour nos besoins.

C’est cette seconde options que j’ai pris, donc direction hub.docker.com et rechercher vsftpd (382 images trouvées…). Après il faut prendre un peu de temps pour regarder ce que fait chaque image.

J’ai fini par m’arrêter sur celle-ci panubo/vsftpd qui répondait à mon besoin et pour lesquels j’ai trouvé que les sources étaient propre.

Construire une stack vsftpd.

Bon alors la base d’un fichier de stack dans portainer c’est :

version: 2
services:
  vsftpd:

Après il faut définir les éléments qu’on veut mettre en place dans notre Stack. on va commencer par le minimum, l’image du conteneur à utiliser, les noms et le comportement à avoir en cas d’arrêt :

version: "2"
services:
  vsftpd:
    image: panubo/vsftpd:latest
    container_name: vsftpd
    hostname: vsftpd
    restart: always

Maintenant, on peut passer aux aspects réseaux, le bloc ports nous permet de spécifier les ports qui seront exposés à l’extérieur du réseau privée docker :

  ports:
    - 21:21
    - 4559-4564:4559-4564

On passe ensuite à la persistance des données maintenant en définissant nos volumes (rappels sur les volumes dans la partie 1) :

  volumes:
    - "vsftpd_cert:/etc/ssl:ro"
    - "shared_ftp:/srv:ro"
    - "vsftpd_logs:/var/log"
    - "vsftpd_conf:/etc/vsftpd"

Notez qu’on a pas besoin de créer les volumes s’ils n’existent pas, docker/portainer s’en occupera tout seul à l’instanciation si besoin. Remarquez aussi le :ro en fin de ligne pour spécifier que le volume est en read only pour le conteneur.

Maintenant il nous reste un peu de configuration à faire pour créer les utilisateurs et mettre en place le chiffrement des communications. Pour les utilisateurs, l’image de panubo passe par des variables d’environnement dans le docker.

  environment:
    - FTP_USER_1=toto:$$6$$R3h09ywl$$QBf0HtgHgwDejoruGviab1Ogo4PiGrXbXSSM4Hx4zu3ZnfreHeDEjxxSPMexod0G/ekznFmSyswVwQvKDTcO/
    - FTP_USER_2=tata:$$6$$ZE.GMXwY9mFaCDQ$$b5vfJ5ThglxZmjZbyibsaQulIS0rxszUp9DHZ8mQi2zwrfYFGhtg.x7QKP/ANdx.FQiY8UMGzKCHPN1lnGvq1

Et le hash du mot de passe est à générer avec la commande suivante :

mkpasswd -m sha-512 monSuperMot2Passe
$6$HsHpgRecjOX13/$wc5ExJnkcwEaIshtgp5OmRXqT7ORTrC0ZSsvAxPV0kqAK4kUmdZBsEWFFvG9BqxnLgZRc/c4rNs4rA3aedikF.

Notez qu’il faut doubler les $ (pour les échapper) dans le fichier par rapport au retour de la commande.

Mettre en place le chiffrement FTPS

Il nous reste ce dernier point à mettre en place. Pour ça il faut d’abord générer un certificat et sa clé privée :

openssl genrsa -out vsftpd.key 2048
openssl rsa -in vsftpd.key -pubout -out vsftpd.crt

Ici vous allez avoir besoin de créer le volume vsftpd_certs avant de lancer votre stack pour placer les certificats dedans. Pour cela rendez-vous dans Volume-> Create dans Portainer.

Stack vsftpd

A partir de là, sur votre hôte vous trouverez dans /var/lib/docker/volumes/vsftpd_cert/_data/ votre volume. IL vous faut alors y créer les dossiers suivants et déplacer vos certificats dedans ainsi.

mkdir /var/lib/docker/volumes/vsftpd_cert/_data/certs
mkdir /var/lib/docker/volumes/vsftpd_cert/_data/private
mv vsftpd.crt /var/lib/docker/volumes/vsftpd_cert/_data/certs
mv vsftpd.key /var/lib/docker/volumes/vsftpd_cert/_data/private

Il faut ensuite changer la commande de démarrage de notre image vsftpd pour utiliser le fichier de configuration « ssl » comme documenté par le projet. Et pour cela vous devez rajouter la ligne suivante dans votre docker compose.

   command: "vsftpd /etc/vsftpd_ssl.conf"

Stack vsftpd : docker-compose.yml

Au final vous devriez vous retrouver avec un fichier comme ça :

version: "2"
services:
  vsftpd:
    image: panubo/vsftpd:latest
    container_name: vsftpd
    hostname: vsftpd
    command: "vsftpd /etc/vsftpd_ssl.conf"
    restart: always
    environment:
      - FTP_USER_1=toto:$$6$$R3h09ywl$$QBf0SHtgHgwDejoSBDviab1Ogo4PiGrXbXSSM4Hx4zu3Znfdl2eDEjxxSPMexod0G/ekznFmSyswVwQvKDTcO/
      - FTP_USER_2=tata:$$6$$ZE.GMXwY9mFaCDQ$$b5vfJ5rVBlxZmjZbyibsaQulIS0rxszUp9DHZ8tmQi2zwrfYFarqg.x7QKP/ANdx.FQiY8UMGzKCHPN1lnGvq1
    ports:
      - 21:21
      - 4559-4564:4559-4564
    volumes:
      - "vsftpd_cert:/etc/ssl:ro"
      - "shared_ftp:/srv:ro"
      - vsftpd_logs:/var/log
      - vsftpd_conf:/etc/vsftpd

Il faudra copier cette Stack dans Portainer dans Stack-> Add Stack.

Stack vsftpd

Et c’est tout, vous cliquez sur Deploy the stack et vous devriez avoir un beau serveur vsftpd tout bien configuré qui sera accessible sur le port 21 et en mode « passif » sur les ports 4559 à 4564.

Vous pouvez tester avec un filezilla par exemple en configurant dans le gestionnaire de site :

Conclusion

Voilà c’est tout pour aujourd’hui, on a eufleré ici la construction d’une stacks docker. J’aurais aussi pu vous parler du networking de vos conteneurs ou de la manière dont on peut remonter les logs des conteneurs dans un Splunk, mais ce sera pour la suite.

Dans les prochains TP on verra comment modifier une image docker à partir d’une image existante, et surtout comment déclarer et lier plusieurs conteneurs dans un même Stack.

A bientôt pour la suite et geekez bien (et chez vous donc) d’ici là.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.