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 Dockerfile pour exposer un port, et je peux utiliser l' -p
indicateur avec docker run
pour affecter des ports, mais une fois qu'un conteneur est réellement en cours d'exécution, existe-t-il une commande pour ouvrir / mapper des ports supplémentaires en direct?
Par exemple, supposons que j'ai un conteneur Docker qui exécute sshd. Quelqu'un d'autre utilise le conteneur ssh dans et installe httpd. Existe-t-il un moyen d'exposer le port 80 sur le conteneur et de le mapper sur le port 8080 sur l'hôte, afin que les utilisateurs puissent visiter le serveur Web exécuté dans le conteneur, sans le redémarrer?
Réponses:
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
Pour obtenir l'adresse IP du conteneur, exécutez les 2 commandes:
En interne, Docker lance un shell pour appeler iptables lorsque vous exécutez une image, donc peut-être que certaines variations à ce sujet fonctionneront.
pour exposer le port 8000 du conteneur sur le port 8001 de vos hôtes locaux:
Une façon de résoudre ce problème est de configurer un autre conteneur avec le mappage de port souhaité et de comparer la sortie de la commande iptables-save (cependant, j'ai dû supprimer certaines des autres options qui forcent le trafic à passer par le docker Procuration).
REMARQUE: ceci est en train de renverser le docker, donc devrait être fait en sachant qu'il peut bien créer de la fumée bleue
OU
Une autre alternative consiste à rechercher l'option (nouvelle? Post 0.6.6?) -P - qui utilisera des ports hôtes aléatoires, puis les câbler.
OU
avec 0.6.5, vous pourriez utiliser la fonction LINKs pour faire apparaître un nouveau conteneur qui parle au conteneur existant, avec quelques relais supplémentaires aux drapeaux -p de ce conteneur? (Je n'ai pas encore utilisé de LIENS)
OU
avec docker 0,11? vous pouvez utiliser
docker run --net host ..
pour attacher votre conteneur directement aux interfaces réseau de l'hôte (c'est-à-dire que net n'est pas à espacement de nom) et ainsi tous les ports que vous ouvrez dans le conteneur sont exposés.la source
CONTAINER_IP=$(docker inspect container_name | jq .[0].NetworkSettings.IPAddress | sed -r 's/\"([^\"]+)\"/\1/''])'); iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination ${CONTAINER_IP}:8000
jq
etsed
vous pouvez utiliser l'-f
option dedocker inspect
:CONTAINER_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name)
jshon -e 0 -e NetworkSettings -e Networks -e bridge -e IPAddress -u
Voici ce que je ferais:
la source
sudo docker
et pas seulementdocker
?docker commit
j'étais prêt à tester à nouveau l'application au lieu de passer des heures à tout réinstaller.Bien que vous ne puissiez pas exposer un nouveau port d'un conteneur existant , vous pouvez démarrer un nouveau conteneur dans le même réseau Docker et le faire transférer le trafic vers le conteneur d'origine.
Exemple travaillé
Lancez un service Web qui écoute sur le port 80, mais n'exposez pas son port interne 80 (oups!):
Trouvez son IP réseau Docker:
Lancez
verb/socat
avec le port 8080 exposé et faites-le transférer le trafic TCP vers le port 80 de cette IP:Vous pouvez maintenant accéder à pastebin sur http: // localhost: 8080 / , et vos demandes sont envoyées à celui
socat:1234
qui les transmetpastebin:80
, et la réponse parcourt le même chemin en sens inverse.la source
verb/socat:alpine
, car son image a 5% de l'empreinte (sauf si vous rencontrez des incompatibilités libc ou DNS ).alpine/socat
--net myfoldername_default
à maverb/socat
commande de lancement depuis que j'ai démarré le conteneur non exposé dans une composition de docker qui crée un réseau.Les hacks IPtables ne fonctionnent pas, du moins sur Docker 1.4.1.
La meilleure façon serait d'exécuter un autre conteneur avec le port exposé et de relayer avec socat. Voici ce que j'ai fait pour me connecter (temporairement) à la base de données avec SQLPlus:
Dockerfile:
la source
FROM
image de base que votre conteneur DB, pour une utilisation efficace des ressources.Voici une autre idée. Utilisez SSH pour effectuer la redirection de port; cela a l'avantage de fonctionner également sous OS X (et probablement Windows) lorsque votre hôte Docker est une machine virtuelle.
la source
J'ai dû faire face à ce même problème et j'ai pu le résoudre sans arrêter aucun de mes conteneurs en cours d'exécution. Il s'agit d'une solution à jour en 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 en profondeur pour les nouveaux utilisateurs.
Dans mon scénario, je voulais me connecter temporairement à MySQL fonctionnant dans un conteneur, et puisque d'autres conteneurs d'application y sont liés, l'arrêt, la reconfiguration et la réexécution du conteneur de base de données n'étaient pas un démarreur.
Puisque je souhaite accéder à la base de données MySQL en externe (à partir de Sequel Pro via le tunneling SSH), je vais utiliser le port
33306
sur la machine hôte. (Non3306
, juste au cas où une instance MySQL externe est en cours d'exécution.)Environ une heure de peaufinage des iptables s'est avérée infructueuse, même si:
Étape par étape, voici ce que j'ai fait:
Modifiez
dockerfile
, en plaçant ceci à l'intérieur:Construisez ensuite l'image:
Ensuite, exécutez-le, en vous liant à votre conteneur en cours d'exécution. (Utilisez
-d
au lieu de-rm
pour le garder en arrière-plan jusqu'à ce qu'il soit explicitement arrêté et supprimé. Je veux seulement qu'il fonctionne temporairement dans ce cas.)la source
Pour ajouter à la solution de réponse acceptée
iptables
, j'ai dû exécuter deux commandes supplémentaires sur l'hôte pour l'ouvrir au monde extérieur.Remarque: J'ouvrais le port https (443), mon IP interne de docker était
172.17.0.2
Remarque 2: ces règles et temporaires et ne dureront que jusqu'au redémarrage du conteneur
la source
Vous pouvez utiliser SSH pour créer un tunnel et exposer votre conteneur dans votre hôte.
Vous pouvez le faire des deux manières, 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 un et serveur dans un autre).
Par exemple, dans le conteneur, vous pouvez faire
Vous pouvez trouver l'adresse IP du conteneur à partir de cette ligne (dans le conteneur):
Ensuite, dans l'hôte, vous pouvez simplement faire:
la source
Dans le cas où aucune réponse ne fonctionne pour quelqu'un - vérifiez si votre conteneur cible est déjà en cours d'exécution sur le réseau docker:
Enregistrez-le pour plus tard dans la variable
$NET_NAME
:Si oui, vous devez exécuter le conteneur proxy sur le même réseau.
Recherchez ensuite l'alias du conteneur:
Enregistrez-le pour plus tard dans la variable
$ALIAS
:Maintenant, exécutez
socat
dans un conteneur du réseau$NET_NAME
pour établir un pont vers le port$ALIAS
exposé (mais non publié) du conteneur ed:la source
Vous pouvez utiliser un réseau de superposition comme Weave Net , qui attribuera une adresse IP unique à chaque conteneur et exposera implicitement tous les ports à chaque partie de conteneur du réseau.
Weave fournit également une intégration au 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) à partir de l'hôte, vous pouvez exécuter simplement exécuter
weave expose
.Divulgation complète: je travaille chez Weaveworks.
la source
Il existe un emballage HAProxy pratique.
Cela crée un HAProxy dans le conteneur cible. peasy facile.
la source
Voici quelques solutions:
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
la source
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. C'est parce que docker-compose (j'exécute docker 1.17) crée un nouveau réseau. La manière d'aborder ce scénario serait
docker network ls
Ensuite, ajoutez ce qui suit
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
la source
Il n'est pas possible de faire un mappage de port en direct, mais il existe plusieurs façons de donner à un conteneur Docker ce qui équivaut à une interface réelle comme une machine virtuelle.
Interfaces Macvlan
Docker inclut désormais un pilote réseau Macvlan . Cela attache un réseau Docker à une interface "du monde réel" et vous permet d'attribuer ces adresses de réseaux directement au conteneur (comme un mode ponté de machines virtuelles).
pipework
peut également mapper une interface réelle dans un conteneur ou configurer une sous-interface dans les anciennes versions de Docker.IP de routage
Si vous contrôlez le réseau, vous pouvez router 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.
Interface hôte partagée
L'
--net host
option 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 le même hôte en raison de la nature partagée.la source