run - que es docker hub




Exponer un puerto en un contenedor Docker en vivo (9)

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?


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>

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

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


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.


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.


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




docker