Mise à jour II
Nous sommes maintenant le 16 juillet 2015 et les choses ont de nouveau changé. J'ai découvert ce conteneur automagique de Jason Wilder :
https://github.com/jwilder/nginx-proxy
et il résout ce problème en autant de temps qu'il faut pourdocker run
le conteneur. C'est maintenant la solution que j'utilise pour résoudre ce problème.
Mise à jour
Nous sommes maintenant en juillet 2015 et les choses ont radicalement changé en ce qui concerne la mise en réseau des conteneurs Docker. Il existe maintenant de nombreuses offres différentes qui résolvent ce problème (de différentes manières).
Vous devriez utiliser cet article pour acquérir une compréhension de base de l'
docker --link
approche de la découverte de services, qui est à peu près aussi basique que possible, fonctionne très bien et nécessite en fait moins de danse sophistiquée que la plupart des autres solutions. Il est limité en ce sens qu'il est assez difficile de mettre en réseau des conteneurs sur des hôtes distincts dans un cluster donné, et les conteneurs ne peuvent pas être redémarrés une fois mis en réseau, mais offrent un moyen rapide et relativement simple de mettre en réseau des conteneurs sur le même hôte. C'est un bon moyen d'avoir une idée de ce que le logiciel que vous utiliserez probablement pour résoudre ce problème fait réellement sous le capot.De plus, vous aurez probablement envie de vérifier également Docker de la naissante
network
, Hashicorp deconsul
, Weaveworksweave
, Jeff Lindsayprogrium/consul
&gliderlabs/registrator
et GoogleKubernetes
.Il y a aussi les CoreOS offres qui utilisent
etcd
,fleet
etflannel
.Et si vous voulez vraiment organiser une fête, vous pouvez créer un cluster pour exécuter
Mesosphere
, ouDeis
, ouFlynn
.Si vous êtes nouveau dans le réseautage (comme moi), vous devriez sortir vos lunettes de lecture, pop "Paint The Sky With Stars - The Best of Enya" sur le Wi-Hi-Fi et craquer une bière - ça va être un moment avant de vraiment comprendre exactement ce que vous essayez de faire. Astuce: vous essayez d'implémenter un
Service Discovery Layer
dans votreCluster Control Plane
. C'est une très belle façon de passer un samedi soir.C'est très amusant, mais j'aurais aimé prendre le temps de mieux me renseigner sur le réseautage en général avant de me lancer directement. J'ai finalement trouvé quelques articles des dieux bienveillants du Digital Ocean Tutorial:
Introduction to Networking Terminology
etUnderstanding ... Networking
. Je suggère de les lire quelques fois avant de plonger.S'amuser!
Message original
Je n'arrive pas à comprendre le mappage des ports pour les Docker
conteneurs. Plus précisément, comment passer des requêtes de Nginx à un autre conteneur, en écoutant sur un autre port, sur le même serveur.
J'ai un Dockerfile pour un conteneur Nginx comme ceci:
FROM ubuntu:14.04
MAINTAINER Me <[email protected]>
RUN apt-get update && apt-get install -y htop git nginx
ADD sites-enabled/api.myapp.com /etc/nginx/sites-enabled/api.myapp.com
ADD sites-enabled/app.myapp.com /etc/nginx/sites-enabled/app.myapp.com
ADD nginx.conf /etc/nginx/nginx.conf
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80 443
CMD ["service", "nginx", "start"]
Et puis le api.myapp.com
fichier de configuration ressemble à ceci:
upstream api_upstream{
server 0.0.0.0:3333;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.mypp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_pass http://api_upstream;
}
}
Et puis un autre pour app.myapp.com
aussi.
Et puis je cours:
sudo docker run -p 80:80 -p 443:443 -d --name Nginx myusername/nginx
Et tout se tient très bien, mais les demandes ne sont pas transmises aux autres conteneurs / ports. Et quand je ssh dans le conteneur Nginx et inspecter les journaux, je ne vois aucune erreur.
De l'aide?
Réponses:
La réponse de @ T0xicCode est correcte, mais j'ai pensé développer les détails car il m'a fallu environ 20 heures pour enfin mettre en place une solution fonctionnelle.
Si vous cherchez à exécuter Nginx dans son propre conteneur et à l'utiliser comme proxy inverse pour équilibrer la charge de plusieurs applications sur la même instance de serveur, les étapes à suivre sont les suivantes:
Liez vos conteneurs
Lorsque vous utilisez
docker run
vos conteneurs, généralement en entrant un script shell dansUser Data
, vous pouvez déclarer des liens vers tout autre conteneur en cours d' exécution . Cela signifie que vous devez démarrer vos conteneurs dans l'ordre et que seuls les derniers conteneurs peuvent être liés aux premiers. Ainsi:Ainsi, dans cet exemple, le
API
conteneur n'est lié à aucun autre, mais leApp
conteneur est lié àAPI
etNginx
est lié à la fois àAPI
etApp
.Il en résulte des modifications apportées aux
env
variables vars et aux/etc/hosts
fichiers qui résident dans les conteneursAPI
etApp
. Les résultats ressemblent à ceci:/ etc / hosts
L'exécution
cat /etc/hosts
dans votreNginx
conteneur produira les éléments suivants:ENV Vars
L'exécution
env
dans votreNginx
conteneur produira les éléments suivants:J'ai tronqué la plupart des variables réelles, mais les valeurs ci-dessus sont les valeurs clés dont vous avez besoin pour transférer le trafic vers vos conteneurs.
Pour obtenir un shell pour exécuter les commandes ci-dessus dans un conteneur en cours d'exécution, utilisez ce qui suit:
sudo docker exec -i -t Nginx bash
Vous pouvez voir que vous disposez désormais à la fois d'
/etc/hosts
entrées de fichier et deenv
variables contenant l'adresse IP locale de l'un des conteneurs liés. Autant que je sache, c'est tout ce qui se passe lorsque vous exécutez des conteneurs avec des options de lien déclarées. Mais vous pouvez maintenant utiliser ces informations pour configurernginx
dans votreNginx
conteneur.Configurer Nginx
C'est là que ça devient un peu compliqué, et il y a quelques options. Vous pouvez choisir de configurer vos sites pour pointer vers une entrée dans le
/etc/hosts
fichier qui adocker
créé, ou vous pouvez utiliser lesENV
vars et exécuter un remplacement de chaîne (j'ai utilisésed
) sur votrenginx.conf
et tout autre fichier de configuration qui peut être dans votre/etc/nginx/sites-enabled
dossier pour insérer l'adresse IP valeurs.OPTION A: Configurer Nginx à l'aide d'ENV Vars
La principale différence entre cette option et l'utilisation de l'
/etc/hosts
option de fichier réside dans la façon dont vous écrivez votreDockerfile
pour utiliser un script shell commeCMD
argument, qui à son tour gère le remplacement de chaîne pour copier les valeurs IPENV
dans vos fichiers de configuration.Voici l'ensemble des fichiers de configuration avec lesquels j'ai fini:
Dockerfile
nginx.conf
api.myapp.conf
Nginx-Startup.sh
Je vous laisse le soin de faire vos devoirs sur la plupart des contenus de
nginx.conf
etapi.myapp.conf
.La magie se produit
Nginx-Startup.sh
là où nous utilisonssed
pour faire le remplacement de chaîne sur l'APP_IP
espace réservé que nous avons écrit dans leupstream
bloc de nos fichiersapi.myapp.conf
etapp.myapp.conf
.Cette question de ask.ubuntu.com l'explique très bien: rechercher et remplacer du texte dans un fichier à l'aide de commandes
Ainsi, docker a lancé notre conteneur et déclenché l'
Nginx-Startup.sh
exécution du script, qui a utilisésed
pour changer la valeurAPP_IP
de laENV
variable correspondante que nous avons fournie dans lased
commande. Nous avons maintenant des fichiers de configuration dans notre/etc/nginx/sites-enabled
répertoire qui ont les adresses IP desENV
variables que le docker a définies lors du démarrage du conteneur. Dans votreapi.myapp.conf
fichier, vous verrez que leupstream
bloc a changé comme suit:L'adresse IP que vous voyez peut être différente, mais j'ai remarqué que c'est généralement le cas
172.0.0.x
.Vous devriez maintenant avoir tout routé correctement.
OPTION B: utiliser les
/etc/hosts
entrées de fichierCela devrait être le moyen le plus rapide et le plus simple de le faire, mais je n'ai pas pu le faire fonctionner. Apparemment, vous entrez simplement la valeur de l'
/etc/hosts
entrée dans vos fichiersapi.myapp.conf
etapp.myapp.conf
, mais je n'ai pas pu faire fonctionner cette méthode.Voici la tentative que j'ai faite
api.myapp.conf
:Compte tenu du fait qu'il y a une entrée dans mon
/etc/hosts
fichier comme ceci:172.0.0.2 API
je pensais que cela extrairait simplement la valeur, mais cela ne semble pas l'être.J'ai également eu quelques problèmes accessoires avec mon
Elastic Load Balancer
approvisionnement de tous les AZ, c'est peut-être le problème lorsque j'ai essayé cette route. Au lieu de cela, j'ai dû apprendre à gérer le remplacement des chaînes sous Linux, donc c'était amusant. Je vais essayer dans un moment et voir comment ça se passe.la source
J'ai essayé d'utiliser le proxy inverse populaire de Jason Wilder qui fonctionne comme par magie pour tout le monde, et j'ai appris que cela ne fonctionne pas pour tout le monde (c'est-à-dire moi). Et je suis tout nouveau sur NGINX et je n'ai pas aimé le fait que je ne comprenais pas les technologies que j'essayais d'utiliser.
Je voulais ajouter mes 2 cents, car la discussion ci-dessus sur les
linking
conteneurs ensemble est maintenant datée car il s'agit d'une fonctionnalité obsolète. Alors, voici une explication sur la façon de le faire en utilisantnetworks
. Cette réponse est un exemple complet de configuration de nginx en tant que proxy inverse vers un site Web paginé statiquement à l'aide d'uneDocker Compose
configuration nginx.TL, DR;
Ajoutez les services qui doivent se parler sur un réseau prédéfini. Pour une discussion étape par étape sur les réseaux Docker, j'ai appris certaines choses ici: https://technologyconversations.com/2016/04/25/docker-networking-and-dns-the-good-the-bad-and- le moche/
Définir le réseau
Tout d'abord, nous avons besoin d'un réseau sur lequel tous vos services backend peuvent communiquer. J'ai appelé le mien
web
mais ça peut être ce que tu veux.Construisez l'application
Nous allons simplement créer une application de site Web simple. Le site Web est une simple page index.html servie par un conteneur nginx. Le contenu est un volume monté sur l'hôte sous un dossier
content
DockerFile:
default.conf
docker-compose.yml
Notez que nous n'avons plus besoin de mappage de port ici. Nous exposons simplement le port 80. Ceci est pratique pour éviter les collisions de ports.
Lancez l'application
Lancez ce site Web avec
Quelques vérifications amusantes concernant les mappages DNS pour votre conteneur:
Ce ping devrait fonctionner, à l'intérieur de votre conteneur.
Construire le proxy
Proxy inverse Nginx:
Dockerfile
Nous réinitialisons toute la configuration de l'hôte virtuel, car nous allons la personnaliser.
docker-compose.yml
Exécutez le proxy
Lancez le proxy en utilisant notre fidèle
En supposant qu'il n'y ait aucun problème, vous avez deux conteneurs en cours d'exécution qui peuvent se parler en utilisant leurs noms. Testons-le.
Configurer l'hôte virtuel
Le dernier détail consiste à configurer le fichier d'hébergement virtuel afin que le proxy puisse diriger le trafic en fonction de la manière dont vous souhaitez configurer votre correspondance:
sample-site.conf pour notre configuration d'hébergement virtuel:
En fonction de la configuration du proxy, vous aurez besoin de ce fichier stocké dans votre
conf.d
dossier local que nous avons monté via lavolumes
déclaration dans ledocker-compose
fichier.Enfin, dites à nginx de recharger sa configuration.
Cette séquence d'étapes est le point culminant d'heures de maux de tête alors que je luttais contre l'erreur toujours douloureuse 502 Bad Gateway et que j'apprenais nginx pour la première fois, car la plupart de mon expérience était avec Apache.
Cette réponse consiste à montrer comment éliminer l'erreur 502 Bad Gateway qui résulte du fait que les conteneurs ne peuvent pas se parler.
J'espère que cette réponse permettra à quelqu'un d'économiser des heures de douleur, car il était vraiment difficile de faire en sorte que les conteneurs se parlent pour une raison quelconque, bien que ce soit ce que je m'attendais à être un cas d'utilisation évident. Mais là encore, moi stupide. Et faites-moi savoir comment je peux améliorer cette approche.
la source
502 Gateway Error
, un classique tristement célèbre de nos jours. Merci @gdbj d'avoir brûlé le temps de faire avancer la conversation et de fournir une solution aussi détaillée.À l'aide de liens docker , vous pouvez lier le conteneur en amont au conteneur nginx. Une fonctionnalité supplémentaire est que le docker gère le fichier hôte, ce qui signifie que vous pourrez faire référence au conteneur lié en utilisant un nom plutôt que l'adresse IP potentiellement aléatoire.
la source
L '"Option B" d'AJB peut être mise en œuvre en utilisant l'image Ubuntu de base et en configurant nginx vous-même. (Cela n'a pas fonctionné lorsque j'ai utilisé l'image Nginx de Docker Hub.)
Voici le fichier Docker que j'ai utilisé:
Ma configuration nginx (alias: conf / mysite.com):
Et enfin, comment je démarre mes conteneurs:
Cela m'a mis en marche, donc mon nginx a pointé l'amont vers le deuxième conteneur docker qui exposait le port 3000.
la source
upstream website {
définit la valeur du site Web pour nginx. C'est ce que vous utilisez ensuite dans votre fichierproxy_pass
. La partie docker de ceci utilise simplement le même nom pour la cohérence, mais n'a rien à voir avec la configuration de nginx. Pour rendre les choses un peu plus claires, le passe du proxy devrait se lire:upstream website { server localhost:3000; }
La réponse de @ gdbj est une excellente explication et la réponse la plus à jour. Voici cependant une approche plus simple.
Donc, si vous souhaitez rediriger tout le trafic de nginx écoutant
80
vers un autre conteneur exposant8080
, la configuration minimale peut être aussi petite que:nginx.conf:
docker-compose.yml
Documents Docker
la source
Je viens de trouver un article d'Anand Mani Sankar qui montre un moyen simple d'utiliser le proxy amont nginx avec docker composer.
Fondamentalement, il faut configurer la liaison d'instance et les ports dans le fichier docker-compose et mettre à jour en amont sur nginx.conf en conséquence.
la source
links
qui sont obsolètes. Utilisez les réseaux maintenant: docs.docker.com/engine/userguide/networking