Le starter pack de l’auto hébergement avec Docker 🐳🚀

Le starter pack de l’auto hébergement avec Docker 🐳🚀

Temps de lecture : 17 minutes

Temps de réalisation « novice » : 3 heures
Temps de réalisation « connaisseur » : 1 heure
Temps de réalisation « expert » : 30 minutes

Introduction

Suite à beaucoup de demande et de nombreuses heures passées à vous aider à déployer des logiciels avec Docker, voici un guide complet afin de déployer plusieurs logiciels sur votre machine équipée de Docker !

Des connaissances basiques Linux et réseau sont requises (édition de fichier, compréhension de l’arborescence Linux, adressage IP, compréhension du réseau sous Linux (interface, bridge, ip(6)tables), résolution de noms d’hôtes par « hostname » et DNS, jargon informatique).

Ce guide s’adresse à tout ceux qui :

  • Hébergent plusieurs sites grâce à des VirtualHost NGINX ou Apache avec des configurations homogènes et / ou hétérogènes et souhaitent améliorer la gestion du déploiement, configuration et mise à jour de ces derniers.
  • Débutent avec Docker.
  • Veulent déployer un environnement de développement web (Python, NodeJS, PHP, etc…).
  • Souhaitent auto héberger leurs données et projets plus facilement.

Dans ce guide, les logiciels suivants seront utilisés:

  • Docker :
    • Le gestionnaire de conteneur
  • Traefik :
    • Un reverse-proxy « Cloud Native » (il s’adapte très bien aux grosses infrastructures convergées) léger, avec configuration dynamique (de traefik et des conteneurs backend)
  • Apache & PHP :
    • Afin d’héberger tout type de site, on utilisera WordPress pour l’exemple (sans utiliser l’image Docker de WordPress)
  • MariaDB :
    • Le serveur de bases de données MySQL
  • NextCloud :
    • Un endroit sûr pour stocker vos données, contacts, agendas, etc…
  • Portainer :
    • Une interface web de gestion de conteneurs.

Pré-requis

Un serveur (bare-metal ou machine virtuelle KVM) avec:

  • Linux (Ubuntu / Debian / Autre selon préférence)
  • Minimum 4GB de RAM
  • Minimum 4 Thread CPU
  • Du stockage (selon vos besoins)
  • Une ou plusieurs IPv4 et/ou blocs IPv6 publique accessible depuis internet
  • Un domaine avec une gestion entière des champs DNS (A, AAAA)

(Fonctionne aussi sous « Docker Desktop (Windows) » mais les chemins pour relier le stockage d’un conteneur à un stockage existant seront différents, je ne garanti pas le bon fonctionnement de ce guide sous Windows.)

Éléments utilisés dans le guide

Pour ce qui est du serveur:

  • OS: Debian 10.7
  • RAM: 8GB
  • CPU: 8 Thread
  • Unique disque de 150GB SSD
  • Une IPv4 et une IPv6 publique

Tous les sites déployés utiliseront mon domaine gouint.fr et un sous-domaine par service:

  • Portainer: portainer.gouint.fr
  • NextCloud: nextcloud.gouint.fr
  • Notre site d’exemple WordPress: wordpress.gouint.fr
  • Dashboard Traefik: traefik.gouint.fr

Dans les commandes énoncées dans ce guide, il faudra modifier le domaine utilisé avec le votre.

Au niveau DNS, les sous-domaines sont configurés avec un champ DNS AAAA vers l’IPv6 de l’hôte Docker, et un champ A vers l’IPv4 de l’hôte Docker (ou l’IPv4/v6 du conteneur cible si vous avez configuré docker pour utiliser des IP publiques, ce qui n’est pas le cas ici)

Dans ce guide, nous restreindrons l’utilisation des ressources matérielle et l’isolation réseau des logiciels comme ce qui suit:

  • NextCloud et WordPress:
    • 2 GB de RAM
    • 1,5 Thread
    • Réseau proxy et database
  • MariaDB:
    • 2 GB de RAM
    • 2 Thread
    • Réseau database
  • Traefik et Portainer
    • 1 GB de RAM
    • 1 Thread
    • Réseau proxy

Nous utilisons presque toutes les ressources du serveur, si votre serveur n’a pas autant de capacité, adaptez les limitations CPU/RAM des logiciels déployés en fonction de votre matériel.

Docker sera configuré pour fonctionner en « Dual Stack » c’est à dire, en IPv4 et en IPv6 en même temps.
Les réseaux docker seront le bloc IPv6 privé fd00::/7

But / pourquoi ?

Quand on héberge plusieurs sites avec la technologie des VirtualHost proposé sous NGINX et Apache, plusieurs sites tournent sur le même processus et héritent donc tous des configurations de ce dernier (ressources CPU/RAM, réseau, etc…)

Utiliser un conteneur par site / logiciel permet de mieux maitriser la distribution des ressources entre vos différents sites hébergés, améliorer leur portabilité et faciliter les mises à jour dans le cas d’applications sous forme d’image de conteneur. Cela permet aussi d’isoler au niveau du réseau les logiciels tiers et serveurs de bases de données, par exemple, les conteneurs WordPress et NextCloud peuvent accéder au conteneur MariaDB mais Traefik lui ne peut pas, car il n’est pas dans le même réseau Docker que le conteneur MariaDB.

Installation et configuration de docker

Pour installer docker, il suffit d’une seule commande exécutée en tant que root ou sudoer:

# curl https://get.docker.com | bash

Si vous n’avez pas le paquet curl, il faut bien évidemment l’installer !
Puis on démarre le démon docker avec la commande:

# systemctl start docker

On peut vérifier que docker soit bien démarré en regardant la version du serveur:

# docker version
Client: Docker Engine - Community
 Version:           20.10.2
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        2291f61
 Built:             Mon Dec 28 16:17:34 2020
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.2
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8891c58
  Built:            Mon Dec 28 16:15:28 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Dans ce guide, nous utiliserons donc Docker version 20.10.2.

Ensuite, pour que Docker fonctionne en IPv6 (si vous le voulez), il faut modifier un fichier de configuration, s’il n’existe pas, il faut le créer.
Le fichier est /etc/docker/daemon.json
Et son contenu:

{
  "ipv6": true,
  "experimental": true,
  "ip6tables": true,
  "fixed-cidr-v6": "fd00::/64"
}

Avec cette configuration, le bridge par défaut aura le réseau fd00::/64. C’est un réseau local mais vous pouvez aussi utiliser un réseau « publique » (dans la plage 2000::/3, généralement votre FAI vous fournie un /64 ou un /56 pour les plus chanceux) (Attention, chez Orange, seul le premier bloc /64 du bloc /56 attribué à votre ligne est utilisable)

Ensuite, il faut redémarrer le démon Docker avec la commande:

# systemctl restart docker

On peut inspecter le réseau docker par défaut appelé « bridge » afin de vérifier qu’IPv6 est bien activé:

# docker inspect bridge | grep v6
"EnableIPv6": true,

Le champ EnableIPv6 est bien à « true ».

Configuration des réseaux Docker

Afin de créer les sous réseaux proxy et database, il faut définir quels seront les réseaux IP (v4 et v6) utilisés.
On utilisera un réseau v4 et v6 privé a chaque fois (RFC1918 et RFC4193).
Pour le réseau proxy:

  • IPv4: 172.20.0.0/16
  • IPv6 (si utilisé): fd00:1::/64

Pour le réseau database:

  • IPv4: 172.21.0.0/16
  • IPv6 (si utilisé): fd00:2::/64

Créons le réseau Proxy:

# docker network create proxy --ipv6 --subnet=172.20.0.0/16,fd00:1::/64 --driver=bridge

Ainsi que le réseau database:

# docker network create database --ipv6 --subnet=172.21.0.0/16,fd00:2::/64 --driver=bridge

Si vous n’utilisez pas IPv6, retirez simplement l’argument –ipv6 ainsi que la deuxième valeur de l’argument –subnet (après la virgule)

Si vous avez configuré vos réseaux Docker avec des IPv6 publiques afin que vos conteneurs puissent être accessible directement depuis internet, il vous faudra le logiciel NDPPD qui permet de transmettre les paquets « Neighbor Discovery Protocol » (NDP, l’équivalent d’ARP en IPv6) entre l’interface « WAN » et vos bridges docker (docker0 pour le bridge par défaut, br-xxxxxxxxxxxx pour les réseaux bridge créés manuellement).
Voici un exemple de configuration avec le bridge Docker par défaut et le bloc 2001:db8::/64 (bloc utilisé pour la documentation, à remplacer par votre bloc).
Le fichier de configuration est /etc/ndppd.conf et notre interface « WAN » est eth0.

route-ttl 30000
proxy eth0 {
    router yes
    rule 2001:db8::/64 {
        static
    }
}
proxy docker0 {
    router yes
    rule 2001:db8::/64 {
        static
    }
}

Il faudra aussi activer le forwarding IPv6 dans les paramètres du noyau linux. Cela peut se faire en ajoutant une ligne au fichier /etc/sysctl.conf:

net.ipv6.conf.all.forwarding = 1

Il faut ensuite indiquer au système que les paramètres ont été modifiés avec la commande:

# sysctl -p

En indiquant cela dans le fichier sysctl.conf, la configuration sera appliquée à chaque redémarrage.
Pour un paramétrage temporaire vous pouvez utiliser la commande:

# sysctl -w net.ipv6.conf.all.forwarding=1

Déploiement de Traefik

Traefik est un reverse proxy moderne, beaucoup plus abordable que NGINX ou HAProxy qui doivent être reconfigurés manuellement à chaque déploiement / modification d’un site.
Pour remédier à ce problème, Traefik utilise l’API de docker afin de trouver les conteneurs (sites web ou autre services TCP/UDP) vers les quels router le traffic en fonction des labels de ce dernier.

Si vous utilisez des adresses IPv6 publiques, vous n’avez pas besoin de Traefik, car chaque conteneur sera déjà accessible depuis internet via sa propre IPv6 publique (seulement, si vous désirez avoir une connectivité IPv4 sur les sites, Traefik devra être présent car une seule IPv4 publique est configurée, sauf dans le cas ou vous avez plusieurs IPv4 routé vers votre serveur (en ARP L2 ou BGP L3)).
Si au contraire vous n’utilisez pas IPv6 ou que vous l’utilisez avec des adresses privées, il vous faudra l’installer.

Traefik n’est pas un simple reverse proxy, il permet aussi l’auto attribution et configuration de certificats SSL Let’s Encrypt. S’il n’est pas présent, vous devrez gérer vos certificats vous même ou utiliser un serveur web permettant de faire la même chose (Caddy par exemple)

Passons maintenant à l’installation. Vu que Portainer sera accessible seulement via Traefik, nous devrons installer Traefik en ligne de commande avant de pouvoir installer et accéder à Portainer pour installer le reste.

Tout d’abord, il faut créer le fichier de configuration par défaut de Traefik, nous utiliserons la version 2.4 dans ce guide, voici le lien de la configuration par défaut pour cette version:
https://raw.githubusercontent.com/traefik/traefik/v2.4/traefik.sample.toml
On ira l’enregistrer dans /opt/hosting/traefik.toml.

Par défaut, Traefik est configuré avec deux points d’entrée, un sur le port 80 (nommé « web ») ainsi qu’un autre sur le port 443 (nommé « websecure ») pour le support de TLS (HTTPS). Nous ne modifierons pas cette configuration car c’est déjà ce que l’on veut.
Cependant, nous voulons configurer le challenge HTTP ACME de let’s encrypt pour obtenir automatiquement un certificat à la configuration d’un nouveau service hébergé.

Voici le bloc de configuration à ajouter à la fin du fichier traefik.toml:

[certificatesResolvers.letsencrypt.acme]
  email = "your-email@example.com"
  storage = "/certs/acme.json"
  [certificatesResolvers.letsencrypt.acme.httpChallenge]
    entryPoint = "web"

Les certificats seront sauvegardés dans le fichier /certs/acme.json du conteneur, les alertes d’expirations seront envoyées à your-email@example.com et le challenge HTTP se fait via le point d’entrée nommé « web » (port 80).

Par défaut traefik regarde tout les conteneurs, on désactive cela afin d’éviter les mauvaises surprises dans la rubrique « [providers.docker] » en décommentant la ligne « exposedByDefault = false »

On va aussi configurer le point d’entrée web (HTTP) pour qu’il redirige toutes les requêtes vers websecure (HTTPS)

Pour cela il faut éditer la configuration de l’entrypoint comme ce qui suit:

[entryPoints]
  [entryPoints.web]
    address = ":80"

    [entryPoints.web.http]
      [entryPoints.web.http.redirections]
        [entryPoints.web.http.redirections.entryPoint]
          to = "websecure"
          scheme = "https"

Il faut aussi configurer un routeur afin que traefik.gouint.fr redirige vers le dashboard Traefik.

Pour cela, il faut ajouter quelques lignes à la configuration statique, actuellement seul Docker est un fournisseur de configuration dynamique, il faut en configurer un second afin de prendre un fichiers pour configuration dynamique.
Nous configurerons dans le même temps le provider docker afin de limiter l’écoute des services Docker qu’a ceux présent dans le réseau « proxy ».
La section [providers] du fichier traefik.toml doit ressembler à cela:

[providers]
  [providers.docker]
    exposedByDefault = false
    network = "proxy"
  [providers.file] # Ici, notre nouveau provider de configuration dynamique par fichier
    directory = "/etc/traefik/dynamic"
    watch = true

Puis on peut ajouter la configuration suivante au fichier /opt/hosting/dynamic.toml.

[http.routers.dashboard]
  rule = "Host(`traefik.gouint.fr`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
  service = "api@internal"
  middlewares = ["auth"]
  entryPoints = ["websecure"]
  [http.routers.dashboard.tls]
    certResolver = "letsencrypt"
  

[http.middlewares.auth.basicAuth]
  users = [
    "admin:$apr1$dp872vot$C5VtNMF27kofjoMvQ2Wyf0"
  ]

On utilise un middleware d’authentification basique qui utilise la même syntaxe que htpasswd (fichier ou on défini users/password avec le serveur web Apache). Vous pouvez générer cette ligne ici.

Ici, on accèdera au dashboard sur https://traefik.gouint.fr/dashboard/ (ne pas oublier le dernier slash « / » ) avec l’identifiant « admin » et mot de passe « test ».

Puis, on peut lancer Traefik avec docker:

docker run -d -p 443:443 -p 80:80 --network=proxy --restart always -v /opt/hosting/traefik.toml:/etc/traefik/traefik.toml -v /opt/hosting/dynamic.toml:/etc/traefik/dynamic/dynamic.toml -v /opt/hosting/certs:/certs -v /var/run/docker.sock:/var/run/docker.sock -m 1G --cpus 1 --name traefik traefik:v2.4.8

On utilise docker run avec plusieurs options:
-d : Le conteneur tourne en arrière plan

-p : Permet de rediriger le port de n’importe quelle interface de l’hôte docker vers le conteneur (Hote:Conteneur), inutile si vous utilisez directement des IPv4/IPv6 publiques sur le réseau du conteneur.

--restart always: Le conteneur redémarrera quoi qu’il se passe (redémarrage de l’hôte, erreur, etc…).

--name permet de spécifier un nom pour le conteneur, sans ça, un nom généré par docker sera appliqué.

--network permet de placer le conteneur dans un réseau docker spécifique.

-v: Permet de configurer du stockage persistent sous forme de volume docker ou de dossiers/fichiers déjà existant

nom-du-volume:/dossier/conteneur (cette syntaxe est un montage de volume)

/dossier/hote:/dossier/conteneur (cette syntaxe est un montage sous forme de bind de dossier)

/dossier/hote/fichier.txt:/dossier/conteneur/fichier.txt (cette syntaxe est un montage sous forme de bind de fichier)

-m: Limite la quantité de RAM disponible pour le conteneur

--cpus: Limite le nombre de thread CPU que le conteneur peut utiliser.

Si la source du stockage n’existe pas docker créera automatiquement un dossier (dans le cas d’un bind de fichier/dossiers) ou un volume.
Ici, on monte un fichier traefik.toml qui est la configuration de Traefik, le fichier de configuration dynamique, un dossier afin de stocker les certificats générés par let’s encrypt et enfin, le socket unix de Docker afin que Traefik puisse regarder nos conteneurs.

Et en dernier on indique l’image docker utilisée, ici l’image est « traefik » et le tag correspondant à la version « :v2.4.8 »

Documentation complète de la commande « docker run »

Déploiement de Portainer

Portainer est une interface web de gestion de conteneurs, il supporte Docker, Docker Swarm (docker en mode cluster) et Kubernetes (une plateforme d’orchestration de conteneurs).
Documentation officielle de Portainer.

Pour fonctionner, Portainer a besoin de stocker des données, cela se fait via un volume docker qu’il faut créer avec la commande suivante:

docker volume create portainer_data

Pour l’installer, nous allons devoir modifier la commande indiquée dans la documentation afin de ne pas exposer l’interface web via des ports mais via Traefik.

Voici la commande:

docker run -d --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data -l traefik.enable=true -l traefik.http.routers.portainer.entryPoints=websecure -l traefik.http.routers.portainer.rule="Host(\`portainer.gouint.fr\`)" -l traefik.http.services.portainer.loadbalancer.server.port=9000 -l traefik.http.routers.portainer.service=portainer -l traefik.http.routers.portainer.tls=true -l traefik.http.routers.portainer.tls.certresolver=letsencrypt -m 1G --cpus 1 --network=proxy portainer/portainer-ce

On a simplement retiré les deux port forwarding par défaut (port 8000 et 9000), indiqué que le container devait se trouver dans le réseau proxy afin que traefik puisse y accéder, on l’a limité à 1Go de RAM et 1 Thread CPU et ajouté les labels suivants:

  • traefik.enable=true
    Indique à Traefik qu’il faut « regarder » ce conteneur
  • traefik.http.routers.portainer.entryPoints=websecure
    On accepte que le trafic venant du point d’entrée sécurisé
  • traefik.http.routers.portainer.rule="Host(...)"
    On veut que ce routeur soit relié à l’hôte DNS « portainer.gouint.fr ». Ne pas oublier le « \ » avant le caractère « ` » pour échapper ce dernier, qui sans, serait interprété par bash en tant que début de commande, portainer.gouint.fr serait donc la commande à interpréter.
  • traefik.http.services.portainer.loadbalancer.server.port=9000
    Portainer n’utilise pas le port 80 qui est le port par défaut d’un service web mais le port 9000, le nom du service par défaut est le nom du conteneur, ici, « portainer ».
  • traefik.http.routers.portainer.tls=true
    Ce routeur utilise le protocole TLS vu que le point d’entrée est sécurisé (https)
  • traefik.http.routers.portainer.tls.certresolver=letsencrypt
    Le certificat TLS correspondant à ce routeur est fourni par le provider TLS « letsencrypt » présent dans la configuration statique de Traefik.

Une fois Portainer lancé, le routeur ainsi que le service devrait apparaitre sur le dashboard de Traefik:

Notre routeur ayant pour hôte portainer.gouint.fr est bien configuré sans erreurs sur le service portainer. Le provider est Docker car il a été configuré via les labels du conteneur Portainer.
Notre service est bien configuré vers le port 9000 du conteneur Portainer.

Accédons maintenant à l’interface de Portainer via l’hôte configuré sur le routeur, ici, portainer.gouint.fr.
Il faudra configurer un utilisateur administrateur:

Configuration de l’utilisateur administrateur de Portainer.

Une fois ceci configuré, il faut maintenant indiquer à Portainer à quoi se connecter, ici l’hôte Docker local:

Portainer utilisera le socket docker qu’on lui a transmis via un bind lors de la création du conteneur.

Si vous avez configuré correctement le conteneur, votre hôte devrait apparaître:

Cliquez dessus puis sur « Containers » dans le menu à gauche pour visualiser les conteneurs présents sur l’hôte Docker:

Nos deux conteneurs traefik et portainer sont visibles, tout va bien !

Maintenant que Portainer est installé et utilisable, nous pouvons l’utiliser pour la suite du guide afin de créer/gérer les futurs conteneurs.

Déploiement du serveur de bases de données MySQL (MariaDB)

MariaDB est une version modifiée (fork) de MySQL. Il supporte plus de moteurs de base de données que MySQL, est plus performant et propose plus d’options que ce dernier.

Nous utiliserons ce serveur afin d’installer WordPress ainsi que NextCloud.

Pour créer le conteneur, Portainer nous met a disposition des « stack » (configuration de conteneur(s)) pour déployer plus facilement certaines applications, dont MariaDB. On va donc s’en servir pour créer le conteneur.

L’équivalent en commande docker run est le suivant:

# docker volume create mariadb
# docker run -d --restart=always --name=mariadb -v mariadb:/var/lib/mysql --network=database -e MYSQL_ROOT_PASSWORD=test -m 2G --cpus 2 mariadb
Dans le menu App Template s’y trouve plusieurs applications prêtes au déploiement.

On configure ensuite le nom du conteneur ainsi que le réseau docker (ici, database) et le mot de passe du compte d’administration « root ».
On ne mappe aucun port de l’hôte sur le conteneur car nous n’en avons pas besoin en dehors du réseau database.
Le stockage persistent du dossier « /var/lib/mysql » du conteneur se fera dans un volume Docker que Portainer créera automatiquement.

Configuration de la stack MariaDB

Par défaut Portainer ne limite pas le CPU ni la RAM du conteneur, il faudra l’éditer afin de le limiter. Pour cela on se rend sur la liste des conteneurs et on clique sur le conteneur mariadb puis on l’édite en cliquant sur le bouton « Duplicate/Edit » tout en haut.
Enfin, tout en bas de la page dans les paramètres avancés et dans « Runtime & Resources » on peut limiter la RAM et CPU.

2048MB (2Go) de RAM et 2 Thread CPU.

On clique sur « Deploy the container » puis on confirme le remplacement (car pour éditer un conteneur il faut le stopper, le supprimer puis le recréer, ce que Portainer fait à notre place).

Et voilà ! Le conteneur MariaDB est installé et configuré ! Il ne reste plus qu’a s’y connecter pour créer les utilisateurs et bases de données pour WordPress et NextCloud.

Afin de créer cela, on doit obtenir une console sur le conteneur. On peut en obtenir une de deux manières différentes.
Via l’outil CLI docker:

# docker exec -ti mariadb bash

L’argument -ti permet d’obtenir un terminal interactif, sans ce dernier, docker va simplement exécuter la commande « bash » dans le conteneur, mais sans aucun retour ni possibilité d’interagir avec.

Ou sinon, via Portainer en se rendant sur la page du conteneur et en cliquant sur « Console » dans la partie « Container Status »

Choix de la commande et de l’utilisateur avec le quel on l’exécute.

Et en cliquant sur « Connect » on obtient une console interactive comme avec la commande docker exec -ti.

On peut maintenant utiliser la commande mysql afin d’interagir avec le serveur MariaDB et créer nos utilisateurs et bases de données:

# mysql -ptest
On peut maintenant interagir avec le système MySQL

L’argument -p suivi du mot de passe représente le mot de passe de l’utilisateur root afin de se connecter. Ici notre mot de passe est « test », on peut aussi l’entrer en mode interactif en indiquant rien après la lettre « p » de l’argument.

Ajoutons maintenant les deux utilisateurs ainsi que les bases de données:

MariaDB [(none)]> CREATE USER 'wordpress'@'%' IDENTIFIED BY 'wordpress';
MariaDB [(none)]> CREATE USER 'nextcloud'@'%' IDENTIFIED BY 'nextcloud';
MariaDB [(none)]> CREATE DATABASE wordpress;
MariaDB [(none)]> CREATE DATABASE nextcloud;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'%';
MariaDB [(none)]> FLUSH PRIVILEGES;

Le mot de passe des utilisateurs sont indiqué par « IDENTIFIED BY 'mot_de_passe'« .

Le serveur MariaDB est maintenant prêt à accueillir nos données !

Déploiement de NextCloud

NextCloud est une solution pour stocker vos fichiers, organiser vos agendas, lire vos mails, et bien plus !

Voici les commande docker pour créer le volume, le conteneur et connecter le conteneur au réseau database:

# docker volume create nextcloud
# docker run -d --restart=always --name=nextcloud --network=proxy -m 2G --cpus 1.5 -v nextcloud:/var/www/html -l traefik.enable=true -l traefik.http.routers.nextcloud.entryPoints=websecure -l traefik.http.routers.nextcloud.rule="Host(\`nextcloud.gouint.fr\`)" -l traefik.http.routers.nextcloud.tls=true -l traefik.http.routers.nextcloud.tls.certresolver=letsencrypt -l traefik.docker.network=proxy -u 1000 nextcloud
# docker network connect database nextcloud

Le label traefik.docker.network permet d’indiquer via quel réseau Traefik doit atteindre le conteneur.
L’argument -u indique à docker que l’utilisateur par défaut dans le conteneur ne sera pas « root », cela ajoute une couche de sécurité car le conteneur n’utilisera pas l’utilisateur root comme utilisateur principal ! L’utilisateur ayant pour id « 1000 » est le premier utilisateur par défaut sous linux hors root, il n’aura pas de nom dans ce conteneur.

Avec l’interface de portainer, il faut tout d’abord créer un volume de stockage via la page « Volume »:

Page de gestion des volumes

On nomme le volume « nextcloud » et on laisse les autres options par défaut.

Il est possible de créer différents types de volumes en fonction de son driver, ou utiliser un montage NFS / CIFS. Ces options équivalent aux arguments --driver et --opt de la commande docker volume create.
Documentation de la commande docker volume create.

Une fois le volume créé on se rend sur la page des conteneurs pour en créer un nouveau avec le bouton « + Add container ».
On configure le nom et l’image du conteneur:

Puis dans les options avancées plus bas il faut configurer:

Command & Logging:

On limite l’utilisateur du conteneur afin qu’il ne soit pas « root ».

Volumes :

On monte le volume « nextcloud » sur le dossier /var/www/html

Network:

Le conteneur sera par défaut dans le réseau proxy

Labels:

On ajoute les labels relatifs à Traefik

Restart policy:

Afin que le conteneur redémarre quoi qu’il arrive

Runtime & Resources:

On limite les ressources du conteneur.

Ceci fait, vous pouvez déployer votre conteneur ! Mais il faut maintenant connecter le conteneur au réseau database afin que NextCloud puisse communiquer avec le conteneur MariaDB, rendez vous sur la page des conteneurs, cliquez sur le conteneur « nextcloud » et descendez en bas de la page pour rejoindre le réseau:

Selectionnez le réseau et cliquez sur « Join network »

Le conteneur est maintenant dans le réseau database et a accès au conteneur MariaDB !

Rendez vous sur votre domaine relié à nextcloud et configurez votre compte d’administrateur ainsi que l’accès à la base de données:

mariadb étant le nom de notre conteneur MariaDB.

Une fois l’installation terminée, vous devriez arriver sur le dashboard de NextCloud:

Nextcloud installé avec succès

Vous pouvez maintenant relier vos différents comptes mails, héberger vos fichiers et même avoir une application de synchronisation type Dropbox, Mega, Hubic (pour les « anciens ») sur tous vos appareils, les partager avec des utilisateurs internes à votre NextCloud ou externes (par mail ou avec la fédération).
Bref, un outil parfait pour l’auto hébergement de vos données tout en étant intuitif et modulable !

Déploiement de Apache & PHP pour WordPress

WordPress est un CMS bien connu, il permet de réaliser des sites internet de tout type (principalement vitrine, e-commerce, blog). Il se sert de PHP (comme NextCloud) et est compatible avec Nginx ou Apache, ce dernier sera utilisé ici.
L’image de WordPress ne sera pas utilisée, afin de généraliser l’installation d’un CMS quel qu’il soit.
Nous utiliserons l’image « webdevops/php-apache » avec la version 8.0 de PHP, c’est l’image embarquant PHP-FPM et Apache en une la plus téléchargé sur docker.

Commandes docker:

# docker volume create wordpress
# docker run -d --name=wordpress --restart=always --network=proxy -m 2G --cpus 1.5 -v wordpress:/app -l traefik.enable=true -l traefik.http.routers.wordpress.entryPoints=websecure -l traefik.http.routers.wordpress.rule="Host(\`wordpress.gouint.fr\`)" -l traefik.http.routers.wordpress.tls=true -l traefik.http.routers.wordpress.tls.certresolver=letsencrypt -l traefik.docker.network=proxy -u 1000 webdevops/php-apache:8.0
# docker network connect database wordpress

Pour le créer via Portainer, suivez la même procédure de création que pour Nextcloud, pensez à bien indiquer l’image « webdevops/php-apache:8.0 » ainsi que renseigner les bons labels et un nouveau volume monté sur « /app ».

Par défaut, le dossier « /app » qui contient le site hébergé est vide, nous allons entrer en terminal interactif dans le conteneur afin d’installer wordpress:

root@docker:~# docker exec -ti wordpress bash
application@9794dfbc5bf3:/$ cd app/
application@9794dfbc5bf3:/app$ wget https://fr.wordpress.org/latest-fr_FR.zip
application@9794dfbc5bf3:/app$ unzip latest-fr_FR.zip
application@9794dfbc5bf3:/app$ mv wordpress/* .
application@9794dfbc5bf3:/app$ rmdir wordpress

Dans l’ordre:

  • On rentre dans le conteneur wordpress.
  • On va dans le dossier « app » qui est le dossier du site hébergé.
  • On télécharge la dernière version de wordpress
  • On la dé-zip
  • On déplace le contenu du dossier wordpress dans le dossier courant (/app)
  • On supprime le dossier wordpress qui est vide

Ensuite, il faut éditer le fichier wp-config-sample.php et ajouter après le tag php <?php:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO']  )  &&  'https'  == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
    $_SERVER['HTTPS']  =  'on';
}

if ( isset( $_SERVER['CF-CONNECTING-IP'] ) ) {
    $_SERVER['REMOTE_ADDR']  = $_SERVER['CF-CONNECTING-IP'];
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR']  ) ) {
    $http_x_headers =  explode(  ',', $_SERVER['HTTP_X_FORWARDED_FOR']  );
    $_SERVER['REMOTE_ADDR']  = $http_x_headers[0];
}

Ce code permet d’indiquer à PHP que la requête a été servie via HTTPS et que l’adresse IP du visiteur se trouve dans le champs header « X-Forwarded-For » ajouté par le proxy Traefik ou dans le champ « CF-Connectif-IP » ajouté par le proxy CloudFlare si utilisé. Certains CMS gèrent cela nativement, mais pas WordPress d’où le fait qu’on soit obligé de le faire comme cela.

On peut ensuite se rendre sur l’installation de WordPress, par défaut le CSS et le JavaScript ne seront pas chargés car la configuration de l’installation ne prend pas en compte le fichier wp-config-sample.php pour servir le CSS et le JavaScript via HTTPS, il le sert donc en HTTP mais cela n’est pas accepté par votre navigateur car le site est chargé en HTTPS (mixed content).

On clique sur « C’est parti ! » pour débuter la configuration.

On rempli ensuite le formulaire avec les informations de la base de données:

Si vous avez tout configuré correctement, voici le résultat une fois le formulaire envoyé:

Il ne reste plus qu’a configurer notre site et lancer l’installation ! (Vu que nous venons de configurer WordPress, le CSS et le JavaScript se charge enfin correctement)

Et voila ! WordPress est installé !

Conclusion

Si vous avez correctement suivi ce guide, vous savez maintenant comment déployer plusieurs logiciels « web » derrière Traefik sur votre serveur avec Docker !

J’espère que ce guide vous a plu et qu’il n’a pas été trop long !
Si le guide ne fonctionne pas et que vous pensez qu’il n’est pas à jour, contactez moi et je le mettrai à jour dans la mesure du possible.
Si vous rencontrez des difficultés lors de l’exécution de ce guide, vous pouvez me contacter via la rubrique « Contactez moi » présente sur la page d’accueil de ce site.

Remerciements:
Christian, pour la machine virtuelle et la relecture.
Emre, pour la relecture.
Clément, pour la relecture.

Voici quelques liens qui pourraient vous être utiles:
Documentation Docker
Documentation Traefik
Documentation Portainer
Hub Docker (dictionnaire d’image de conteneur)
Github NDPPD

Version du guide: 1.0 (Mai 2021)

 

Laisser un commentaire

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