run que puertos puerto mapeo imagenes hub exponer dockers container docker

que - Exponer un puerto en un contenedor Docker en vivo



mapeo de puertos docker (13)

Aquí hay otra idea. Utilice SSH para hacer el reenvío de puertos; Esto tiene la ventaja de que también funciona en OS X (y probablemente en Windows) cuando su host Docker es una máquina virtual.

docker exec -it <containterid> ssh -R5432:localhost:5432 <user>@<hostip>

Estoy tratando de crear un contenedor Docker que actúa como una máquina virtual completa. Sé que puedo usar la instrucción EXPOSE dentro de un Dockerfile para exponer un puerto, y puedo usar el indicador -p con la función docker run para asignar puertos, pero una vez que se ejecuta un contenedor, ¿hay un comando para abrir / mapear puertos adicionales en vivo? ?

Por ejemplo, digamos que tengo un contenedor Docker que ejecuta sshd. Alguien más usa el contenedor ssh en e instala httpd. ¿Hay alguna forma de exponer el puerto 80 en el contenedor y asignarlo al puerto 8080 en el host, para que las personas puedan visitar el servidor web que se ejecuta en el contenedor sin reiniciarlo?


En caso de que ninguna respuesta funcione para alguien, verifique si su contenedor de destino ya se está ejecutando en la red de la ventana acoplable:

docker inspect my-target-container | grep NetworkMode "NetworkMode": "my-network-name",

En caso afirmativo, debe ejecutar el contenedor proxy en la misma red.

docker inspect my-target-container | grep -A2 Aliases "Aliases": [ "my-alias", "23ea4ea42e34a"

Comando final:

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


Esto es lo que yo haría:

  • Cometer el contenedor vivo.
  • Ejecute el contenedor nuevamente con la nueva imagen, con los puertos abiertos (recomendaría montar un volumen compartido y abrir el puerto ssh también)

sudo docker ps sudo docker commit <containerid> <foo/live> sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t <foo/live> /bin/bash


Hay un envoltorio práctico de HAProxy.

docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy

Esto crea un HAProxy al contenedor de destino. pan comido.


Lea primero la respuesta de Ricardo . Esto funcionó para mí.

Sin embargo, existe un escenario en el que esto no funcionará si el contenedor en ejecución se inició utilizando la función docker-compose. Esto se debe a que docker-compose (Estoy ejecutando docker 1.17) crea una nueva red. La forma de abordar este escenario sería

docker network ls

Luego agregue la siguiente docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name


Los hacks de IPtables no funcionan, al menos en Docker 1.4.1.

La mejor manera sería ejecutar otro contenedor con el puerto expuesto y retransmitir con socat. Esto es lo que he hecho para (temporalmente) conectarse a la base de datos con 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


No es posible realizar la asignación de puertos en vivo, pero hay varias formas de dar a un contenedor Docker lo que equivale a una interfaz real como la que tendría una máquina virtual.

Interfaces Macvlan

Docker ahora incluye un controlador de red Macvlan . Esto conecta una red Docker a una interfaz del "mundo real" y le permite asignar las direcciones de esas redes directamente al contenedor (como un modo puenteo de máquinas virtuales).

docker network create / -d macvlan / --subnet=172.16.86.0/24 / --gateway=172.16.86.1 / -o parent=eth0 pub_net

pipework también puede asignar una interfaz real en un contenedor o configurar una interfaz secundaria en versiones anteriores de Docker.

Enrutamiento de IP

Si tiene el control de la red, puede enrutar redes adicionales a su host Docker para su uso en los contenedores.

Luego, asigna esa red a los contenedores y configura su host Docker para enrutar los paquetes a través de la red docker.

Interfaz de host compartido

La opción --net host permite que la interfaz del host se comparta en un contenedor, pero probablemente esta no sea una buena configuración para ejecutar múltiples contenedores en un host debido a la naturaleza compartida.


No puede hacerlo a través de Docker, pero puede acceder al puerto no expuesto del contenedor desde la máquina host.

Si tiene un contenedor con algo que se ejecuta en su puerto 8000, puede ejecutar

wget http://container_ip:8000

Para obtener la dirección IP del contenedor, ejecute los 2 comandos:

docker ps docker inspect container_name | grep IPAddress

Internamente, Docker se apaga para llamar a iptables cuando ejecuta una imagen, por lo que quizás alguna variación en esto funcione.

para exponer el puerto 8000 del contenedor en su puerto local 8001:

iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000

Una forma de resolver esto es configurar otro contenedor con la asignación de puertos que desee y comparar la salida del comando iptables-save (aunque, tuve que eliminar algunas de las otras opciones que obligan al tráfico a ir a través de la ventana acoplable). apoderado).

NOTA: esto está subvirtiendo la ventana acoplable, por lo que debe hacerse con la conciencia de que puede crear humo azul

O

Otra alternativa es buscar (nueva? Post 0.6.6?) Opción -P, que usará puertos de host aleatorios, y luego conectarlos.

O

con 0.6.5, podría usar la función ENLACES para abrir un nuevo contenedor que habla con el existente, con un retransmisión adicional a las banderas -p de ese contenedor. (No he usado LINKs todavía)

O

con docker 0.11? puede usar el docker run --net host .. para adjuntar su contenedor directamente a las interfaces de red del host (es decir, net no tiene espacios) y, por lo tanto, todos los puertos que abre en el contenedor están expuestos.


Para agregar a la solución iptables respuesta aceptada , tuve que ejecutar dos comandos más en el host para abrirlo al mundo exterior.

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

Nota: estaba abriendo el puerto https (443), mi IP interna de la 172.17.0.2 acoplable era 172.17.0.2

Nota 2: Estas reglas son temporales y solo durarán hasta que se reinicie el contenedor


Puede usar SSH para crear un túnel y exponer su contenedor en su host.

Puede hacerlo de dos maneras, de contenedor a host y de host a contenedor. Pero necesita una herramienta SSH como OpenSSH en ambos (cliente en uno y servidor en otro).

Por ejemplo, en el contenedor, puede hacer

$ 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..

Puede encontrar la dirección IP del contenedor desde esta línea (en el contenedor):

$ ifconfig eth0 | grep "inet addr" | sed ''s/^[^:]*:/([^ ]*/).*//1/g'' 172.17.0.2

Luego en el host, simplemente puedes hacer:

sudo ssh -NfL 80:0.0.0.0:80 [email protected]


Puede usar una red de superposición como Weave Net , que asignará una dirección IP única a cada contenedor y expondrá implícitamente todos los puertos a cada parte del contenedor de la red.

Weave también proporciona integración de red de host . Está deshabilitado de forma predeterminada pero, si desea acceder también a las direcciones IP del contenedor (y todos sus puertos) desde el host, puede ejecutar simplemente weave expose .

Revelación completa: trabajo en Weaveworks.


Si bien no puede exponer un nuevo puerto de un contenedor existente , puede iniciar un nuevo contenedor en la misma red Docker y hacer que reenvíe el tráfico al contenedor original.

# docker run / --rm / -p $PORT:1234 / verb/socat / TCP-LISTEN:1234,fork / TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT

Ejemplo trabajado

Inicie un servicio web que escuche en el puerto 80, pero no exponga su puerto interno 80 (¡oops!):

# docker run -ti mkodockx/docker-pastebin # Forgot to expose PORT 80!

Encuentra su red Docker IP:

# docker inspect 63256f72142a | grep IPAddress "IPAddress": "172.17.0.2",

Ejecute verb/socat con el puerto 8080 expuesto, y verb/socat que reenvíe el tráfico TCP al puerto 80 de esa IP:

# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80

Ahora puede acceder a pastebin en http://localhost:8080/ , y sus solicitudes van a socat:1234 que las reenvía a pastebin:80 , y la respuesta recorre el mismo camino en sentido inverso.


Tuve que lidiar con este mismo problema y pude resolverlo sin detener ninguno de mis contenedores en ejecución. Esta es una solución actualizada en febrero de 2016, utilizando Docker 1.9.1. De todos modos, esta respuesta es una versión detallada de la respuesta de @ricardo-branco, pero con mayor profundidad para los nuevos usuarios.

En mi caso, quería conectarme temporalmente a MySQL que se ejecuta en un contenedor, y dado que otros contenedores de aplicaciones están vinculados a él, se detiene, se reconfigura y se vuelve a ejecutar el contenedor de la base de datos.

Ya que me gustaría acceder a la base de datos MySQL externamente (desde Sequel Pro a través del túnel SSH), 33306 el puerto 33306 en la máquina host. (No 3306 , en caso de que haya una instancia externa de MySQL en ejecución).

Alrededor de una hora de ajustar las iptables resultó infructuosa, aunque:

Paso a paso, esto es lo que hice:

mkdir db-expose-33306 cd db-expose-33306 vim Dockerfile

Editar dockerfile , colocando esto dentro:

# 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

Luego construye la imagen:

docker build -t your-namespace/db-expose-33306 .

Luego ejecútalo, enlazando a tu contenedor en ejecución. (Use -d lugar de -rm para mantenerlo en segundo plano hasta que se detenga y elimine explícitamente. Solo quiero que se ejecute temporalmente en este caso).

docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306 your-namespace/db-expose-33306