Est-il possible d'avoir un port d'accès au conteneur Docker ouvert par l'hôte? Concrètement, MongoDB et RabbitMQ s'exécutent sur l'hôte et j'aimerais exécuter un processus dans un conteneur Docker pour écouter la file d'attente et (éventuellement) écrire dans la base de données.
Je sais que je peux transférer un port du conteneur vers l'hôte (via l'option -p) et disposer d'une connexion vers le monde extérieur (par exemple, Internet) depuis le conteneur Docker, mais je souhaite ne pas exposer les ports RabbitMQ et MongoDB. de l'hôte au monde extérieur.
EDIT: quelques éclaircissements:
Starting Nmap 5.21 ( http://nmap.org ) at 2013-07-22 22:39 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00027s latency).
PORT STATE SERVICE
6311/tcp open unknown
joelkuiper@vps20528 ~ % docker run -i -t base /bin/bash
root@f043b4b235a7:/# apt-get install nmap
root@f043b4b235a7:/# nmap 172.16.42.1 -p 6311 # IP found via docker inspect -> gateway
Starting Nmap 6.00 ( http://nmap.org ) at 2013-07-22 20:43 UTC
Nmap scan report for 172.16.42.1
Host is up (0.000060s latency).
PORT STATE SERVICE
6311/tcp filtered unknown
MAC Address: E2:69:9C:11:42:65 (Unknown)
Nmap done: 1 IP address (1 Host up) scanned in 13.31 seconds
Je devais faire cette astuce pour obtenir une connexion Internet avec le conteneur: Mon pare-feu bloque les connexions réseau du conteneur docker vers l'extérieur
EDIT: J'ai fini par créer un pont personnalisé à l'aide de pipework et de laisser les services écouter sur les adresses IP du pont. Je suis allé avec cette approche au lieu de laisser MongoDB et RabbitMQ écouter sur le docker bridge car cela donne plus de flexibilité.
Votre hôte docker expose un adaptateur à tous les conteneurs. En supposant que vous êtes sur Ubuntu récent, vous pouvez exécuter
ip addr
Cela vous donnera une liste d’adaptateurs réseau, dont l’un ressemblera à quelque chose comme:
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 22:23:6b:28:6b:e0 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
inet6 fe80::a402:65ff:fe86:bba6/64 scope link
valid_lft forever preferred_lft forever
Vous devrez dire à lapin/mongo de se lier à cette adresse IP (172.17.42.1). Après cela, vous devriez pouvoir ouvrir des connexions vers 172.17.42.1 à partir de vos conteneurs.
Un moyen simple mais relativement peu sûr serait d'utiliser l'option --net=Host
pour docker run
.
Cette option permet au conteneur d'utiliser la pile de mise en réseau de l'hôte. Ensuite, vous pouvez vous connecter aux services s'exécutant sur l'hôte en utilisant simplement "localhost" comme nom d'hôte.
C’est plus facile à configurer car vous n’aurez pas à configurer le service pour accepter les connexions de l’adresse IP de votre conteneur de menu fixe, ni à indiquer au conteneur de menu fixe une adresse IP ou un nom d’hôte spécifique auquel vous connecter, un port.
Par exemple, vous pouvez le tester en exécutant la commande suivante, qui suppose que votre image s'appelle my_image
, qu'elle inclut l'utilitaire telnet
et que le service auquel vous souhaitez vous connecter se trouve sur le port 25:
docker run --rm -i -t --net=Host my_image telnet localhost 25
Si vous envisagez de le faire de cette manière, veuillez consulter la mise en garde concernant la sécurité sur cette page:
https://docs.docker.com/articles/networking/
Ça dit:
--net = Host - Indique à Docker de ne pas placer le conteneur dans une pile réseau distincte. En substance, ce choix indique à Docker de ne pas conteneuriser la mise en réseau du conteneur! Bien que les processus de conteneur restent limités à leur propre système de fichiers, à leur liste de processus et à leurs ressources limitées, une commande rapide ip addr vous montrera que, du point de vue du réseau, ils vivent "à l'extérieur" de l'hôte principal Docker et ont un accès complet à ses interfaces réseau. . Notez que cela ne permet pas au conteneur de reconfigurer la pile réseau de l'hôte - cela nécessiterait --privileged = true -, mais aux processus de conteneur d'ouvrir des ports avec un numéro peu élevé, comme tout autre processus racine. Il permet également au conteneur d'accéder à des services de réseau locaux tels que D-bus. Cela peut amener les processus du conteneur à effectuer des opérations inattendues, telles que le redémarrage de votre ordinateur. Vous devez utiliser cette option avec prudence.
Vous pouvez également créer un tunnel SSH.
docker-compose.yml
:
---
version: '2'
services:
kibana:
image: "kibana:4.5.1"
links:
- elasticsearch
volumes:
- ./config/kibana:/opt/kibana/config:ro
elasticsearch:
build:
context: .
dockerfile: ./docker/Dockerfile.tunnel
entrypoint: ssh
command: "-N elasticsearch -L 0.0.0.0:9200:localhost:9200"
docker/Dockerfile.tunnel
:
FROM buildpack-deps:jessie
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive \
apt-get -y install ssh && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY ./config/ssh/id_rsa /root/.ssh/id_rsa
COPY ./config/ssh/config /root/.ssh/config
COPY ./config/ssh/known_hosts /root/.ssh/known_hosts
RUN chmod 600 /root/.ssh/id_rsa && \
chmod 600 /root/.ssh/config && \
chown $USER:$USER -R /root/.ssh
config/ssh/config
:
# Elasticsearch Server
Host elasticsearch
HostName jump.Host.czerasz.com
User czerasz
ForwardAgent yes
IdentityFile ~/.ssh/id_rsa
Ainsi, la elasticsearch
dispose d'un tunnel vers le serveur avec le service en cours d'exécution (Elasticsearch, MongoDB, PostgreSQL) et expose le port 9200 avec ce service.
J'ai eu un problème similaire lors de l'accès à un serveur LDAP à partir d'un conteneur Docker. J'ai défini une adresse IP fixe pour le conteneur et ajouté une règle de pare-feu.
docker-compose.yml:
version: '2'
services:
containerName:
image: dockerImageName:latest
extra_hosts:
- "dockerhost:192.168.50.1"
networks:
my_net:
ipv4_address: 192.168.50.2
networks:
my_net:
ipam:
config:
- subnet: 192.168.50.0/24
règle iptables:
iptables -A INPUT -j ACCEPT -p tcp -s 192.168.50.2 -d $192.168.50.1 --dport portnumberOnHost
Dans l'accès au conteneur dockerhost:portnumberOnHost
Si MongoDB et RabbitMQ s'exécutent sur l'hôte, le port devrait déjà être exposé car il ne se trouve pas dans Docker.
Vous n'avez pas besoin de l'option -p
pour exposer les ports du conteneur à l'hôte. Par défaut, tous les ports sont exposés. L'option -p
vous permet d'exposer un port du conteneur à l'extérieur de l'hôte.
Donc, je suppose que vous n'avez pas du tout besoin de -p
et que cela devrait fonctionner correctement :)