web-dev-qa-db-fra.com

Affectation de vhosts aux ports Docker

J'ai un DNS générique configuré pour que toutes les demandes Web vers un domaine personnalisé (* .foo) soient mappées à l'adresse IP de l'hôte Docker. Si j'ai plusieurs conteneurs exécutant des instances Apache (ou Nginx), chaque conteneur mappe le port Apache (80) sur un port entrant externe.

Ce que je voudrais faire, c'est faire une demande à container-1.foo, qui est déjà mappé à la bonne adresse IP (de l'hôte Docker) via mon serveur DNS personnalisé, mais proxy la demande du port 80 par défaut au Docker externe correct port tel que l'instance Apache correcte du conteneur spécifié puisse répondre en fonction du domaine personnalisé. De même, container-2.foo serait un proxy vers Apache d'un deuxième conteneur, et ainsi de suite.

Existe-t-il une solution prédéfinie pour cela, est mon meilleur pari pour exécuter un proxy Nginx sur l'hôte Docker, ou dois-je écrire un proxy node.js avec le potentiel de gérer les conteneurs Docker (démarrer/arrêter/recréer via le Web ), ou...? Quelles options ai-je qui rendraient l'utilisation des conteneurs Docker plus comme un événement naturel et non quelque chose avec des ports et un jonglage de conteneurs étrangers?

81
ringmaster

Cette réponse peut être un peu tardive, mais ce dont vous avez besoin est un proxy inverse automatique. J'ai utilisé deux solutions pour cela:

  • jwilder/nginx-proxy
  • Traefik

Avec le temps, ma préférence est d'utiliser Traefik. Principalement parce qu'il est bien documenté et maintenu, et est livré avec plus de fonctionnalités (équilibrage de charge avec différentes stratégies et priorités, contrôles de santé, disjoncteurs, certificats SSL automatiques avec ACME/Let's Encrypt, ...).


Utilisation de jwilder/nginx-proxy

Lors de l'exécution d'un conteneur Docker image Docker nginx-proxy de Jason Wilder , vous obtenez un serveur nginx configuré en tant que proxy inverse pour vos autres conteneurs sans configuration à maintenir.

Exécutez simplement vos autres conteneurs avec le VIRTUAL_Host la variable d'environnement et nginx-proxy découvriront leur ip: port et mettront à jour la configuration nginx pour vous.

Imaginons que votre DNS soit configuré de sorte que *.test.local correspond à l'adresse IP de votre hôte Docker, puis démarrez simplement les conteneurs suivants pour lancer une démonstration rapide:

# start the reverse proxy
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy

# start a first container for http://tutum.test.local
docker run -d -e "VIRTUAL_Host=tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -e "VIRTUAL_Host=deis.test.local" deis/helloworld

Utiliser Traefik

Lorsque vous exécutez un conteneur Traefik , vous obtenez une configuration de serveur proxy inverse qui reconfigurera ses règles de transfert selon les étiquettes de docker trouvées sur vos conteneurs.

Imaginons que votre DNS soit configuré de sorte que *.test.local correspond à l'adresse IP de votre hôte Docker, puis démarrez simplement les conteneurs suivants pour lancer une démonstration rapide:

# start the reverse proxy
docker run --rm -it -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik --docker

# start a first container for http://tutum.test.local
docker run -d -l "traefik.frontend.rule=Host:tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -l "traefik.frontend.rule=Host:deis.test.local" deis/helloworld
78
Thomasleveil

Voici deux réponses possibles: (1) configurer les ports directement avec Docker et utiliser Nginx/Apache pour proxy les vhosts, ou (2) utiliser Dokk pour gérer les ports et les vhosts pour vous (c'est ainsi que j'ai appris faire la méthode 1).

Méthode 1a (attribuer directement des ports avec docker)

Étape 1: Configurez nginx.conf ou Apache sur l'hôte, avec les affectations de numéro de port souhaitées. Ce serveur Web, exécuté sur l'hôte, fera le proxy vhost. Il n'y a rien de spécial à ce sujet en ce qui concerne Docker - c'est un hébergement vhost normal. La partie spéciale vient ensuite, à l'étape 2, pour que Docker utilise le bon numéro de port d'hôte.

Étape 2: Forcer les attributions de numéros de port dans Docker avec "-p" pour définir les mappages de ports de Docker et "-e" pour définir des variables d'environnement personnalisées dans Docker, comme suit:

port=12345 # <-- the vhost port setting used in nginx/Apache
IMAGE=myapps/container-1
id=$(docker run -d -p :$port -e PORT=$port $IMAGE)
# -p :$port will establish a mapping of 12345->12345 from outside docker to
# inside of docker.
# Then, the application must observe the PORT environment variable
# to launch itself on that port; This is set by -e PORT=$port.

# Additional goodies:
echo $id # <-- the running id of your container
echo $id > /app/files/CONTAINER # <-- remember Docker id for this instance
docker ps # <-- check that the app is running
docker logs $id # <-- look at the output of the running instance
docker kill $id # <-- to kill the app

Méthode 1b Port d'application codé en dur

... si votre application utilise un port codé en dur, par exemple le port 5000 (c'est-à-dire ne peut pas être configuré via la variable d'environnement PORT, comme dans la méthode 1a), alors il peut être codé en dur via Docker comme ceci:

publicPort=12345
id=$(docker run -d -p $publicPort:5000 $IMAGE)
# -p $publicPort:5000 will map port 12345 outside of Docker to port 5000 inside
# of Docker. Therefore, nginx/Apache must be configured to vhost proxy to 12345,
# and the application within Docker must be listening on 5000.

Méthode 2 (laissez Dokku comprendre les ports)

Pour le moment, une assez bonne option pour gérer les vhosts Docker est Dokk . Une option à venir pourrait être d'utiliser Flynn , mais pour l'instant Flynn ne fait que commencer et n'est pas tout à fait prêt. Par conséquent, nous allons avec Dokku pour l'instant: Après avoir suivi les instructions d'installation de Dokku, pour un seul domaine, activez les vhosts en créant le fichier "VHOST":

echo yourdomain.com > /home/git/VHOST
# in your case: echo foo > /home/git/VHOST

Maintenant, quand une application est poussée via SSH vers Dokku (voir les documents Dokku pour savoir comment faire), Dokku regardera le fichier VHOST et pour l'application particulière poussée (disons que vous avez poussé "container-1"), elle générera le fichier suivant:

/home/git/container-1/nginx.conf

Et il aura le contenu suivant:

upstream container-1 { server 127.0.0.1:49162; }
server {
  listen      80;
  server_name container-1.yourdomain.com;
  location    / {
    proxy_pass  http://container-1;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_Host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

Au redémarrage du serveur, Dokku s'assurera que Docker démarre l'application avec le port mappé sur son port initialement déployé (49162 ici), plutôt que de se voir attribuer un autre port au hasard. Pour réaliser cette affectation déterministe, Dokku enregistre le port initialement attribué dans /home/git/container-1/PORT et au prochain lancement, il définit l'environnement PORT sur cette valeur, et mappe également les affectations de port de Docker pour être ce port à la fois côté hôte et côté application. Cela s'oppose au premier lancement, lorsque Dokku définira PORT=5000, puis déterminez les cartes Dokku à port aléatoire du côté VPS à 5000 du côté de l'application. C'est tout autour (et pourrait même changer à l'avenir), mais ça marche!

Le fonctionnement de VHOST, sous le capot, est le suivant: lors d'une poussée git de l'application via SSH, Dokku exécutera des hooks qui vivent dans /var/lib/dokku/plugins/nginx-vhosts. Ces crochets se trouvent également dans le code source de Dokku ici et sont responsables de l'écriture du nginx.conf fichiers avec les paramètres vhost corrects. Si vous n'avez pas ce répertoire sous /var/lib/dokku, puis essayez d'exécuter dokku plugins-install.

42
David Baird

Avec Docker, vous voulez que les IPS internes restent normaux (par exemple 80) et découvrez comment câbler les ports aléatoires.

Une façon de les gérer est d'utiliser un proxy inverse comme hipache. Pointez votre DNS dessus, puis vous pouvez reconfigurer le proxy lorsque vos conteneurs montent et descendent. Jetez un œil à http://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/ pour voir comment cela pourrait fonctionner.

Si vous recherchez quelque chose de plus robuste, vous voudrez peut-être jeter un œil à la "découverte de service". (un aperçu de la découverte de services avec docker: http://txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/ )

3
ben schwartz