J’essaie de créer un conteneur Docker qui agit comme une machine virtuelle complète. Je sais que je peux utiliser l’instruction EXPOSE dans un fichier Dockerfile pour exposer un port, et je peux utiliser l’ -p
avec l’ docker run
pour atsortingbuer des ports, mais une fois qu’un conteneur est en cours d’exécution, existe-t-il une commande pour ouvrir / mapper des ports supplémentaires? ?
Par exemple, disons que j’ai un conteneur Docker qui exécute sshd. Quelqu’un d’autre utilisant le conteneur ssh est installé et installe httpd. Existe-t-il un moyen d’exposer le port 80 sur le conteneur et de le mapper sur le port 8080 de l’hôte afin que les utilisateurs puissent visiter le serveur Web exécuté dans le conteneur sans le redémarrer?
Vous ne pouvez pas le faire via Docker, mais vous pouvez accéder au port non exposé du conteneur depuis la machine hôte.
si vous avez un conteneur avec quelque chose qui tourne sur son port 8000, vous pouvez exécuter
wget http://container_ip:8000
Pour obtenir l’adresse IP du conteneur, exécutez les 2 commandes:
docker ps docker inspect container_name | grep IPAddress
En interne, Docker tente d’appeler iptables lorsque vous exécutez une image.
exposer le port 8000 du conteneur sur votre port localhosts 8001:
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
Une façon de résoudre ce problème consiste à configurer un autre conteneur avec le mappage de port souhaité et à comparer la sortie de la commande iptables-save (cependant, j’ai dû supprimer certaines des autres options qui obligent le trafic à passer par le menu fixe). Procuration).
NOTE: ceci est un subverting docker, donc devrait être fait avec la conscience qu’il peut bien créer de la fumée bleue
OU
Une autre alternative consiste à regarder l’option (nouvelle? Post 0.6.6?) -P – qui utilisera des ports hôtes aléatoires, puis les reliera.
OU
avec 0.6.5, vous pouvez utiliser la fonctionnalité LINKs pour afficher un nouveau conteneur qui communique avec l’existant, avec quelques relais supplémentaires vers les options -p de ce conteneur? (Je n’ai pas encore utilisé LINK)
OU
avec docker 0.11? Vous pouvez utiliser docker run --net host ..
pour connecter votre conteneur directement aux interfaces réseau de l’hôte (par exemple, net n’est pas espacé par un nom) et ainsi tous les ports que vous ouvrez dans le conteneur sont exposés.
Voici ce que je ferais:
sudo docker ps sudo docker commit sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t /bin/bash
Voici une autre idée. Utilisez SSH pour effectuer le transfert de port; Cela présente l’avantage de fonctionner également sous OS X (et probablement Windows) lorsque votre hôte Docker est une machine virtuelle.
docker exec -it ssh -R5432:localhost:5432 @
Les hacks IPtables ne fonctionnent pas, au moins sur Docker 1.4.1.
Le meilleur moyen serait de lancer un autre conteneur avec le port exposé et de relayer avec socat. C’est ce que j’ai fait pour (temporairement) me connecter à la firebase database avec SQLPlus:
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus
Dockerfile:
FROM debian:7 RUN apt-get update && \ apt-get -y install socat && \ apt-get clean USER nobody CMD socat -dddd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521
Bien que vous ne puissiez pas exposer un nouveau port d’un conteneur existant , vous pouvez démarrer un nouveau conteneur sur le même réseau Docker et le faire transférer le trafic vers le conteneur d’origine.
# docker run \ --rm \ -p $PORT:1234 \ verb/socat \ TCP-LISTEN:1234,fork \ TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT
Lancez un service Web qui écoute sur le port 80, mais n’exposez pas son port interne 80 (oops!):
# docker run -ti mkodockx/docker-pastebin # Forgot to expose PORT 80!
Trouver son réseau IP Docker:
# docker inspect 63256f72142a | grep IPAddress "IPAddress": "172.17.0.2",
Lancez verb/socat
avec le port 8080 exposé, et verb/socat
à transférer le trafic TCP vers le port 80 de cet IP:
# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80
Vous pouvez maintenant accéder à pastebin sur http: // localhost: 8080 / et vos demandes vont à socat:1234
qui le transmet à pastebin:80
, et la réponse parcourt le même chemin en sens inverse.
J’ai dû faire face à ce problème et j’ai pu résoudre le problème sans arrêter aucun de mes conteneurs en cours d’exécution. Il s’agit d’une solution à jour en date de février 2016, utilisant Docker 1.9.1. Quoi qu’il en soit, cette réponse est une version détaillée de la réponse de @ricardo-branco, mais plus approfondie pour les nouveaux utilisateurs.
Dans mon scénario, je souhaitais me connecter temporairement à MySQL en cours d’exécution dans un conteneur et, étant donné que d’autres conteneurs d’applications y sont liés, l’arrêt, la reconfiguration et la ré-exécution du conteneur de firebase database n’était pas un début.
Comme je voudrais accéder à la firebase database MySQL en externe (à partir de Sequel Pro via tunneling SSH), je vais utiliser le port 33306
sur la machine hôte. (Pas 3306
, juste au cas où une instance externe de MySQL serait en cours d’exécution.)
Environ une heure de réglage d’ iptables s’est avérée infructueuse, même si:
Pas à pas, voici ce que j’ai fait:
mkdir db-expose-33306 cd db-expose-33306 vim Dockerfile
Modifiez dockerfile
en le plaçant à l’intérieur:
# Exposes port 3306 on linked "db" container, to be accessible at host:33306 FROM ubuntu:latest # (Recommended to use the same base as the DB container) RUN apt-get update && \ apt-get -y install socat && \ apt-get clean USER nobody EXPOSE 33306 CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306
Ensuite, construisez l’image:
docker build -t your-namespace/db-expose-33306 .
Ensuite, lancez-le, en vous connectant à votre conteneur en cours d’exécution. (Utilisez -d
place de -rm
pour le garder en arrière-plan jusqu’à ce qu’il soit explicitement arrêté et supprimé. Je ne le souhaite que temporairement dans ce cas.)
docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306 your-namespace/db-expose-33306
Pour append à la solution de réponse iptables
acceptée , j’ai dû exécuter deux commandes supplémentaires sur l’hôte pour l’ouvrir au monde extérieur.
HOST> iptables -t nat -A DOCKER -p tcp --dport 443 -j DNAT --to-destination 172.17.0.2:443 HOST> iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source 172.17.0.2 --destination 172.17.0.2 --dport https HOST> iptables -A DOCKER -j ACCEPT -p tcp --destination 172.17.0.2 --dport https
Remarque: 172.17.0.2
port https (443), mon adresse IP interne du 172.17.0.2
était 172.17.0.2
Note 2: Ces règles et temporelles ne dureront que lorsque le conteneur sera redémarré
Vous pouvez utiliser SSH pour créer un tunnel et exposer votre conteneur sur votre hôte.
Vous pouvez le faire dans les deux sens, du conteneur à l’hôte et de l’hôte au conteneur. Mais vous avez besoin d’un outil SSH comme OpenSSH dans les deux (client dans l’un et serveur dans un autre).
Par exemple, dans le conteneur, vous pouvez faire
$ yum install -y openssh openssh-server.x86_64 service sshd restart Stopping sshd: [FAILED] Generating SSH2 RSA host key: [ OK ] Generating SSH1 RSA host key: [ OK ] Generating SSH2 DSA host key: [ OK ] Starting sshd: [ OK ] $ passwd # You need to set a root password..
Vous pouvez trouver l’adresse IP du conteneur à partir de cette ligne (dans le conteneur):
$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g' 172.17.0.2
Ensuite, dans l’hôte, vous pouvez simplement faire:
sudo ssh -NfL 80:0.0.0.0:80 [email protected]
Vous pouvez utiliser un réseau superposé tel que Weave Net , qui atsortingbuera une adresse IP unique à chaque conteneur et exposera implicitement tous les ports à chaque conteneur du réseau.
Weave fournit également une intégration réseau hôte . Il est désactivé par défaut mais, si vous souhaitez également accéder aux adresses IP du conteneur (et à tous ses ports) depuis l’hôte, vous pouvez exécuter simplement exécuter weave expose
.
Divulgation complète: je travaille chez Weaveworks.
Il existe un wrapper HAProxy très pratique.
docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy
Cela crée un HAProxy dans le conteneur cible. peasy facile.
Lisez d’abord la réponse de Ricardo . Cela a fonctionné pour moi.
Cependant, il existe un scénario où cela ne fonctionnera pas si le conteneur en cours d’exécution a été lancé à l’aide de docker-compose. Cela est dû au fait que docker-compose (j’utilise docker 1.17) crée un nouveau réseau. La façon de traiter ce scénario serait
docker network ls
Ajoutez ensuite le docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
suivant, docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
Il n’est pas possible de faire un mappage de port en direct, mais il existe de nombreuses manières de donner à un conteneur Docker une interface réelle comme une machine virtuelle.
Docker inclut désormais un pilote réseau Macvlan . Cela attache un réseau Docker à une interface “réelle” et vous permet d’atsortingbuer les adresses de réseaux directement au conteneur (comme un mode pont de machines virtuelles).
docker network create \ -d macvlan \ --subnet=172.16.86.0/24 \ --gateway=172.16.86.1 \ -o parent=eth0 pub_net
pipework
peut également mapper une interface réelle dans un conteneur ou configurer une sous-interface dans les anciennes versions de Docker.
Si vous contrôlez le réseau, vous pouvez acheminer des réseaux supplémentaires vers votre hôte Docker pour les utiliser dans les conteneurs.
Ensuite, vous affectez ce réseau aux conteneurs et configurez votre hôte Docker pour acheminer les paquets via le réseau Docker.
L’option --net host
permet à l’interface hôte d’être partagée dans un conteneur, mais ce n’est probablement pas une bonne configuration pour exécuter plusieurs conteneurs sur un hôte en raison de la nature partagée.
Si aucune réponse ne fonctionne pour quelqu’un, vérifiez si votre conteneur cible est déjà en cours d’exécution dans le réseau docker:
docker inspect my-target-container | grep NetworkMode "NetworkMode": "my-network-name",
Si oui, vous devez exécuter le conteneur proxy sur le même réseau.
docker inspect my-target-container | grep -A2 Aliases "Aliases": [ "my-alias", "23ea4ea42e34a"
Commande finale:
docker run --net my-network-name --name my-new-proxy \ -d -p 8080:1234 alpine/socat TCP-LISTEN:1234,fork TCP-CONNECT:my-alias:80
Pour moi, le meilleur moyen consiste à modifier directement le fichier de configuration du conteneur, voir Comment atsortingbuer un mappage de port à un conteneur Docker existant? , appuyez sur Ctrl + F et trouvez “json” .
Utilisez la commande suivante pour lancer votre conteneur:
docker run -d -p : -t
Il y a aussi l’indicateur -P
qui est assez récent et indique à Docker de mapper tous les ports réseau requirejs dans notre conteneur à notre hôte. Cela peut vous aider à visualiser votre application Web du monde extérieur.
Lorsque vous vous connectez à un port, Docker le redirige pour vous. En utilisant la commande du port Docker, vous verrez quelque chose comme ceci:
docker port 5019f8e8f902 5000/tcp -> 0.0.0.0:49162 5555/tcp -> 0.0.0.0:49163 8080/tcp -> 0.0.0.0:49164