One place for hosting & domains

      dimensionner

      Comment dimensionner et sécuriser une application Django avec Docker, Nginx et Let’s Encrypt


      Introduction

      Dans les environnements basés sur le cloud, il existe de multiples façons de faire évoluer et de sécuriser une application Django. En dimensionnant horizontalement et en exécutant plusieurs copies de votre application, vous pouvez construire un système plus tolérant aux défauts et très disponible, tout en augmentant également son débit, afin que les demandes puissent être traitées simultanément. Une manière de faire évoluer à l’échelle horizontale une application Django consiste à fournir des serveurs d’application supplémentaires qui exécutent votre application Django et son serveur HTTP WSGI (comme Gunicorn ou uWSGI). Pour acheminer et distribuer les demandes entrantes sur cet ensemble de serveurs d’application, vous pouvez utiliser un équilibreur de charge et un proxy inverse comme Nginx. Nginx peut également mettre en cache le contenu statique et mettre fin aux connexions TLS (Transport Layer Security Security), utilisées pour fournir des connexions HTTPS, et sécuriser les connexions à votre application.

      L’exécution de votre application Django et du proxy Nginx à l’intérieur des conteneurs Docker garantit que ces composants se comportent de la même manière quel que soit l’environnement dans lequel ils sont déployés. De plus, les conteneurs fournissent de nombreuses fonctionnalités qui facilitent l’emballage et la configuration de votre application.

      Dans ce tutoriel, vous allez à mettre l’échelle horizontalement une application de sondages pour Django et Gunicorn conteneurisé en fournissant deux serveurs d’application qui exécuteront chacune une copie d’un conteneur d’application Django et Gunicorn.

      Vous allez également activer HTTPS, en fournissant et en configurant un troisième serveur proxy qui exécutera un conteneur proxy inverse Nginx et un conteneur client Certbot. Certbot fournira des certificats TLS pour Nginx à partir de l’autorité de certification Let’s Encrypt. Cela garantira que votre site bénéficie d’une cote de sécurité élevée de la part de SSL Labs. Ce serveur proxy recevra toutes les demandes externes de votre application et sera en face des deux serveurs d’application Django en amont. Enfin, vous allez renforcer ce système distribué en limitant l’accès externe au serveur proxy uniquement.

      Conditions préalables

      Pour suivre ce tutoriel, vous aurez besoin de :

      • Trois serveurs Ubuntu 18.04 :

        • Deux serveurs seront des serveurs d’application, utilisés pour exécuter vos applications Django et Gunicorn.
        • Un serveur sera un serveur proxy utilisé pour exécuter Nginx et Certbot.
        • Tous devraient avoir un non-root user avec des privilèges sudo et un pare-feu actif. Pour savoir comment les configurer, veuillez consulter le présent Guide de configuration initiale du serveur.
      • Docker installé sur les trois serveurs. Pour obtenir de l’aide sur l’installation de Docker, suivez les Étapes 1 et 2 de Comment installer et utiliser Docker sur Ubuntu 18.04.

      • Un nom de domaine enregistré. Ce tutoriel utilisera your_domain.comtout au long. Vous pouvez en obtenir un gratuitement sur Freenom ou utiliser le registre de domaine de votre choix.

      • Un enregistrement DNS A avec your_domain.com pointant sur l’adresse IP publique de votre serveur proxy. Vous pouvez suivre cette introduction au DNS DigitalOcean pour plus de détails sur la façon de l’ajouter à un compte DigitalOcean, si c’est ce que vous utilisez.

      • Un object storage bucket S3 comme un espace DigitalOceanpour stocker les fichiers statiques de votre projet Django et un ensemble de clés d’accès pour cet espace. Pour apprendre à créer un espace, consultez la documentation produit Comment créer des espaces. Pour apprendre à créer des clés d’accès pour les espaces, consultez Partager l’accès aux espaces avec les clés d’accès. Avec des modifications mineures, vous pouvez utiliser n’importe quel service de stockage d’objets que le plugin django-storages prend en charge.

      • Une instance serveur PostgreSQL, une base de données et un utilisateur pour votre application Django. Avec des modifications mineures, vous pouvez utiliser n’importe quelle base de données que Django prend en charge.

      Étape 1 — Configuration du premier serveur d’application Django

      Pour commencer, nous allons cloner le référentiel d’application Django sur le premier serveur d’application. Ensuite, nous allons configurer et construire l’image de l’application Docker, et tester l’application en exécutant le conteneur Django.

      Remarque : si vous continuez en suivant Comment construire une application Django et Gunicorn avec Docker, vous aurez déjà terminé Étape 1 et pouvez passer à l’étape 2 pour configurer le deuxième serveur d’application.

      Commencez par vous connecter au premier des deux serveurs d’application Django et utilisez git pour cloner la branche polls-docker du référentiel GitHub du tutoriel des applications Django Polls. Ce référentiel contient le code pour l’application de sondages dans la documentation de Django. La branche de polls-docker contient une version Dockerisée de l’application de sondage. Pour savoir comment l’application de sondage a été modifiée pour fonctionner efficacement dans un environnement conteneurisé, consultez Comment construire une application Django et Gunicorn avec Docker.

      • git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

      Naviguez dans le répertoire django-polls :

      cd django-polls
      

      Ce répertoire contient le code Python de l’application Django, un Dockerfile que Docker utilisera pour construire l’image du conteneur, ainsi qu’un fichier env contenant une liste de variables d’environnement à passer dans l’environnement d’exécution du conteneur. Inspectez le Dockerfile à l’aide de cat :

      cat Dockerfile
      

      Output

      FROM python:3.7.4-alpine3.10 ADD django-polls/requirements.txt /app/requirements.txt RUN set -ex && apk add --no-cache --virtual .build-deps postgresql-dev build-base && python -m venv /env && /env/bin/pip install --upgrade pip && /env/bin/pip install --no-cache-dir -r /app/requirements.txt && runDeps="$(scanelf --needed --nobanner --recursive /env | awk '{ gsub(/,/, "nso:", $2); print "so:" $2 }' | sort -u | xargs -r apk info --installed | sort -u)" && apk add --virtual rundeps $runDeps && apk del .build-deps ADD django-polls /app WORKDIR /app ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH EXPOSE 8000 CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"]

      Ce Dockerfile utilise l’image Docker officielle de Python 3.7.4 comme base, et installe les exigences du paquet Python de Django et Gunicorn, telles que définies dans le fichier django-polls/requirements.txt. Il supprime ensuite quelques fichiers de construction inutiles, copie le code de l’application dans l’image, et définit le PATH d’exécution. Enfin, il déclare que le port 8000 sera utilisé pour accepter les connexions de conteneurs entrantes, et exécute gunicorn avec 3 travailleurs, en écoutant sur le port 8000.

      Pour en savoir plus sur chacune des étapes de ce Dockerfile, consultez l’Étape 6 de Comment construire une application Django et Gunicorn avec Docker.

      Maintenant, construisez l’image à l’aide de docker build :

      Nous nommons l’image polls en utilisant le drapeau -t et passons dans le répertoire courant comme contexte de construction, l’ensemble de fichiers à faire référence lors de la construction de l’image.

      Après que Docker ait construit et étiqueté l’image, listez les images disponibles à l’aide de docker images :

      docker images
      

      Vous devriez voir l’image polls listée :

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE polls latest 80ec4f33aae1 2 weeks ago 197MB python 3.7.4-alpine3.10 f309434dea3a 8 months ago 98.7MB

      Avant de lancer le conteneur Django, nous devons configurer son environnement d’exécution à l’aide du fichier env présent dans le répertoire actuel. Ce fichier sera transmis dans la commande docker run utilisée pour exécuter le conteneur, et Docker injectera les variables d’environnement configurées dans l’environnement d’exécution du conteneur.

      Ouvrez le fichier env avec nano ou votre éditeur préféré :

      nano env
      

      Nous allons configurer le fichier comme ceci, et vous devrez ajouter quelques valeurs supplémentaires comme indiqué ci-dessous.

      django-polls/env

      DJANGO_SECRET_KEY=
      DEBUG=True
      DJANGO_ALLOWED_HOSTS=
      DATABASE_ENGINE=postgresql_psycopg2
      DATABASE_NAME=polls
      DATABASE_USERNAME=
      DATABASE_PASSWORD=
      DATABASE_HOST=
      DATABASE_PORT=
      STATIC_ACCESS_KEY_ID=
      STATIC_SECRET_KEY=
      STATIC_BUCKET_NAME=
      STATIC_ENDPOINT_URL=
      DJANGO_LOGLEVEL=info
      

      Remplissez les valeurs manquantes pour les clés suivantes :

      • DJANGO_SECRET_KEY : définissez cette valeur à une valeur unique et imprévisible, comme indiqué dans les docs de Django. Une méthode de génération de cette clé est fournie dans Ajustement des paramètres du tutoriel sur les applications Django dimensionnables.
      • DJANGO_ALLOWED_HOSTS: : cette variable sécurise l’application et prévient les attaques d’en-tête d’hôte HTTP. Pour les besoins de test, définissez cette variable à *, un joker qui correspondra à tous les hôtes. En production, vous devriez la définir sur your_domain.com. Pour en savoir plus sur ce paramètre Django, consultez les paramètres de base dans les docs Django.
      • DATABASE_USERNAME : définissez ce paramètre sur l’utilisateur de la base de données PostgreSQL créé dans les étapes préalables.
      • DATABASE_NAME : définissez ce paramètres sur polls ou le nom de la base de données PostgreSQL créée dans les étapes préalables.
      • DATABASE_PASSWORD : définissez ce paramètre sur le mot de passe de l’utilisateur PostgreSQL créé dans les étapes préalables.
      • DATABASE_HOST : définissez ce paramètre sur le nom d’hôte de votre base de données.
      • DATABASE_PORT : définissez ce paramètre sur le port de votre base de données.
      • STATIC_ACCESS_KEY_ID : définissez ce paramètre sur votre bucket S3 ou sur la clé d’accès à l’espace.
      • STATIC_ACCESS_KEY_ID : définissez ce paramètre sur votre bucket S3 ou sur la clé secrète d’accès à l’espace.
      • STATIC_BUCKET_NAME : définissez ce paramètre sur votre bucket S3 ou votre nom d’espace.
      • STATIC_ENDPOINT_URL : définissez ce paramètre sur le bucket S3 approprié ou l’URL de votre espace, par exemple https://space-name.nyc3.digitaloceanspaces.com si votre espace se trouve dans la région nyc3.

      Une fois que vous avez terminé de le modifier, enregistrez et fermez le fichier.

      Nous allons maintenant utiliser docker run pour remplacer le paramètre CMD dans le Dockerfile et créer le schéma de base de données à l’aide des commandes manage.py et manage.py migrate :

      docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"
      

      Nous lançons le container d’images polls:latest, nous passons dans le fichier variable d’environnement que nous venons de modifier, et remplacons la commande Dockerfile par sh -c "python manage.py makemigrations python manage.py image", qui créera le schéma de base de données défini par le code de l’application. Si vous exécutez cette opération pour la première fois, vous devriez voir ce qui suit :

      Output

      No changes detected Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK

      Cela indique que le schéma de base de données a été créé avec succès.

      Si vous exécutez migrate une, fois de plus, Django effectuera un no-op à moins que le schéma de base de données ait changé.

      Ensuite, nous allons exécuter une autre instance du conteneur de l’application et utiliser un shell interactif à l’intérieur de celui-ci pour créer un utilisateur administratif pour le projet Django.

      docker run -i -t --env-file env polls sh
      

      Vous obtiendrez une invite shell à l’intérieur du conteneur en cours d’exécution que vous pouvez utiliser pour créer l’utilisateur Django :

      python manage.py createsuperuser
      

      Entrez un nom d’utilisateur, une adresse email et un mot de passe pour votre utilisateur, et après avoir créé l’utilisateur, appuyez sur CTRL+D pour quitter le conteneur et le fermer.

      Enfin, nous allons générer les fichiers statiques pour l’application et les télécharger sur l’espace DigitalOcean à l’aide de collectstatic. Notez que cela peut prendre un peu de temps.

      docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"
      

      Une fois que ces fichiers sont générés et téléchargés, vous obtiendrez la sortie suivante.

      Output

      121 static files copied.

      Nous pouvons maintenant exécuter l’application :

      docker run --env-file env -p 80:8000 polls
      

      Output

      [2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync [2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7 [2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8 [2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9

      Ici, nous exécutons la commande par défaut définie dans le Dockerfile, gunicorn --bind :8000 --workers 3 mysite.wsgi:application, et exposons le port de conteneur 8000 afin que le port 80 sur le serveur Ubuntu soit mappé sur le port 8000 du conteneur polls.

      Vous devriez maintenant pouvoir naviguez jusqu’à l’application de sondages à l’aide de votre navigateur web en tapant : http://APP_SERVER_1_IP dans la barre d’URL. Comme il n’y a pas de route définie pour le chemin d’accès / , vous obtiendrez probablement une erreur de recherche 404 Page Not Found, qui est prévisible.

      Attention : Lorsque vous utilisez le pare-feu UFW avec Docker, Docker contourne les règles de pare-feu UFW, comme indiqué dans ce numéro de GitHub. Cela explique pourquoi vous avez accès au port 80 de votre serveur, même si vous n’avez pas explicitement créé de règle d’accès UFW dans aucune étape préalable. Dans l’Étape 5, nous aborderons cette faille de sécurité en corrigeant la configuration d’UFW. Si vous n’utilisez pas UFW et que vous utilisez les pare-feu Cloud de DigitalOcean, vous pouvez ignorer cet avertissement.

      Naviguez sur http://APP_SERVER_1_IP/polls pour voir l’interface de l’application de sondage :

      Interface des applications de sondage

      Pour voir l’interface administrative, allez à http://APP_SERVER_1_IP/admin. Vous devriez voir la fenêtre d’authentification de l’application de sondage :

      Page Auth admin des sondages

      Entrez le nom d’utilisateur administratif et le mot de passe que vous avez créé avec la commande createsuperuser.

      Après avoir été authentifié, vous pouvez accéder à l’interface administrative de l’application de sondage :

      Interface principale de l'administration de sondages

      Notez que les actifs statiques pour les applications d’administration et de sondage sont livrées directement depuis le stockage d’objets. Pour confirmer ceci, consultez Testing Spaces Static File Delivery.

      Lorsque vous avez terminé d’explorer, appuyez sur CTRL+C dans la fenêtre de terminal en exécutant le conteneur de Docker pour terminer le conteneur.

      Maintenant que vous avez confirmé que le conteneur d’application fonctionne comme prévu, vous pouvez l’exécuter en mode détaché, qui l’exécutera en arrière-plan et vous permettra de vous déconnecter de votre session SSH :

      docker run -d --rm --name polls --env-file env -p 80:8000 polls
      

      Le drapeau -d demande à Docker d’exécuter le conteneur en mode détaché, le drapeau -rm nettoie le système de fichiers du conteneur après la fermeture du conteneur, et nous donnons un nom aux sondages de conteneur.

      Déconnectez-vous du premier serveur d’application Django, et naviguez vers http://APP_SERVER_1_IP/polls pour confirmer que le conteneur fonctionne comme prévu.

      Maintenant que votre premier serveur d’application Django est opérationnel, vous pouvez configurer votre deuxième serveur d’application Django.

      Étape 2 — Configuration du deuxième serveur d’application Django

      Comme beaucoup de commandes pour configurer ce serveur seront les mêmes que celles de l’étape précédente, elles seront présentées ici sous forme abrégée. Veuillez consulter l’Étape 1 pour plus d’informations sur une commande particulière de cette étape.

      Commencez par vous connecter au deuxième serveur d’application Django.

      Clonez la branche polls-docker du référentiel GitHub django-polls :

      • git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

      Naviguez dans le répertoire django-polls :

      cd django-polls
      

      Maintenant, construisez l’image à l’aide de docker build :

      Ouvrez le fichier env avec nano ou votre éditeur préféré :

      nano env
      

      django-polls/env

      DJANGO_SECRET_KEY=
      DEBUG=True
      DJANGO_ALLOWED_HOSTS=
      DATABASE_ENGINE=postgresql_psycopg2
      DATABASE_NAME=polls
      DATABASE_USERNAME=
      DATABASE_PASSWORD=
      DATABASE_HOST=
      DATABASE_PORT=
      STATIC_ACCESS_KEY_ID=
      STATIC_SECRET_KEY=
      STATIC_BUCKET_NAME=
      STATIC_ENDPOINT_URL=
      DJANGO_LOGLEVEL=info
      

      Remplissez les valeurs manquantes comme à l’Étape 1. Lorsque vous avez terminé les modifications, enregistrez et fermez le fichier.

      Enfin, exécutez le conteneur d’application en mode détaché :

      docker run -d --rm --name polls --env-file env -p 80:8000 polls
      

      Naviguez jusqu’à http://APP_SERVER_2_IP/polls pour confirmer que le conteneur fonctionne comme prévu. Vous pouvez vous déconnecter en toute sécurité du deuxième serveur d’application sans mettre fin à votre conteneur en cours d’exécution.

      Une fois les conteneurs d’application Django opérationnels, vous pouvez passer à la configuration du conteneur proxy inverse Nginx.

      Étape 3 — Configuration du conteneur Docker Nginx

      Nginx est un serveur web polyvalent qui offre un certain nombre de fonctionnalités, dont le proxy inverse, l’équilibrage de la charge et la mise en cache. Dans ce tutoriel, nous avons déchargé les ressources statiques de Django pour le stockage d’objets, nous n’utiliserons donc pas les capacités de mise en cache de Nginx. Cependant, nous utiliserons Nginx comme proxy inverse sur nos deux serveurs d’application Django de backend et distribuerons les demandes entrantes entre eux. En outre, Nginx effectuera la terminaison et la redirection TLS à l’aide d’un certificat TLS fourni par Certbot. Cela signifie qu’il forcera les clients à utiliser HTTPS, redirigeant les requêtes HTTPS vers le port 443. Il déchiffrera ensuite les requêtes HTTPS, puis les enverra par proxy aux serveurs Django en amont.

      Dans ce tutoriel, nous avons pris la décision de découpler les conteneurs Nginx des serveurs de backend. En fonction de votre cas d’utilisation, vous pouvez choisir d’exécuter le conteneur Nginx sur l’un des serveurs d’application Django, en envoyant les requêtes par proxy localement et ainsi que vers l’autre serveur Django. Une autre architecture possible serait d’exécuter deux conteneurs Nginx, un sur chaque serveur de backend avec un load balancer en cloud en avant. Chaque architecture présente différents avantages de sécurité et de performance, et vous devriez tester la charge de votre système pour découvrir les goulets d’étranglement. L’architecture flexible décrite dans ce tutoriel vous permet d’évaluer à la fois la couche d’application Django de backend et la couche proxy Nginx. Une fois que le conteneur Nginx unique devient un goulot d’étranglement, vous pouvez échelonner sur plusieurs proxies Nginx, et ajouter un load balancer en cloud ou un load balancer L4 rapide comme HAProxy.

      Une fois les deux serveurs d’applications Django en place, nous pouvons commencer à configurer le serveur proxy Nginx. Connectez-vous à votre serveur proxy et créez un répertoire appelé conf :

      mkdir conf
      

      Créez un fichier de configuration appelé nginx.conf à l’aide de nano ou de votre éditeur préféré :

      nano conf/nginx.conf
      

      Collez dans la configuration Nginx suivante :

      conf/nginx.conf

      
      upstream django {
          server APP_SERVER_1_IP;
          server APP_SERVER_2_IP;
      }
      
      server {
          listen 80 default_server;
          return 444;
      }
      
      server {
          listen 80;
          listen [::]:80;
          server_name your_domain.com;
          return 301 https://$server_name$request_uri;
      }
      
      server {
          listen 443 ssl http2;
          listen [::]:443 ssl http2;
          server_name your_domain.com;
      
          # SSL
          ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
      
          ssl_session_cache shared:le_nginx_SSL:10m;
          ssl_session_timeout 1440m;
          ssl_session_tickets off;
      
          ssl_protocols TLSv1.2 TLSv1.3;
          ssl_prefer_server_ciphers off;
      
          ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
      
          client_max_body_size 4G;
          keepalive_timeout 5;
      
              location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://django;
              }
      
          location ^~ /.well-known/acme-challenge/ {
              root /var/www/html;
          }
      
      }
      

      Ces blocs upstream, server et location configurent Nginx pour rediriger les requêtes HTTP vers HTTPS, et et équilibrent la charge entre les deux serveurs d’applications Django configurés aux Étapes 1 et 2. Pour en savoir plus sur la structure du fichier de configuration Nginx, consultez cet article sur la compréhension de la structure du fichier de configuration Nginx et les contextes de configuration. En outre, cet article sur La compréhension des algorithmes de sélection des serveurs Nginx et des blocs de localisation peut être utile.

      Cette configuration a été assemblée à partir d’exemplesde fichiers de configuration fournis par Gunicorn, Cerbot et Nginx et est conçue comme une configuration Nginx minimale pour que cette architecture soit opérationnelle. L’adaptation de cette configuration Nginx dépasse la portée de cet article, mais vous pouvez utiliser un outil comme NGINXConfig pour générer des fichiers de configuration Nginx performants et sécurisés pour votre architecture.

      Le bloc upstream définit le groupe de serveurs utilisés pour les demandes de proxy à l’aide de la directive proxy_pass :

      conf/nginx.conf

      upstream django {
          server APP_SERVER_1_IP;
          server APP_SERVER_2_IP;
      }
      . . .
      

      Dans ce bloc, nous nommons le upstream django et incluons les adresses IP des deux serveurs d’application Django. Si les serveurs d’application fonctionnent sur DigitalOcean et que le réseau VPC est activé, vous devriez utiliser leurs adresses IP privées ici. Pour apprendre à activer le VPC Networking sur DigitalOcean, consultez Comment activer le VPC Networking sur les droplets existants.

      Le premier bloc server capture les demandes qui ne correspondent pas à votre domaine et met fin à la connexion. Par exemple, une requête HTTP directe vers l’adresse IP de votre serveur serait traitée par ce bloc :

      conf/nginx.conf

      . . .
      server {
          listen 80 default_server;
          return 444;
      }
      . . .
      

      Le bloc server suivant redirige les requêtes HTTP, vers votre domaine, à l’aide d’un redirect HTTP 301 redirect. Ces demandes sont ensuite traitées par le bloc server final :

      conf/nginx.conf

      . . .
      server {
          listen 80;
          listen [::]:80;
          server_name your_domain.com;
          return 301 https://$server_name$request_uri;
      }
      . . .
      

      Ces deux directives définissent les chemins d’accès au certificat TLS et à la clé secrète. Ceux-ci seront fournis à l’aide de Certbot et montés dans le conteneur Nginx à l’étape suivante.

      conf/nginx.conf

      . . .
      ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
      . . .
      

      Ces paramètres sont les valeurs par défaut de la sécurité SSL recommandées par Certbot. Pour en savoir plus sur ces questions, consultez le Module ngx_http_ssl_module dans les docs Nginx. Security/Server Side TLS de Mozilla est un autre guide utile que vous pouvez utiliser pour ajuster la configuration SSL.

      conf/nginx.conf

      . . .
          ssl_session_cache shared:le_nginx_SSL:10m;
          ssl_session_timeout 1440m;
          ssl_session_tickets off;
      
          ssl_protocols TLSv1.2 TLSv1.3;
          ssl_prefer_server_ciphers off;
      
          ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
      . . .
      

      Ces deux directives d’exemple de configuration Nginx de Gunicorn définissent la taille maximale autorisée du corps de requête client et attribuent le timeout pour les connexions keep-alive avec le client. Nginx fermera les connexions avec le client après keepalive_timeout secondes.

      conf/nginx.conf

      . . .
      client_max_body_size 4G;
      keepalive_timeout 5;
      . . .
      

      Le premier bloc location permet à Nginx d’accéder aux demandes de proxy vers les serveurs upstream django sur HTTP. Il préserve également les en-têtes HTTP du client qui capturent l’adresse IP d’origine, le protocole utilisé pour la connexion et l’hôte cible :

      conf/nginx.conf

      . . .
      location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass http://django;
      }
      . . .
      

      Pour en savoir plus sur ces directives, consultez Deploying Gunicorn et Module ngx_http_proxy_module à partir des docs Deploying

      Le bloc location final capture les demandes vers le chemin /well-known/acme-challenge/ utilisé par Certbot pour les défis HTTP-01 pour vérifier votre domaine avec Let’s Encrypt et fournir ou renouveler les certificats TLS. Pour plus d’informations sur le défi HTTP-01 utilisé par Certbot, consultez les Types de défi dans les docs Let’s Encrypt.

      conf/nginx.conf

      . . .
      location ^~ /.well-known/acme-challenge/ {
              root /var/www/html;
      }
      

      Une fois que vous avez terminé de le modifier, enregistrez et fermez le fichier.

      Vous pouvez maintenant utiliser ce fichier de configuration pour exécuter un conteneur Docker Nginx. Dans ce tutoriel, nous utiliserons l’image nginx:1.19.0, version 1.19.0 de l’image Docker officielle maintenue par Nginx.

      Lorsque nous exécutons le conteneur pour la première fois, Nginx lancera une erreur et échouera car nous n’avons pas encore fourni les certificats définis dans le fichier de configuration. Cependant, nous allons toujours exécuter la commande pour télécharger l’image Nginx localement et tester que tout le reste fonctionne correctement :

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Ici, nous nommons le conteneur nginx et cartographions les ports hôtes 80 et 443 vers les ports conteneur respectifs. Le drapeau -v monte le fichier de configuration dans le conteneur Nginx à /etc/nginx/conf.d/nginx.conf, que l’image Nginx est préconfigurée pour charger. Il est monté en mode ro ou “read only”, de sorte que le conteneur ne peut pas modifier le fichier. Le répertoire racine web /var/www/html est également monté dans le conteneur. Enfin, nginx:1.19.0 demande à Docker de tirer et d’exécuter l’image nginx:1.19.0 depuis Dockerhub.

      Docker tirera et exécutera l’image, puis Nginx lancera une erreur lorsqu’il ne trouvera pas le certificat TLS configuré et la clé secrète. Dans la prochaine étape, nous allons les fournir à l’aide d’un client Certbot Dockerizé et de l’autorité de certification Let’s Encrypt.

      Étape 4 — Configuration de Cerbot et renouvellement du certificat Let’s Encrypt

      Certbot est un client Let’s Encrypt développé par la Electronic Frontier Foundation. Il fournit des certificats TLS gratuits depuis l’autorité de certification Let’s Encrypt qui permet aux navigateurs de vérifier l’identité de vos serveurs web. Comme Docker a été installé sur notre serveur proxy Nginx, nous utiliserons l’image Certbot Docker pour fournir et renouveler les certificats TLS.

      Commencez par vous assurer que vous disposez d’un enregistrement DNS A mappé à l’adresse IP publique du serveur proxy. Ensuite, sur votre serveur proxy, proposez une version de mise en scène des certificats à l’aide de l’image certbot Docker :

      docker run -it --rm -p 80:80 --name certbot 
               -v "/etc/letsencrypt:/etc/letsencrypt" 
               -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
               certbot/certbot certonly --standalone --staging -d your_domain.com
      

      Cette commande exécute l’image certbot Docker en mode interactif, et achemine le port 80 de l’hôte au port 80 du conteneur. Il crée et monte deux répertoires hôtes dans le conteneur : /etc/letsencrypt/ et /var/lib/letsencrypt/ certbot est exécuté en mode stand alone, sans Nginx, et utilisera les serveurs staging de Let’s Encrypt pour effectuer la validation du domaine.

      Lorsque vous y êtes invité, entrez votre adresse email et acceptez les conditions de service. Si la validation du domaine a réussi, vous devriez voir la sortie suivante :

      Output

      Obtaining a new certificate Performing the following challenges: http-01 challenge for stubb.dev Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your_domain.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your_domain.com/privkey.pem Your cert will expire on 2020-09-15. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.

      Vous pouvez inspecter le certificat à l’aide de cat :

      sudo cat /etc/letsencrypt/live/your_domain.com/fullchain.pem
      

      Une fois le certificat TLS fourni, nous pouvons tester la configuration Nginx assemblée à l’étape précédente :

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      C’est la même commande exécutée à l’Étape 3, avec l’ajout des deux répertoires Let’s Encrypt récemment créés.

      Une fois que Nginx est opérationnel, naviguez jusqu’à http://your_domain.com. Vous pouvez recevoir un avertissement dans votre navigateur signalant que l’autorité de certification est invalide. C’est normal car nous avons fourni des certificats de mise en scène et non pas des certificats Let’s Encrypt. Vérifiez la barre d’URL de votre navigateur pour confirmer que votre requête HTTP a été redirigée vers HTTPS.

      Entrez CTRL+C dans votre terminal pour quitter Nginx et exécutez à nouveau le client certbot, cette fois en omettant le drapeau --staging flag :

      docker run -it --rm -p 80:80 --name certbot 
               -v "/etc/letsencrypt:/etc/letsencrypt" 
               -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
               certbot/certbot certonly --standalone -d your_domain.com
      

      Lorsque vous êtes invité à conserver le certificat existant ou à le renouveler et à le remplacer, tapez 2 pour le renouveler et ensuite ENTER (ENTRÉE) pour confirmer votre choix.

      Une fois le certificat de production TLS fourni, exécutez à nouveau le serveur Nginx :

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Dans votre navigateur, naviguez vers http://your_domain.com. Dans la barre d’URL, vérifiez que la requête HTTP a été redirigée vers HTTPS. Comme l’application de sondage n’a pas de route configurée par défaut, vous devriez voir une erreur Django Page not found. Naviguez vers https://your_domain.com/polls et vous verrez l’interface standard de l’application de sondage :

      Interface des applications de sondage

      Vous avez maintenant fourni un certificat TLS de production à l’aide du client Certbot Docker, et vous effectuez un proxying inverse et un équilibrage de charge des requêtes externes vers les deux serveurs d’application Django.

      Les certificats Let’s Encrypt expirent tous les 90 jours. Pour vous assurer que votre certificat reste valide, vous devriez le renouveler régulièrement avant son expiration prévue. Avec Nginx en cours d’exécution, vous devriez utiliser le client Certbot en mode webroot au lieu d’un mode standalone. Cela signifie que Certbot effectuera la validation en créant un fichier dans le répertoire /var/www/html/.well-known/acme-challenge/ et les demandes de validation Let’s Encrypt vers ce chemin seront captées par la règle location définie dans la configuration Nginx à l’Étape 3. Certbot effectuera ensuite la rotation des certificats, et vous pouvez recharger Nginx afin qu’il utilise ce certificat qui vient d’être fourni.

      Il existe de multiples façons d’automatiser cette procédure et le renouvellement automatique des certificats TLS va au-delà de la portée de ce tutoriel. Pour effectuer un processus similaire à l’aide de l’utilitaire de planification cron, consultez l’Étape 6 de Comment sécuriser une application Node.js avec Nginx, Let’s Encrypt et Docker Compose.

      Dans votre terminal, entrez sur CTRL+C pour terminer le conteneur Nginx. Exécutez-le à nouveau en mode détaché en apposant le drapeau -d :

      docker run --rm --name nginx -d -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
        -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Avec Nginx en cours d’exécution en arrière-plan, utilisez la commande suivante pour effectuer un essai de la procédure de renouvellement du certificat :

      docker run -it --rm --name certbot 
          -v "/etc/letsencrypt:/etc/letsencrypt" 
        -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
        -v "/var/www/html:/var/www/html" 
        certbot/certbot renew --webroot -w /var/www/html --dry-run
      

      Nous utilisons le plugin --webroot, spécifions le chemin racine web, et utilisons le drapeau --dry-run pour vérifier que tout fonctionne correctement sans réellement effectuer le renouvellement du certificat.

      Si la simulation de renouvellement réussit, vous devriez voir la sortie suivante :

      Output

      Cert not due for renewal, but simulating renewal for dry run Plugins selected: Authenticator webroot, Installer None Renewing an existing certificate Performing the following challenges: http-01 challenge for your_domain.com Using the webroot path /var/www/html for all unmatched domains. Waiting for verification... Cleaning up challenges - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - new certificate deployed without reload, fullchain is /etc/letsencrypt/live/your_domain.com/fullchain.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain.com/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Dans un environnement de production, après avoir renouvelé les certificats, vous devez recharger Nginx pour que les modifications prennent effet. Pour recharger Nginx, exécutez la commande suivante :

      docker kill -s HUP nginx
      

      Cette commande enverra un signal Unix HUP au processus Nginx en cours d’exécution dans le conteneur Docker nginx. À la réception de ce signal, Nginx rechargera sa configuration et les certificats renouvelés.

      Une fois HTTPS activé, et tous les composants de cette architecture opérationnels, la dernière étape consiste à verrouiller la configuration en empêchant l’accès externe aux deux serveurs d’application backend ; toutes les requêtes HTTP devraient passer par le proxy Nginx.

      Étape 5 — Prévention de l’accès externe aux serveurs d’application Django

      Dans l’architecture décrite dans ce tutoriel, la terminaison SSL se produit au niveau du proxy Nginx. Cela signifie que Nginx décrypte la connexion SSL, et que les paquets sont acheminés vers les serveurs d’application Django non cryptés. Pour de nombreux cas d’utilisation, ce niveau de sécurité est suffisant. Pour les applications impliquant des données financières ou sanitaires, vous souhaiterez peut-être mettre en place le cryptage de bout en bout. Vous pouvez le faire en envoyant des paquets cryptés via le répartiteur de charge et en les décryptant sur les serveurs d’application, ou en les cryptant à niveau du proxy et en décryptant une fois de plus sur les serveurs d’application Django. Ces techniques vont au-delà de la portée de cet article, mais pour en savoir plus veuillez consulter le Cryptage de bout en bout.

      Le proxy Nginx agit comme une passerelle entre le trafic externe et le réseau interne. En théorie, aucun client externe ne doit avoir un accès direct aux serveurs d’application internes, et toutes les demandes doivent passer par le serveur Nginx. La remarque de l’Étape 1 décrit brièvement un problème ouvert avec Docker où Docker contourne les paramètres du pare-feu ufw par défaut et ouvre les ports à l’extérieur, ce qui peut se révéler dangereux. Pour répondre à cette préoccupation de sécurité, il est recommandé d’utiliser les pare-feu en cloud lors de l’utilisation de serveurs Docker. Pour obtenir plus d’informations sur la création de pare-feu en cloud avec DigitalOcean, consultez Comment créer des pare-feu. Vous pouvez également manipuler directement les iptables au lieu d’utiliser ufw. Pour en savoir plus sur l’utilisation d’iptables avec Docker, consultez Docker et iptables.

      Au cours de cette étape, nous allons modifier la configuration d’UFW pour bloquer l’accès externe aux ports hôtes ouverts par Docker. En exécutant Django sur les serveurs d’application, nous avons passé le drapeau -p 80:8000 à docker, qui achemine le port 80 de l’hôte au port de conteneur 8000. Cela a également ouvert le port 80 à des clients externes, ce que vous pouvez vérifier en visitant http://your_app_server_1_IP. Pour éviter un accès direct, nous allons modifier la configuration d’UFW à l’aide de la méthode décrite dans le référentiel GitHub ufw-docker.

      Commencez par vous connecter au premier serveur d’application Django. Ensuite, ouvrez le fichier /etc/ufw/after.rules avec des privilèges super-utilisateur, à l’aide de nano ou de votre éditeur préféré :

      sudo nano /etc/ufw/after.rules
      

      Entrez votre mot de passe lorsque vous y serez invité, et appuyez sur ENTER pour confirmer.

      Vous devriez voir les règles ufw suivantes :

      /etc/ufw/after.rules

      #
      # rules.input-after
      #
      # Rules that should be run after the ufw command line added rules. Custom
      # rules should be added to one of these chains:
      #   ufw-after-input
      #   ufw-after-output
      #   ufw-after-forward
      #
      
      # Don't delete these required lines, otherwise there will be errors
      *filter
      :ufw-after-input - [0:0]
      :ufw-after-output - [0:0]
      :ufw-after-forward - [0:0]
      # End required lines
      
      # don't log noisy services by default
      -A ufw-after-input -p udp --dport 137 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 138 -j ufw-skip-to-policy-input
      -A ufw-after-input -p tcp --dport 139 -j ufw-skip-to-policy-input
      -A ufw-after-input -p tcp --dport 445 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 67 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 68 -j ufw-skip-to-policy-input
      
      # don't log noisy broadcast
      -A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
      
      # don't delete the 'COMMIT' line or these rules won't be processed
      COMMIT
      

      Faites défiler vers le bas, et collez dans le bloc suivant des règles de configuration UFW :

      /etc/ufw/after.rules

      . . .
      
      # BEGIN UFW AND DOCKER
      *filter
      :ufw-user-forward - [0:0]
      :DOCKER-USER - [0:0]
      -A DOCKER-USER -j RETURN -s 10.0.0.0/8
      -A DOCKER-USER -j RETURN -s 172.16.0.0/12
      -A DOCKER-USER -j RETURN -s 192.168.0.0/16
      
      -A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
      
      -A DOCKER-USER -j ufw-user-forward
      
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
      
      -A DOCKER-USER -j RETURN
      COMMIT
      # END UFW AND DOCKER
      

      Ces règles limitent l’accès du public aux ports ouverts par Docker, et permettent un accès à partir des plages IP privées 10.0.0/8, 172.16.0.0/12 et 192.168.0.0/16. Si vous utilisez VPC avec DigitalOcean, alors les Droplets de votre réseau VPC aura accès au port ouvert sur l’interface réseau privée, mais les clients externes ne l’auront pas. Pour plus d’informations sur VPC, consultez la documentation officielle de VPC. Pour en savoir plus sur les règles appliquées dans ce snippet, consultez Comment ça marche ? du fichier README ufw-docker.

      Si vous n’utilisez pas VPC avec DigitalOcean et que vous avez entré les adresses IP publiques des serveurs d’application dans le bloc upstream de votre configuration Nginx, vous devrez modifier explicitement le pare-feu UFW pour autoriser le trafic depuis le serveur Nginx par le port 80 sur les serveurs d’application Django. Pour obtenir des conseils sur la création de règles allow avec le pare-feu UFW, consultez les Essentiels  d’UFW: Règles et commandes communes du pare-feu.

      Quand vous avez terminé de le modifier, enregistrez et fermez le fichier.

      Redémarrez ufw afin qu’il adopte la nouvelle configuration :

      sudo systemctl restart ufw
      

      Naviguez vers http://APP_SERVER_1_IP dans votre navigateur web pour vérifier que vous ne pouvez plus accéder au serveur d’application sur le port 80.

      Répétez ce processus sur le deuxième serveur d’application Django.

      Déconnectez-vous du premier serveur d’application ou ouvrez une autre fenêtre de terminal, et connectez-vous au deuxième serveur d’application Django. Ensuite, ouvrez le fichier /etc/ufw/after.rules avec des privilèges super-utilisateur, à l’aide de nano ou de votre éditeur préféré :

      sudo nano /etc/ufw/after.rules
      

      Entrez votre mot de passe lorsque vous y serez invité, et appuyez sur ENTER pour confirmer.

      Faites défiler vers le bas, et collez dans le bloc suivant des règles de configuration UFW :

      /etc/ufw/after.rules

      . . .
      
      # BEGIN UFW AND DOCKER
      *filter
      :ufw-user-forward - [0:0]
      :DOCKER-USER - [0:0]
      -A DOCKER-USER -j RETURN -s 10.0.0.0/8
      -A DOCKER-USER -j RETURN -s 172.16.0.0/12
      -A DOCKER-USER -j RETURN -s 192.168.0.0/16
      
      -A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
      
      -A DOCKER-USER -j ufw-user-forward
      
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
      
      -A DOCKER-USER -j RETURN
      COMMIT
      # END UFW AND DOCKER
      

      Quand vous avez terminé de le modifier, enregistrez et fermez le fichier.

      Redémarrez ufw afin qu’il adopte la nouvelle configuration :

      sudo systemctl restart ufw
      

      Naviguez vers http://APP_SERVER_2_IP dans votre navigateur web pour vérifier que vous ne pouvez plus accéder au serveur d’application sur le port 80.

      Enfin, naviguez jusqu’à https://your_domain_here/polls pour confirmer que le proxy Nginx a toujours accès aux serveurs Django en amont. Vous devriez voir l’interface de ‘application de sondage.

      Conclusion

      Dans ce tutoriel, vous avez mis en place une application de sondage Django évolutive à l’aide de conteneurs Docker. Au fur et à mesure que votre trafic et la charge sur le système grandissent, vous pouvez faire évoluer chaque couche séparément : la couche proxy Nginx, la couche d’application backend Django et la couche de base de données PostgreSQL.

      Lorsque vous construisez un système distribué, vous devez souvent faire face à de multiples décisions de conception, et plusieurs architectures peuvent satisfaire votre cas d’utilisation. L’architecture décrite dans ce tutoriel est conçue comme un modèle flexible pour la conception d’applications évolutives avec Django et Docker.

      Vous pouvez vouloir contrôler le comportement de vos conteneurs lorsqu’ils rencontrent des erreurs, ou exécuter automatiquement les conteneurs lorsque votre système démarre. Pour ce faire, vous pouvez utiliser un gestionnaire de processus comme Systemd ou mettre en œuvre des politiques de redémarrage. Pour plus d’informations à ce propos, consultez la section Démarrer les conteneurs automatiquement dans la documentation Docker.

      Lorsque vous travaillez à l’échelle avec plusieurs hôtes exécutant la même image Docker, il peut être plus efficace d’automatiser les étapes à l’aide d’un outil de gestion de configuration comme Ansible ou Chef. Pour en savoir plus sur la gestion de la configuration, consultez Une Introduction à la gestion de la configuration et Configuration de serveur automatisée avec Ansible : un kit d’atelier DigitalOcean.

      Au lieu de construire la même image sur chaque hôte, vous pouvez également rationaliser le déploiement à l’aide d’un registre d’images comme Docker Hub, qui construit, stocke et distribue des images Docker à plusieurs serveurs de manière centralisée. En plus d’un registre d’images, un pipeline d’intégration et de déploiement continu peut vous aider à construire, tester et déployer des images sur vos serveurs d’application. Pour plus d’informations sur les CI/CD, veuillez consulter Une Introduction aux meilleures pratiques de CI/CD.



      Source link