Cet article est le 11ème jour du Calendrier de l'Avent Recruit Lifestyle 2015 - Qiita. Je suis moremagic, qui est en charge du développement chez Hot Pepper Beauty. Nous travaillons dans l'équipe de l'infrastructure des applications pour aider les développeurs.
Utilisez-vous Docker? J'ai récemment commencé à l'utiliser, mais c'est incroyablement pratique!
Cependant, à mesure que le nombre de conteneurs augmente, il est difficile de se souvenir du numéro de port. .. De plus, il est génial que vous ne puissiez savoir à quel service vous accédez par numéro de port. Au lieu de changer le conteneur pour accéder par numéro de port Ne serait-il pas plus facile de comprendre si le nom du conteneur saisissait le nom de domaine tel quel?
Donc, cette fois, je parlerai de l'accès avec Docker avec le nom du conteneur comme sous-domaine.
Par exemple ,,
Le nom du serveur exécutant Docker est ʻexample.com Nom du conteneur
dev-tomcat`
En supposant que le port 8080 est transféré vers le port 49000
Normalement, si vous souhaitez accéder au port 8080 du conteneur dev-tomcat ci-dessus Parce que le port 8080 est redirigé vers le port 49000 Accédez comme suit.
http://example.com:49000/
S'il n'y a qu'un seul conteneur démarré, ce n'est pas difficile. Il est difficile de se souvenir quand le nombre de conteneurs et de services augmente. Si vous faites une erreur, vous vous connecterez à un autre service.
Il est donc facile pour les humains de comprendre
http://dev-tomcat-8080.example.com
C'est une histoire pour la rendre accessible comme décrit ci-dessus. Dans ce cas, vous pouvez y accéder en mémorisant le nom du conteneur et le port qui fonctionne réellement dans le conteneur!
Créez et lancez un conteneur de résolution de nom qui rend le sous-domaine de nom de conteneur accessible au sein du serveur. Puisqu'il est réalisé par proxy http, la résolution de sous-domaine n'est possible que pour le protocole http.
Les informations du conteneur de Docker sont stockées périodiquement dans le conteneur simplement en démarrant le conteneur de résolution de nom. Vous pouvez accéder par nom de conteneur sans réécrire le fichier de paramètres chaque fois que vous démarrez le conteneur.
Il existe un environnement Docker et l'hôte sur lequel Docker s'exécute peut résoudre le nom. RemoteAPI de Docker activé
Préparez les fichiers suivants et créez une image Docker Placez autre que Dockerfile dans un dossier approprié selon la description de Dockerfile.
Le Dockerfile ressemble à ceci. Installez redis, python3, nginx basé sur ubuntu: 14.04 Je crée un shell de démarrage et je le frappe au démarrage
Dockerfile
FROM ubuntu:14.04
~ Omis ~
# python3 install
RUN apt-get install -y python3 python3-pip && apt-get clean
RUN pip3 install redis
ADD redis/regist.py /usr/sbin/regist.py
RUN chmod +x /usr/sbin/regist.py
# redis
RUN apt-get update && apt-get install -fy redis-server
ADD redis/redis.conf /etc/redis/redis.conf
# nginx install
RUN apt-get -y install nginx lua-nginx-redis && apt-get clean
ADD nginx/default /etc/nginx/sites-available/
ADD nginx/rewrite.lua /etc/nginx/sites-available/
ADD nginx/cert/ /etc/nginx/cert/
#Créer un shell de lancement
RUN printf '#!/bin/bash \n\
/usr/bin/redis-server & \n\
/usr/sbin/regist.py > /dev/null & \n\
/etc/init.d/nginx start \n\
/etc/init.d/nginx reload \n\
/usr/sbin/sshd -D \n\
tail -f /var/null \n\
' >> /etc/service.sh \
&& chmod +x /etc/service.sh
EXPOSE 22 6379 80 443
CMD /etc/service.sh
nginx La clé de l'opération, le fichier de configuration nginx ressemble à ceci. Le serveur attend à 80 443 et est configuré pour réécrire → processus.
default
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
set $upstream "";
rewrite_by_lua_file /etc/nginx/sites-available/rewrite.lua;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://$upstream;
client_max_body_size 200M;
}
}
server {
listen 443;
server_name localhost;
ssl on;
ssl_certificate /etc/nginx/cert/ssl.crt;
ssl_certificate_key /etc/nginx/cert/ssl.key;
ssl_session_timeout 5m;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
set $upstream "";
rewrite_by_lua_file /etc/nginx/sites-available/rewrite.lua;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass https://$upstream;
client_max_body_size 200M;
}
}
rewrite.lua Obtenez le nom du conteneur et le numéro de port à partir du nom d'hôte. Contactez redis et renvoyez le conteneur réel
rewrite.lua
local routes = _G.routes
if routes == nil then
routes = {}
ngx.log(ngx.ALERT, "[[[Route cache is empty.]]")
end
local container_name = string.sub(ngx.var.http_host, 1, string.find(ngx.var.http_host, "%.")-1)
local route = routes[container_name]
if route == nil then
local Redis = require "nginx.redis"
local client = Redis:new()
client:set_timeout(1000)
local ok, err = client:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "************ Redis connection failure: " .. err)
return
end
route = client:get(container_name)
end
ngx.log(ngx.ALERT, route)
-- fallback to redis for lookups
if route ~= nil then
ngx.var.upstream = route
routes[container_name] = route
else
ngx.log(ngx.ALERT, "=ng=[[[route null]]]")
ngx.exit(ngx.HTTP_NOT_FOUND)
end
python C'est un joueur en coulisses qui stocke les informations sur les conteneurs dans Redis. Il met à jour les informations du conteneur toutes les 3 secondes via l'API distante de Docker. Je l'ai exécuté en boucle tout le temps, mais il y a peut-être un peu plus de chemin. .. ..
regist.py
#!/usr/bin/python3
import os
import sys
import time
import json
import redis
import urllib.request
DOCKER_HOST = os.getenv('DOCKER_HOST')
REDIS_ADDR = '127.0.0.1'
REDIS_PORT = 6379
def redisDump():
conn = redis.Redis(host=REDIS_ADDR, port=REDIS_PORT)
for key in conn.keys():
print(key)
print(conn.get(key))
return conn.keys()
def addData(datas):
conn = redis.Redis(host=REDIS_ADDR, port=REDIS_PORT)
for key in set(list(datas.keys()) + list(conn.keys())):
if isinstance(key, bytes):
key = key.decode('utf-8')
if key in datas:
conn.set(key, datas[key])
else:
conn.delete(key)
def getContainers():
response = urllib.request.urlopen('http://' + DOCKER_HOST + '/containers/json?all=1')
jsonData = json.loads(response.read().decode('utf-8'))
datas = {}
for con in jsonData:
name = con['Names'][-1][1:]
con_ip = getIpAddress(con['Id'])
for port in con['Ports']:
key = name + '-' + str(port['PrivatePort'])
value=con_ip + ':' + str(port['PrivatePort'])
datas[key] = value
return datas
def getIpAddress(con_id):
response = urllib.request.urlopen('http://' + DOCKER_HOST + '/containers/' + con_id + '/json')
jsonData = json.loads(response.read().decode('utf-8'))
#print(json.dumps(jsonData))
ret = jsonData['NetworkSettings']['IPAddress']
return ret
while True:
addData(getContainers())
print( redisDump() )
sys.stdout.flush()
time.sleep(3)
Allez dans le dossier où le Dockerfile est stocké et tapez la commande suivante!
# docker build -t docker-discovery .
Démarrez l'image que vous avez créée précédemment. Étant donné que les informations sur le conteneur sont acquises à l'aide de l'API DockerRemote de Docker s'exécutant sur l'hôte depuis l'intérieur du conteneur, je vais l'épeler au démarrage.
# docker run -d -p 80:80 -p 443: 443 -e DOCKER_HOST = <Adresse IP de l'hôte Docker>: <Port RemoteAPI> --name docker-discovery docker-discovery
C'est tout ce dont vous avez besoin pour la résolution de noms!
Supposons que l'hôte exécutant le docker soit example.com Vous pouvez vous connecter au conteneur correspondant avec l'URL suivante.
http: // {nom du conteneur} - {numéro de port dans le conteneur public} .example.com
Commençons par le conteneur TeamCity à titre d'essai.
docker run -dP --name teamcity moremagic/teamcity
Ce conteneur expose le port 8111 au monde extérieur, vous pouvez donc y accéder à l'URL suivante. http://teamcity-8111.example.com
Profitez de Docker!
Recommended Posts