Introduction
WordPress est l'un des systèmes de gestion de contenu (CMS) les plus populaires du marché. Statistiquement, il propulse plus de 39 % de tous les sites web que vous voyez sur le World Wide Web. C'est un choix populaire en raison de son extensibilité via des extensions (plugins) et de son système de modèles flexible. Il vous permet de modifier son apparence en quelques secondes. De plus, son administration peut se faire via l'interface web sans nécessiter de grandes connaissances techniques.
De plus, WordPress est gratuit et open-source, et repose sur une base de données MySQL avec un traitement PHP. Vous pouvez déployer WordPress sur une pile LAMP (Linux, Apache, MySQL et PHP) ou une pile LEMP (Linux, Nginx, MySQL et PHP). Cependant, configurer cette pile à chaque fois que vous souhaitez effectuer un déploiement s'avère fastidieux.
Heureusement, les méthodes modernes de distribution de logiciels telles que le cloud computing, Docker, et Docker Compose ont grandement facilité l'expérience globale des développeurs. Ces outils simplifient le processus de configuration de n'importe quelle pile en évitant la surcharge liée à l'installation et à la configuration de composants individuels à chaque fois que vous souhaitez déployer une application. Au lieu de cela, vous écrivez des fichiers de configuration qui seront utilisés pour récupérer et créer des images, puis les exécuter dans des conteneurs Docker, ce qui vous permet de déployer votre application avec une seule commande.
Les conteneurs sont des environnements standardisés, légers, virtualisés, portables et définis par logiciel qui permettent au logiciel de s'exécuter de manière isolée des autres logiciels s'exécutant sur la machine hôte physique. Docker Compose vous permet de gérer plusieurs conteneurs et de vous assurer qu'ils communiquent entre eux. Par exemple, le code source d'une application et une base de données doivent communiquer.
Dans ce tutoriel, nous allons créer une application WordPress multi-conteneurs. Une application WordPress complète nécessite trois conteneurs : une base de données MySQL, un serveur Nginx et le code source de WordPress. La sécurité étant une priorité pour les sites web modernes, nous obtiendrons un certificat SSL auprès de Let’s Encrypt afin de sécuriser votre installation. Ensuite, nous configurerons une tâche cron pour vérifier et renouveler périodiquement les certificats afin de maintenir la sécurité de votre site web en continu.
Prérequis
- Comme il s'agit d'un tutoriel pratique, vous devriez disposer d'une installation d'Ubuntu 20.04 comme environnement d'exploitation initial. Vous devriez également avoir un utilisateur non-root avec des privilèges sudo. Voici un tutoriel étape par étape pour vous aider à configurer votre serveur Ubuntu.
- Vous devez également installer Docker. Vous pouvez vous référer à ce tutoriel sur comment installer et utiliser Docker sur Ubuntu 18.04.
- Une installation de Docker Compose. Vous pouvez suivre l'étape 1 du tutoriel Comment installer et configurer Docker Compose sur Ubuntu 20.04.
- Un nom de domaine enregistré est requis pour obtenir un certificat TLS/SSL auprès de Let’s Encrypt. Pour les besoins de ce tutoriel, nous utiliserons
example.com. - Configurez les enregistrements DNS pour diriger le trafic vers votre VPS. Vous avez besoin de deux enregistrements DNS :
- Un enregistrement A avec
example.compointant vers l'adresse IP publique de votre serveur. - Un enregistrement A avec
www.example.compointant vers l'adresse IP publique de votre serveur.
- Un enregistrement A avec
Étape 1 : Définir les configurations pour le serveur Web
Le serveur web héberge les fichiers de votre site web et permet aux utilisateurs d'accéder à votre application web. Il est donc tout à fait approprié de définir la configuration du serveur web dès la première étape. Nous allons définir un fichier de configuration de serveur Nginx qui inclura des blocs de localisation spécifiques à WordPress. Nous inclurons également des blocs de localisation pour diriger les requêtes de vérification de Let’s Encrypt vers le client Certbot pour les renouvellements automatiques de certificat.
Commençons par créer un répertoire pour le projet. Vous pouvez choisir le nom de répertoire que vous préférez. Nous utiliserons wordpress_docker pour ce tutoriel. Entrez la commande suivante pour créer le répertoire et y accéder :
|
1 |
mkdir wordpress_docker && cd wordpress_docker |
Ensuite, créez un répertoire pour contenir les fichiers de configuration Nginx avec la commande :
|
1 |
mkdir nginx-conf |
Utilisez nano pour ouvrir le fichier avec la commande suivante :
|
1 |
nano nginx-conf/nginx.conf |
Dans ce fichier, nous allons définir les directives de base pour la configuration d'un bloc de serveur Nginx. Celles-ci incluent des directives pour le nom du serveur, la racine du document et les blocs de localisation pour diriger les requêtes du plugin Certbot pour les certificats, les fichiers statiques et le traitement PHP. Vous pouvez lire notre tutoriel sur Comment sécuriser Nginx avec Let’s Encrypt pour en savoir plus. Ajoutez le code suivant au fichier, en remplaçant example.com par votre nom de domaine enregistré :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Définissons les sections que vous avez ajoutées :
-
Directives :
listen: elle indique à Nginx d'écouter sur le port80. Cela permet d'utiliser le webroot de Certbot pour effectuer des demandes de certificat. Une fois que nous aurons obtenu un certificat SSL, nous mettrons à jour cette configuration pour utiliser le port443.server_name: cela définit le domaine que cette configuration doit gérer. Le trafic vers le nom de domaine défini ici sera dirigé vers ce bloc de serveur particulier, et donc vers la racine du documentroot.root: elle définit le répertoire racine pour les requêtes vers le nom de domaine ci-dessus. C'est généralement le répertoire contenant les fichiers réels de notre site web. Nous avons défini le répertoire sur/var/www/html. Il sera créé en tant que point de montage Docker pendant le temps de construction du conteneur. Nous définirons les instructions pour ce processus à l'intérieur du Dockerfile WordPress.index: cela définit les fichiers qui seront utilisés comme index ou point d'entrée de votre serveur web lors du traitement des requêtes. Nous avons déplacé index.php avant index.html afin que Nginx donne la priorité àindex.php.
-
Blocs Location :
location ~ /.well-known/acme-challenge: gère les requêtes vers le répertoire bien connu (well-known) où Certbot ajoute un fichier temporaire pour valider que le DNS pour le domaine spécifié dirige vers le serveur particulier auprès duquel nous demandons des certificats SSL. C'est pourquoi vous devez ajouter un domaine valide pour que cette étape fonctionne au lieu duexample.comque nous utilisons dans ce tutoriel.location /: récupère les requêtes URI et donne le contrôle à WordPressindex.phppour demander des arguments à traiter.location ~ \.php$: gère le traitement PHP et transmet la requête au conteneur WordPress (nous définirons un fichier de configuration pour cela dans une étape ultérieure). Nous avons défini des configurations spécifiques au protocole FastCGI ici car l'image Docker WordPress sera basée sur l'image php:fpm. Nginx utilise un processeur PHP indépendant pour les requêtes spécifiques à PHP. Nous utiliserons le processeurphp-fpmqui est fourni avec l'image Dockerphp:fpm.location ~ /\.ht: gère les fichiers.htaccessque Nginx n'utilise pas. La directivedeny allgarantit que ces fichiers ne sont jamais servis aux visiteurs du site web.location = /favicon.ico, location = /robots.txt: comme on le voit dans la définition, cela empêche la journalisation des requêtes vers les fichiers/favicon.icoet/robots.txt.location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: désactive la journalisation des requêtes vers les fichiers statiques et garantit qu'ils sont mis en cache pour réduire la charge sur le serveur.
Vous pouvez maintenant enregistrer et fermer le fichier en appuyant sur CTRL+X, Y, puis ENTRÉE. Cela termine la première étape.
Étape 2 : Définir les variables d'environnement
Les variables d'environnement sont nécessaires pour faciliter la communication entre l'application WordPress et la base de données. Elles garantissent également la persistance des données de l'application. Les variables d'environnement comprennent des informations sensibles telles que les identifiants de la base de données et des informations non sensibles telles que le nom de la base de données et l'hôte.
Pour des raisons de sécurité, c'est toujours une bonne idée de ne pas ajouter d'informations sensibles aux dépôts de projet. Par conséquent, au lieu de définir les valeurs sensibles dans le fichier Docker Compose, nous définirons les identifiants MySQL à l'intérieur des fichiers .env qui ne seront pas validés dans le dépôt du projet et ne risqueront pas d'être exposés publiquement. À l'intérieur de la racine du projet root ~/wordpress_docker, ouvrez le fichier .env :
|
1 |
nano .env |
|
1 2 3 |
MYSQL_ROOT_PASSWORD=votre_mot_de_passe_root_fort MYSQL_USER=votre_utilisateur_base_de_donnees_wordpress MYSQL_PASSWORD=mot_de_passe_base_de_donnees_wordpress_fort |
La prochaine chose que vous devez faire est d'ajouter le fichier .env aux fichiers .gitignore et .dockerignore pour vous assurer qu'il ne soit pas ajouté respectivement à vos dépôts ou à vos images Docker.
Ce n'est pas nécessaire pour ce tutoriel, mais si vous souhaitez travailler avec Git pour le contrôle de version, entrez la commande suivante pour initialiser le répertoire actuel en tant que dépôt git :
|
1 |
git init |
Ouvrez le fichier .gitignore avec nano :
|
1 |
nano .gitignore |
Ajoutez la ligne suivante :
|
1 |
.env |
Enregistrez et fermez le fichier. Ensuite, ouvrez le fichier .dockerignore avec nano :
|
1 |
nano .dockerignore |
Ajoutez la ligne suivante :
|
1 |
.env |
Tant que vous y êtes, vous pouvez éventuellement ajouter d'autres fichiers et répertoires associés au développement de votre application :
|
1 2 3 |
.env .git docker-compose.yml |
Enregistrez et fermez le fichier une fois terminé. C'est tout pour cette étape. Passons à la définition de Docker Compose.
Étape 3 : Configurer les services avec Docker Compose
Docker Compose utilise un docker-compose.yml fichier pour construire des images. Ce fichier contient des définitions de service pour la configuration complète d'une application. Les définitions de service sont essentiellement des instructions sur la façon dont un conteneur va s'exécuter. Un service est un conteneur en cours d'exécution réel.
Docker Compose permet de définir différents services pour des applications multi-conteneurs en liant les différents services entre eux avec des réseaux et des volumes partagés. Vous verrez cela en action car nous allons définir trois conteneurs pour notre application : un serveur web, une installation WordPress et une base de données. Nous ajouterons un quatrième conteneur pour exécuter le client Certbot pour les renouvellements de certificats.
Saisissez la commande suivante pour créer le docker-compose.yml fichier :
|
1 |
nano docker-compose.yml |
La première ligne d'un fichier docker-compose.yml est la ligne de définition de la version. Nous avons défini 3 pour la nôtre. Ensuite, vous pouvez commencer à définir vos services. Ajoutez l'extrait de code suivant dans le fichier pour définir le service db :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: '3' services: #Service MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network |
Voyons en détail ce que nous avons dans les définitions du service db ci-dessous :
image: détermine l'image sur laquelle le conteneur sera basé. Il est toujours préférable de spécifier une version spécifique (mysql:8.0) plutôt que d'utiliser la balise latest (mysql:latest) car les futures versions des images MySQL peuvent entrer en conflit avec notre application si nous devons reconstruire cette image. Vous trouverez plus d'informations sur les bonnes pratiques pour les Dockerfiles sur la documentation officielle de Dockerfile.container_name: nous spécifions ici le nom du conteneur.restart: cette directive détermine le comportement de redémarrage du conteneur. Par défaut, c'estnomais nous l'avons configuré pour toujoursredémarrerà moins qu'il ne soit arrêté manuellement.env_file: cette directive est utilisée pour spécifier l'emplacement du fichier contenant les variables d'environnement (.env) utilisées par notre application.environment: utilisé pour spécifier des variables d'environnement supplémentaires. Dans ce tutoriel, nous avons spécifié la variableMYSQL_DATABASEpour contenir le nom de la base de données de notre application. Le nom de la base de données peut être inclus dans ledocker-compose.yml.volumes: utilisé pour spécifier les emplacements de montage. Dans notre exemple, nous avons monté un volume nommé appelé dbdata sur le répertoire/var/lib/mysqldu conteneur, qui est généralement le répertoire de données standard pour MySQL.command: cette directive spécifie une commande qui remplacera l'instruction CMD par défaut de l'image. Nous avons ajouté une option à la commande standardmysqldde l'image Docker qui démarre le serveur MySQL à l'intérieur du conteneur. L'option que nous avons ajoutée est--default-authentication-plugin=mysql_native_password, qui met à jour le plugin d'authentification par défaut de MySQL pour utiliser l'authentification par mot de passe (mysql_native_password). Ceci est nécessaire pour que votre application PHP (WordPress) fonctionne, car elle utilise un nom d'utilisateur et un mot de passe pour accéder à la base de données. Dans les versions plus récentes de MySQL, le plugin d'authentification par défaut a changé. Cependant, la plupart des applications utilisent l'authentification par mot de passe. Par conséquent, vous devez modifier ce paramètre pour que l'application fonctionne.networks: cette directive est utilisée pour spécifier que le servicedbdoit rejoindre le réseauapp-network, que nous définirons au fur et à mesure du tutoriel.
Ensuite, définissons la configuration du service pour notre application WordPress. Nous appellerons le service et container_name app. Ajoutez le fragment de code suivant sous la définition du service db, en gardant à l'esprit l'indentation correcte :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#Service de code d'application WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network |
Tout comme nous l'avons fait avec le service db, nous avons nommé notre conteneur et défini la politique de redémarrage. D'autres options que nous avons ajoutées sont définies ci-dessous :
depends_on: cette directive garantit que les conteneurs sont démarrés dans l'ordre de dépendance. Dans notre cas, le conteneurappdépend du conteneurdb. Par conséquent, il démarrera après le démarrage du conteneurdb. Cela doit se produire dans cet ordre car l'application WordPress dépend de la disponibilité d'une base de données MySQL pour fonctionner.image: comme on peut le voir dans le fragment de code, nous utiliserons l'image WordPress version 5.1.1 fpm alpine image. Nous avions expliqué le fonctionnement du processeurphp-fpmdont Nginx a besoin pour le traitement PHP. Cette image s'en charge. L'image alpine basée sur le projet Alpine Linux permet de réduire la taille de l'image. Si vous avez besoin de plus d'informations sur les variantes d'images, vous pouvez suivre ce lien vers les images WordPress sur Docker Hub.env_file: spécifie l'emplacement du fichier.envqui contient les identifiants de la base de données.environment: cette directive définit des variables d'environnement supplémentaires. Dans notre cas, nous définissons les variables attendues par WordPress et leur attribuons les valeurs des variables de notre fichier.env. Il s'agit deWORDPRESS_DB_USER,WORDPRESS_DB_PASSWORD, etWORDPRESS_DB_HOSTqui fait référence au serveur MySQL s'exécutant sur le conteneurdb, accessible depuis le port par défaut de MySQL3306. Enfin, vous voyezWORDPRESS_DB_NAMEque nous avons défini sur wordpress. La même valeur est spécifiée dans la définition du service MySQL dans le conteneur db :MYSQL_DATABASE=wordpress.volumes: cette directive monte un volume appelé app sur le point de montage/var/www/html, créé par l'image WordPress. Le nommage des volumes permet de partager le code de l'application avec d'autres conteneurs.networks: enfin, nous ajoutons le conteneur app au réseauapp-networkpour s'assurer qu'il communique avec les autres conteneurs du réseau.
Ce sera tout pour le conteneur de service app pour l'image WordPress. Définissons maintenant le service webserver pour l'image Nginx. Tout d'abord, ajoutez le fragment de code suivant sous la définition du service app dans votre fichier docker-compose.yml :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#Service Nginx de serveur web webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
Nous avons déjà expliqué l'option depends_on. Dans le cas de ce service webserver, le conteneur démarrera après le démarrage du conteneur app. Le conteneur du serveur web est basé sur l'image Nginx alpine. Il a une politique de redémarrage similaire à celle des définitions de service précédentes. Les autres options de la définition du service webserver incluent :
ports: lie les ports entre la machine hôte et le conteneur. À l'étape 1, nous avions défini le port80dans le fichiernginx.conf. Ce port est mappé au port80sur le conteneur.volumes: nous avons une combinaison de bind mounts et de volumes nommés sous cette option :app:/var/www/html: cette définition de volume monte l'application WordPress dans le répertoire/var/www/htmlque nous avions précédemment défini comme racine dans le bloc de serveur Nginx../nginx-conf:/etc/nginx/conf.d : cette définition lie par montage (bind mount) le répertoire de configuration Nginx de la machine hôte au répertoire de configuration Nginx que nous avons défini pour le conteneur. Par conséquent, toute modification sur la machine hôte est automatiquement répercutée dans le conteneur.certbot-etc:/etc/letsencrypt: cette définition monte les certificats et clés Let’s Encrypt pour le domaine dans le répertoire approprié du conteneur.
networks: comme dans les définitions de service précédentes, la directivenetworksajoute le service webserver auapp-networks.
Puisque nous en avons terminé avec la définition du serveur web, ajoutons les instructions pour le service Certbot. Celui-ci s'occupera d'obtenir vos certificats TLS/SSL auprès de Let’s Encrypt. Si vous souhaitez en savoir plus sur la sécurisation d'un serveur Nginx, ce tutoriel sur comment sécuriser Nginx with Let’s Encrypt est une bonne source.
Ensuite, ajoutez l'extrait de code suivant sous le service webserver. N'oubliez pas de définir votre nom de domaine et votre adresse e-mail corrects :
|
1 2 3 4 5 6 7 8 9 10 |
#certbot service certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com |
L'image certbot ne démarrera qu'après le démarrage de webserver, en raison de la directive depends_on. Docker Compose va récupérer l'image Certbot depuis Docker Hub comme défini.
Sous la définition des volumes, le conteneur Certbot partagera les certificats et la clé de domaine dans certbot-etc avec le conteneur Nginx webserver et le code de l'application avec le conteneur app conteneur.
Sous la définition command, nous avons spécifié une sous-commande pour exécuter la commande Certbot par défaut du conteneur certonly avec les options supplémentaires listées ci-dessous :
-
--webroot: spécifie l'utilisation du plugin webroot qui place les fichiers dans le dossier webroot pour l'authentification.--webroot-path: spécifie le chemin du répertoire webroot.--agree-tos: spécifie que vous acceptez les conditions d'utilisation d'ACME.--no-eff-email: spécifie que vous ne souhaitez pas partager votre e-mail avec l'EFF. Vous pouvez omettre cela si vous souhaitez le partager.--staging: indique à Certbot que vous souhaitez d'abord obtenir des certificats de test auprès de l'environnement de staging de Let’s Encrypt pour tester votre configuration avant d'obtenir le certificat réel. Let’s Encrypt applique une limitation du taux de requêtes par domaine. Par conséquent, tester d'abord votre configuration vous aidera à éviter que votre domaine ne soit limité.-d: cette option prend les noms de domaine pour la demande de certificat. Dans ce tutoriel, nous avons inclusexample.cometwww.example.com. Veuillez spécifier votre domaine réellement enregistré.
Notre fichier docker-compose.yml est presque complet. Cependant, vous devez également ajouter les définitions de réseau et de volume sous le service Certbot :
|
1 2 3 4 5 6 7 8 9 10 |
#Volumes volumes: certbot-etc: app: dbdata: #Networks networks: app-network: driver: bridge |
La clé volumes définit les volumes à partager avec tous les services (conteneurs) définis dans ce fichier compose : certbot-etc, app, et dbdata. Le contenu des volumes créés par Docker est stocké dans un répertoire géré par Docker sur le système de fichiers hôte : /var/lib/docker/volumes/. Les contenus de chaque volume sont ensuite montés sur n'importe quel conteneur qui utilise le volume. Cela permet de partager des données et du code entre les conteneurs.
La networks définit le réseau en pont qui permet la communication entre les conteneurs. Les conteneurs sur le même réseau en pont tels que webserver et db peuvent communiquer de manière sécurisée via des ports sans exposer le trafic au réseau externe. Nous n'exposons que le port 80 pour permettre l'accès aux pages du site web frontal.
Le fichier docker-compose.yml complet ressemblera à ceci :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
version: '3' services: #Service MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network #Service de code d'application WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Service de serveur web Nginx webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #Service certbot certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com #Volumes volumes: certbot-etc: app: dbdata: #Réseaux networks: app-network: driver: bridge |
Vous pouvez sauvegarder et fermer le fichier. Dans l'étape suivante, nous allons démarrer et tester le conteneur et les demandes de certificat.
Étape 4 : Exécution des conteneurs et obtention des certificats SSL
Le plus grand avantage de Docker Compose est que, une fois que vous avez défini tous vos services dans le docker-compose.yml fichier, vous pouvez démarrer tous les conteneurs avec une seule commande : docker-compose up. La commande exécute chaque instruction spécifiée. Si les requêtes de domaine réussissent, vous devriez pouvoir voir le code de sortie correct dans votre terminal. Entrez la commande suivante pour créer les conteneurs. Le -d flag sert à exécuter les conteneurs en arrière-plan :
|
1 |
docker-compose up -d |
Si vous voyez un résultat similaire à la capture d'écran ci-dessous, alors les services ont été créés avec succès :
Pour confirmer le statut des services, exécutez la commande docker-compose ps :
|
1 |
docker-compose ps |
Le résultat de la commande est tel qu'indiqué ci-dessous si tout s'est bien passé. L'état des conteneurs app, db, et webserver doit être « up », et le conteneur certbot doit avoir le statut Exit0 :
Si vous voyez autre chose que Up dans la colonne d'état pour app, db ou webserver, ou un statut Exit qui n'est pas 0 pour le conteneur certbot , alors quelque chose s'est mal passé. Vous pouvez vérifier les journaux de chaque conteneur à l'aide de la commande docker-compose logs, et spécifier le service_name:
|
1 |
docker-compose logs service_name |
Par exemple, vous pouvez vérifier les journaux du conteneur certbot en saisissant la commande suivante :
|
1 |
docker-compose logs certbot |
Pour vérifier si les certificats ont été montés sur le conteneur webserver, utilisez la commande docker-compose exec :
|
1 |
docker-compose exec webserver ls -la /etc/letsencrypt/live |
Si vous avez utilisé un nom de domaine réellement enregistré autre que example.com et que les demandes de certificat ont réussi, vous devriez voir un résultat similaire à ceci :
Une fois que vous avez confirmé que la demande de certificat a réussi, vous pouvez modifier le fichier docker-compose.yml et supprimer le flag --staging. Ouvrez le fichier avec nano:
|
1 |
nano docker-compose.yml |
Faites défiler vers le bas jusqu'à la section de définition du service Certbot, dans l'option command, et remplacez le flag --staging par le flag --force-renewal. Cela indique à Certbot que vous demandez un renouvellement de certificat pour un certificat du même domaine. Votre définition du service Certbot devrait maintenant ressembler à ceci :
|
1 2 3 4 5 6 7 8 9 10 |
#certbot service certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com |
Enregistrez le fichier lorsque vous avez terminé l'édition.
Entrez la commande suivante pour recréer le conteneur certbot. Le flag --no-deps inclus indique à Compose d'ignorer le redémarrage du service de serveur web puisqu'il est déjà en cours d'exécution :
|
1 |
docker-compose up --force-recreate --no-deps Certbot |
La commande produit la capture d'écran suivante, montrant que la demande de certificat a réussi :
C'est tout pour cette étape. Dans l'étape suivante, vous modifierez le fichier de configuration Nginx pour inclure le certificat SSL.
Étape 5 : Activation de SSL dans la configuration Nginx et la définition du service
Pour que Nginx serve le trafic via SSL sécurisé, vous allez d'abord modifier le fichier de configuration Nginx pour ajouter une redirection HTTP vers HTTPS. Ensuite, vous devez spécifier les emplacements du certificat et de la clé, et enfin ajouter des paramètres de sécurité et des en-têtes.
Avant de modifier le fichier de configuration, vous devriez obtenir les paramètres de sécurité Nginx recommandés depuis le dépôt GitHub de Certbot en utilisant curl avec la commande suivante :
|
1 |
curl -sSLo nginx-conf/options-ssl-nginx.conf |
La commande s'exécute et enregistre les paramètres qu'elle récupère dans un fichier nommé options-ssl-nginx.conf, dans le répertoire nginx-conf . Supprimez le fichier de configuration Nginx afin que nous puissions en créer un nouveau avec les commandes suivantes :
|
1 2 |
rm nginx-conf/nginx.conf nano nginx-conf/nginx.conf |
Dans le fichier nginx.conf désormais vide, ajoutez le code suivant qui inclut une redirection de HTTP vers HTTPS, de protocoles de certificats SSL , et d'en-têtes de sécurité. Comme vous l'avez fait précédemment, remplacez le example.com par votre propre domaine enregistré :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Sécurité-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # activez la sécurité de transport stricte uniquement si vous en comprenez les implications location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } } |
Dans le premier bloc de serveur qui gère les requêtes non sécurisées utilisant le port 80, nous spécifions la racine web pour les demandes de renouvellement Certbot. Nous incluons également une directive de redirection qui redirige les requêtes HTTP vers HTTPS.
Le second bloc de serveur gère le trafic sécurisé HTTPS arrivant sur le port 443. Comme vous pouvez le voir, nous activons également SSL et HTTP2. HTTP/2 améliore les performances de votre serveur. Vous pouvez en savoir plus à ce sujet dans la documentation officielle de Nginx sur HTTP/2.
Dans ce bloc, nous avons également spécifié que Nginx inclut les emplacements du certificat SSL et de la clé, ainsi que les paramètres de sécurité Certbot recommandés que curl a sauvegardés dans le dossier nginx-conf/options-ssl-nginx.conf.
Les en-têtes de sécurité supplémentaires servent à améliorer les notes de votre site web sur des sites de test de sécurité tels que Security Headers et SSL Labs. Vous pouvez suivre les liens sur ces en-têtes pour en savoir plus : X-Frame-Options, Referrer Policy, X-Content-Type-Options, X-XSS-Protection, Content-Security-Policy. Nous avons commenté l'en-tête HTTP Strict Transport Security (HSTS). Vous êtes libre de vous renseigner sur sa fonctionnalité de préchargement et de décider si vous souhaitez l'activer.
Le reste des directives telles que root, index, et les blocs de localisation spécifiques à WordPress restent tels que décrits à l' Étape 1. Vous pouvez maintenant enregistrer et fermer le fichier lorsque vous avez terminé l'édition.
Maintenant que nous avons activé le trafic HTTPS qui utilise le port 443,, nous devons également activer le port sur la définition de service du serveur web. Entrez la commande suivante pour ouvrir le fichier docker-compose.yml avec nano :
|
1 |
nano docker-compose.yml |
Dans la section du serveur web sous l'option ports, ajoutez un mappage pour le port 443 comme mis en évidence ci-dessous :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
Le fichier docker-compose.yml complet devrait maintenant ressembler à ceci :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
version: '3' services: # Service MySQL db: image: mysql:8.0 container_name: db restart: unless-stopped env_file: .env environment: - MYSQL_DATABASE=wordpress volumes: - dbdata:/var/lib/mysql command: '--default-authentication-plugin=mysql_native_password' networks: - app-network # Service de code d'application WordPress app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app restart: unless-stopped env_file: .env environment: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network # Service de serveur Web Nginx webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network # Service certbot certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com # Volumes volumes: certbot-etc: app: dbdata: # Réseaux networks: app-network: driver: bridge |
Une fois que vous avez confirmé que tout semble correct, enregistrez et fermez le fichier. Après cela, exécutez la commande suivante pour recréer le webserver service :
|
1 |
docker-compose up -d --force-recreate --no-deps webserver |
|
1 |
docker-compose ps |
Maintenant que tous vos conteneurs fonctionnent, il est possible de procéder à la configuration de WordPress depuis l'interface web.
Étape 6 : Complétez la configuration de votre WordPress depuis l'interface Web
Naviguez vers le nom de domaine de votre serveur pour continuer l'installation. Vous devriez voir la page d'accueil de configuration de WordPress. Elle vous invite à choisir votre langue avant de continuer :
Choisissez votre langue et cliquez sur Continuer pour passer à la page suivante :
Sur cette page, renseignez le titre de votre site web, choisissez un nom d'utilisateur mémorable et un mot de passe fort. Il est recommandé de ne pas utiliser Admin comme nom d'utilisateur pour des raisons de sécurité. Saisissez votre e-mail et cliquez sur le bouton Installer WordPress pour commencer l'installation de WordPress.
Une fois l'installation terminée, vous serez redirigé vers l'écran de connexion où vous saisirez le nom d'utilisateur et le mot de passe que vous avez définis. Lorsque vous saisirez des identifiants valides, vous devriez voir votre tableau de bord WordPress :
Vous avez maintenant installé WordPress avec succès ! Ensuite, vous devez prendre les mesures nécessaires pour vous assurer que les certificats SSL se renouvelleront automatiquement.
Étape 7 : Configuration du renouvellement automatique des certificats SSL
Les certificats TLS/SSL de Let’s Encrypt ne sont valides que pendant 90 jours. C'est à vous de créer une configuration de renouvellement automatique pour vous assurer qu'ils n'expirent pas. Vous pouvez y parvenir en créant un script et en le planifiant avec l'utilitaire tâche cron. Dans cette étape, nous allons vous montrer comment créer un script qui renouvellera les certificats. Nous le planifierons ensuite avec l'utilitaire de tâche cron pour l'exécuter périodiquement et renouveler les certificats s'ils approchent de leur date d'expiration.
Dans le répertoire de projet wordpress_docker, ouvrez un script nommé ssl_renewer.sh avec nano:
|
1 |
nano ssl_renewer.sh |
Ajoutez le code suivant au script pour gérer le renouvellement automatique et le rechargement de la configuration Nginx. N'oubliez pas de remplacer le nom d'utilisateur en surbrillance par votre nom d'utilisateur non-root :
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose –ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
Dans ce script, nous attribuons le binaire docker-compose à une variable nommée COMPOSE. Nous incluons également l'option –ansi never qui indique au script d'exécuter les commandes docker-compose sans caractères de contrôle ANSI. Nous attribuons ensuite le binaire Docker à une variable nommée DOCKER.
Le script se déplace ensuite dans notre répertoire de projet wordpress_docker et exécute les commandes suivantes :
docker-compose run: démarre le conteneur certbot et remplace la commande que nous avions fournie dans la définition du service certbot. Au lieu d'exécuter la sous-commande certonly, il exécute la sous-commande renew qui renouvellera les certificats SSL/TLS de Let’s Encrypt s'ils sont sur le point d'expirer.docker-compose kill: envoie un signal SIGHUP au conteneurwebserverpour recharger les configurations Nginx. Vous pouvez consulter ce tutoriel de Docker sur comment utiliser l'image Docker officielle de Nginx.docker system prune: cette commande supprime tous les conteneurs et images inutilisés.
Enregistrez et fermez le fichier lorsque vous avez terminé l'édition. Ensuite, exécutez la commande suivante pour le rendre exécutable :
|
1 |
chmod +x ssl_renewer.sh |
Une fois que vous l'avez rendu exécutable, ouvrez votre fichier crontab root pour exécuter le script périodiquement aux intervalles que nous allons spécifier :
|
1 |
sudo crontab -e |
Le crontab vous demande de choisir votre éditeur préféré si c'est la première fois que vous l'utilisez :
Choisissez votre éditeur préféré et appuyez sur Entrée pour ouvrir le fichier. Tout en bas du fichier, ajoutez la ligne suivante :
|
1 |
*/5 * * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
Cela définit l'intervalle à cinq minutes pour nous permettre de tester si notre script de renouvellement fonctionne ou non. Nous avons également spécifié un fichier journal qui contiendra la sortie de la tâche : cron_docker.log.
Attendez cinq minutes et vérifiez le cron.log pour voir si le script a réussi la demande de renouvellement :
|
1 |
tail -f /var/log/cron_docker.log |
Vous devriez voir quelque chose de similaire à la capture d'écran ci-dessous si les requêtes ont réussi :
Maintenant que nous l'avons testé et que nous avons confirmé qu'il fonctionne, vous pouvez modifier le fichier crontab pour spécifier un renouvellement quotidien. Par exemple, vous pouvez spécifier que le script s'exécute chaque jour à 18 h. Pour ce faire, modifiez la dernière ligne du crontab pour qu'elle ressemble à ceci :
|
1 |
0 18 * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
De plus, vous devez supprimer l'option –dry-run du script ssl_renewer.sh pour vous assurer que le renouvellement réel a lieu lors de son exécution. Il devrait ressembler à ceci :
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose --ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
Ensuite, enregistrez et fermez le fichier. Une fois cela fait, la tâche cron maintiendra vos scripts valides en les renouvelant avant la fin des 90 jours.
Conclusion
Si vous êtes arrivé jusqu'ici dans ce tutoriel, vous pouvez vous considérer comme un peu plus proche de devenir ingénieur DevOps. Vous avez réussi à créer un script de configuration Nginx, créé un fichier docker-compose.yml et défini plusieurs services nécessaires pour exécuter une application WordPress avec Docker et Docker Compose. Vous avez obtenu des certificats SSL/TLS auprès de Let’s Encrypt pour vous assurer que votre serveur web est sécurisé. Enfin, vous avez créé une tâche cron pour vous assurer que les certificats n'expirent pas. Bon travail !
Si vous cherchez à approfondir vos connaissances en DevOps, jetez un œil à d'autres ressources sur les conteneurs sur notre blog:
- Découvrir Kubernetes
- Comment déployer une application Node.js (Express.js) avec Docker sur Ubuntu 20.04
- Déployer une application PHP sur un cluster Kubernetes avec Ubuntu 18.04.
- Déploiement de Laravel, Nginx et MySQL avec Docker Compose
Bonne informatique !










Commentaires
Aucun commentaire pour l'instant. Soyez le premier.