Cet article traite de la fourniture de votre conteneur Drupal Docker, et /ou de tout autre conteneur, via https avec un certificat SSL de chiffrement Let's Encrypt valide.

Première étape:

Assurez-vous d'avoir plusieurs serveurs virtuels linux. Créez plusieurs VPS avec Docker chez DigitalOcean, en utilisant par exemple la distribution «Docker» dans la section «Applications en un clic» de Digital Ocean.  Cela ne fonctionnera pas sur localhost car, pour pouvoir utiliser Let’s Encrypt, vous devez démontrer la propriété de votre ou de vos domaine (s) au monde extérieur.  Dans ce didacticiel, nous allons desservir deux sites différents, un site HTML simple et un site Drupal, chacun utilisant des ports standard, sur le même hôte Docker, à l'aide d'un reverse proxy, un conteneur situé en face de vos autres conteneurs et dirigeant le trafic.

Deuxième étape:

Configurez deux domaines ou sous-domaines que vous possédez et redirigez-les vers votre serveur. Commencez par vous assurer que vous avez deux domaines qui pointent vers votre serveur. Dans cet exemple, nous allons utiliser:  test-one.example.com sera un site HTML simple. test-two.example.com sera un site Drupal.

Monter un cluster Docker Swarm pour plus de scalabilité :

Vous souhaitez plus de scalabilité sur votre site web ? pas de soucis en deux lignes de commandes avec Docker on peut monter un cluster via Swarm.

root@vps485213:~# docker swarm init --advertise-addr 147.135.208.167
Swarm initialized: current node (3jokuaei83l4c6gxx0rablu5a) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-2flqg99lhw5wg6wnvti2ctqxt5i58clvlypsp49u4oxn16rlkb-ewd9ojmt8w2hek23tgfei2oi6 \
    147.135.208.167:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Troisième étape: Créez vos sites

Nous ne souhaitons pas mapper les ports de nos conteneurs directement sur nos ports hôtes à l’aide de -p 80:80 -p 443: 443, car nous aurons plusieurs applications utilisant le même port (le protocole sécurisé 443). La mise en correspondance des ports incombera au reverse proxy (pour plus d'informations à ce sujet plus tard). Remplacez example.com par votre propre domaine:

DOMAIN=example.com
docker run -d \
  -e "VIRTUAL_HOST=test-one.$DOMAIN" \
  -e "LETSENCRYPT_HOST=test-one.$DOMAIN" \
  -e "LETSENCRYPT_EMAIL=my-email@$DOMAIN" \
  --expose 80 --name test-one \
  httpd
docker run -d \
  -e "VIRTUAL_HOST=test-two.$DOMAIN" \
  -e "LETSENCRYPT_HOST=test-two.$DOMAIN" \
  -e "LETSENCRYPT_EMAIL=my-email@$DOMAIN" \
  --expose 80 --name test-two \
  drupal

Vous avez maintenant deux sites en cours d'exécution, mais ils ne sont pas encore accessibles au monde extérieur.

Troisième étape: un proxy inverse et Let's Encrypt

Dans notre cas, nous voulons un conteneur de serveur Web qui représente nos conteneurs Drupal et HTML. Les conteneurs Drupal et HTML sont efficacement cachés devant un proxy. Pourquoi “reverse”? Le terme «proxy» est déjà utilisé et signifie que l'utilisateur Web est caché du serveur. Si ce sont les serveurs Web qui sont cachés (dans ce cas, Drupal ou les conteneurs html), nous utilisons le terme «reverse proxy».  

Let’s Encrypt est une autorité de certification gratuite qui certifie que vous êtes le propriétaire de votre domaine.  Nous utiliserons nginx-proxy comme reverse proxy. Comme cela ne prend pas en charge les certificats, nous allons utiliser le conteneur LetsEncrypt companion pour nginx-proxy pour configurer et gérer les certificats Let’s Encrypt.  Commençons par créer un répertoire vide qui contiendra nos certificats:

mkdir "$HOME"/certs

Maintenant, en suivant les instructions du projet LetsEncrypt companion, nous pouvons configurer notre reverse proxy:

root@vps485213:~# docker run -d -p 80:80 -p 443:443 \
>   --name nginx-proxy \
>   -v "$HOME"/certs:/etc/nginx/certs:ro \
>   -v /etc/nginx/vhost.d \
>   -v /usr/share/nginx/html \
>   -v /var/run/docker.sock:/tmp/docker.sock:ro \
>   --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy \
>   --restart=always \
>   jwilder/nginx-proxy

Et enfin, démarrez Let'sEncrypt companion :

root@vps485213:~# docker run -d \
>   --name nginx-letsencrypt \
>   -v "$HOME"/certs:/etc/nginx/certs:rw \
>   -v /var/run/docker.sock:/var/run/docker.sock:ro \
>   --volumes-from nginx-proxy \
>   --restart=always \
>   jrcs/letsencrypt-nginx-proxy-companion

Attendez quelques minutes pour que "$HOME"/certs soient renseignés avec vos fichiers de certificat. Vous devriez maintenant pouvoir accéder à vos sites:

  • https://test-two.example.com/ devrait afficher le programme d'installation de Drupal (la configuration d'un conteneur MySQL pour l'installation de Drupal n'entre pas dans le cadre de cet article);
  • https://test-one.example.com devrait afficher la page “It works!”.

Dans les deux cas, le certificat doit être valide et vous ne devriez pas recevoir de message d'erreur.

http://test-one.example.com devrait rediriger vers https://test-one.example.com

http://test-two.example.com devrait rediriger vers https://test-two.example.com

Les certificats ont rempli le dossier prévu à cet effet

Le renouvellement des certificats

Comme les certificats Encrypt durent 3 mois, nous souhaitons généralement renouveler tous les deux mois. Le conteneur LetsEncrypt companion pour nginx-proxy indique qu'il renouvelle automatiquement les certificats dont l'expiration est prévue dans moins d'un mois. Il effectue cette vérification toutes les heures, bien qu'il existe des problèmes liés au renouvellement dans la file d'attente.  Il est également possible de forcer les renouvellements en exécutant:

docker exec nginx-letsencrypt /app/force_renew

Il serait donc utile d’envisager de rechercher les renouvellements ayant échoué et de les forcer si nécessaire.  

Edit: configurations spécifiques au domaine

J'ai utilisé cette technique pour créer un registre Docker et le rendre accessible en toute sécurité:

docker run \
  --entrypoint htpasswd \
  registry:2 -Bbn username password > auth/htpasswd

docker run -d --expose 5000 \
  -e "VIRTUAL_HOST=mydomain.example.com" \
  -e "LETSENCRYPT_HOST=mydomain.example.com" \
  -e "LETSENCRYPT_EMAIL=me@example.com" \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ 
  --restart=always -v "$PWD"/auth:/auth \
  --name registry registry:2

Mais en essayant de pousser une image, j'obtenais “413 Request Entity Too Large”. C'est une erreur avec le proxy-nginx, pas avec le registre Docker. Pour résoudre ce problème, vous pouvez définir des configurations spécifiques à un domaine. Dans cet exemple, nous autorisons la transmission d'un maximum de 600 Mo, mais uniquement vers le registre Docker à l'adresse mydomain.example.com:

docker exec nginx-proxy /bin/bash -c 'cp /etc/nginx/vhost.d/default /etc/nginx/vhost.d/mydomain.example.com'
docker exec nginx-proxy /bin/bash -c 'echo "client_max_body_size 600M;" >> /etc/nginx/vhost.d/mydomain.example.com'
docker restart nginx-proxy

Enjoy