hub - docker ubuntu
¿Cuál es la diferencia entre "exponer" y "publicar" en Docker? (5)
Respuesta corta:
-
EXPOSE
es una forma de documentar. -
--publish
(o-p
) es una forma de asignar un puerto de host a un puerto de contenedor en ejecución
Note a continuación que:
-
EXPOSE
está relacionado conDockerfiles
( documentando ) -
--publish
está relacionado con ladocker run ...
--publish
docker run ...
( ejecución / tiempo de ejecución )
Exposición y publicación de puertos.
En la red Docker, hay dos mecanismos diferentes que involucran directamente a los puertos de red: exponer y publicar puertos. Esto se aplica a la red puente predeterminada y a las redes puente definidas por el usuario.
Expone los puertos utilizando la palabra clave
EXPOSE
en el Dockerfile o el indicador--expose
para ejecutar la--expose
acoplable. Exponer puertos es una forma de documentar qué puertos se utilizan, pero en realidad no asigna ni abre ningún puerto. La exposición de puertos es opcional .Usted publica los puertos utilizando el
--publish
o--publish-all
paradocker run
la--publish
docker run
. Esto le indica a Docker qué puertos abrir en la interfaz de red del contenedor. Cuando se publica un puerto, se asigna a un puerto de alto orden disponible (superior a30000
) en la máquina host, a menos que especifique el puerto al que se asignará en la máquina host en el tiempo de ejecución. No puede especificar el puerto al que se asignará en el equipo host cuando genere la imagen (en el Dockerfile), porque no hay manera de garantizar que el puerto esté disponible en el equipo host donde ejecuta la imagen .
También,
EXPONER
... La instrucción
EXPOSE
no publica realmente el puerto. Funciona como un tipo de documentación entre la persona que construye la imagen y la persona que ejecuta el contenedor, acerca de los puertos que deben publicarse .de: documentation
Acceso al servicio cuando EXPOSE
/ --publish
no está definido:
En respuesta de se afirma que:
"Si no especifica ninguno de ellos, no se podrá acceder al servicio en el contenedor desde cualquier lugar, excepto desde dentro del mismo contenedor ".
Quizás ese fue el caso en el momento en que se escribió la respuesta, pero ahora parece que incluso si no usa EXPOSE
o --publish
, el host
y otros containers
de la misma red podrán acceder a un servicio que puede comenzar dentro de ese contenedor .
Cómo probar esto:
He usado el siguiente Dockerfile
. Básicamente, comienzo con Ubuntu e instalo un pequeño servidor web:
FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
build
la imagen como "testexpose" y run
un nuevo contenedor con:
docker run --rm -it testexpose bash
Dentro del contenedor, lanzo algunas instancias de mini-httpd
:
root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090
Entonces puedo usar el curl
del host u otros contenedores para obtener la página de inicio de mini-httpd
.
Estoy experimentando con Dockerfiles, y creo que entiendo la mayor parte de la lógica. Sin embargo, no veo la diferencia entre "exponer" y "publicar" un puerto en este contexto.
Todos los tutoriales que he visto primero incluyen el comando EXPOSE
en el Dockerfile:
...
EXPOSE 8080
...
Luego construyen una imagen de este Dockerfile:
$ docker build -t an_image - < Dockerfile
Y luego publique el mismo puerto que el anterior cuando ejecute la imagen:
$ docker run -d -p 8080 an_image
o publicar todos los puertos usando
$ docker run -d -P an_image
¿Cuál es el punto de exponer un puerto en el Dockerfile, si se publicará de todos modos? ¿Habría alguna vez la necesidad de exponer un puerto primero y no publicarlo más tarde? Efectivamente, me gustaría especificar todos los puertos que usaré en el Dockerfile al crear la imagen, y luego no volver a molestarme con ellos, simplemente ejecutándolos con:
$ docker run -d an_image
es posible?
Básicamente, tienes tres opciones:
- Ni especifique
EXPOSE
ni-p
- Solo especifique
EXPOSE
- Especifique
EXPOSE
y-p
1) Si no especifica EXPOSE
ni -p
, solo se podrá acceder al servicio en el contenedor desde dentro del mismo contenedor.
2) Si EXPOSE
un puerto, el servicio en el contenedor no es accesible desde el exterior de Docker, sino desde el interior de otros contenedores de Docker. Así que esto es bueno para la comunicación entre contenedores.
3) Si EXPOSE
y -p
un puerto, se puede acceder al servicio en el contenedor desde cualquier lugar, incluso fuera de Docker.
La razón por la que ambos están separados es IMHO porque:
- la elección de un puerto de host depende del host y, por lo tanto, no pertenece al Dockerfile (de lo contrario, dependería del host),
- ya menudo es suficiente si se puede acceder a un servicio en un contenedor desde otros contenedores.
La documentation establece explícitamente:
La instrucción
EXPOSE
expone los puertos para su uso dentro de los enlaces.
También le indica cómo vincular los contenedores , que básicamente es la comunicación entre contenedores de la que hablé.
PD: si haces -p
, pero NO EXPOSE
, Docker hace un EXPOSE
implícito. Esto se debe a que si un puerto está abierto al público, también se abre automáticamente a otros contenedores de Docker. Por lo tanto -p
incluye EXPOSE
. Es por eso que no lo mencioné arriba como un cuarto caso.
Expone los puertos utilizando la palabra clave EXPOSE en el Dockerfile o el indicador --expose para ejecutar la ventana acoplable. Exponer puertos es una forma de documentar qué puertos se utilizan, pero en realidad no asigna ni abre ningún puerto. La exposición de puertos es opcional.
Fuente: github commit
La mayoría de la gente usa red docker para componer con redes. La documentation establece:
La función de red de Docker admite la creación de redes sin la necesidad de exponer puertos dentro de la red; para obtener información detallada, consulte la descripción general de esta función).
Lo que significa que si usa redes para la comunicación entre contenedores, no necesita preocuparse por exponer los puertos.
EXPOSE
permite definir puertos privados (contenedor) y públicos (host) para exponer en el momento de creación de la imagen para cuando se ejecuta el contenedor. El puerto público es opcional; si no se especifica un puerto público, la ventana acoplable seleccionará un puerto aleatorio en el host para exponer el puerto de contenedor especificado en Dockerfile.
Una buena práctica es no especificar el puerto público, ya que limita solo un contenedor por host (un segundo contenedor lanzará un puerto que ya está en uso).
Puede usar -p
en la docker run
para controlar en qué puerto público se podrán conectar los puertos de contenedor expuestos.
De todos modos, si no usa EXPOSE
ni -p
, no se expondrán puertos.
Si siempre usa -p
en la docker run
, no necesita EXPOSE
pero si usa EXPOSE
el comando de docker run
EXPOSE
docker run
puede ser más simple, EXPOSE
puede ser útil si no le importa qué puerto se expondrá en el host, o si está Seguro de que solo se cargará un contenedor.