¿Cuál es la diferencia entre puertos y exposición en Docker-Compose?
¿ Cuál es la diferencia entre ports
y expose
opciones en docker-compose.yml
?
Según la referencia de Docker-Compose ,
Los puertos se definen como:
Exponer puertos . Especifique ambos puertos (HOST:CONTENEDOR) o solo el puerto del contenedor (se elegirá un puerto de host aleatorio).
- Los puertos mencionados en docker-compose.yml se compartirán entre diferentes servicios iniciados por docker-compose.
- Los puertos estarán expuestos a la máquina host a un puerto aleatorio o a un puerto determinado.
Mi docker-compose.yml
aspecto es:
mysql:
image: mysql:5.7
ports:
- "3306"
Si lo hago docker-compose ps
, se verá así:
Name Command State Ports
-------------------------------------------------------------------------------------
mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:32769->3306/tcp
Exponer se define como:
Exponga los puertos sin publicarlos en la máquina host; solo serán accesibles para los servicios vinculados. Sólo se puede especificar el puerto interno.
Los puertos no están expuestos a las máquinas host, solo a otros servicios.
mysql:
image: mysql:5.7
expose:
- "3306"
Si lo hago docker-compose ps
, se verá así:
Name Command State Ports
---------------------------------------------------------------
mysql_1 docker-entrypoint.sh mysqld Up 3306/tcp
Editar
En versiones recientes de Dockerfile, EXPOSE
normalmente ya no tiene ningún impacto operativo, solo es informativo. ( ver también )
puertos :
- Activa el contenedor para escuchar puertos específicos del mundo fuera de la ventana acoplable (puede ser la misma máquina host o una máquina diferente) Y también el mundo accesible dentro de la ventana acoplable.
- Se puede especificar más de un puerto (es por eso que los puertos no son el puerto)
exponer :
- Activa el contenedor para escuchar un puerto específico solo desde el mundo dentro de la ventana acoplable Y el mundo no accesible fuera de la ventana acoplable.
- Se puede especificar más de un puerto
Puertos Esta sección se utiliza para definir la asignación entre el servidor host y el contenedor Docker.
ports:
- 10005:80
Significa que la aplicación que se ejecuta dentro del contenedor está expuesta en el puerto 80. Pero el sistema/entidad externa no puede acceder a ella, por lo que debe asignarse al puerto del servidor host.
Nota: debe abrir el puerto del host 10005 y modificar las reglas del firewall para permitir que entidades externas accedan a la aplicación.
pueden usar
http://{IP del host}:10005
algo como esto
EXPOSE Esto se usa exclusivamente para definir el puerto en el que se ejecuta la aplicación dentro del contenedor acoplable.
También puedes definirlo en dockerfile. En general, es una práctica buena y ampliamente utilizada definir EXPOSE dentro del dockerfile porque muy rara vez alguien los ejecuta en otro puerto que no sea el predeterminado 80.
Puertos
La ports
sección publicará los puertos en el host. Docker configurará un reenvío para un puerto específico desde la red host al contenedor. De forma predeterminada, esto se implementa con un proceso proxy de espacio de usuario ( docker-proxy
) que escucha en el primer puerto y reenvía al contenedor, que necesita escuchar en el segundo punto. Si el contenedor no está escuchando en el puerto de destino, aún verá algo escuchando en el host, pero se rechazará una conexión si intenta conectarse a ese puerto del host, desde el reenvío fallido a su contenedor.
Tenga en cuenta que el contenedor debe estar escuchando en todas las interfaces de red, ya que este proxy no se ejecuta dentro del espacio de nombres de red del contenedor y no puede llegar a 127.0.0.1 dentro del contenedor. El método IPv4 para esto es configurar su aplicación para escuchar 0.0.0.0
.
Tenga en cuenta también que los puertos publicados no funcionan en la dirección opuesta. No puede conectarse a un servicio en el host desde el contenedor publicando un puerto. En su lugar, encontrará errores de Docker al intentar escuchar el puerto de host que ya está en uso.
Exponer
Exponer es documentación. Establece metadatos en la imagen y, cuando se ejecuta, también en el contenedor. Por lo general, esto se configura en el Dockerfile con las EXPOSE
instrucciones y sirve como documentación para los usuarios que ejecutan su imagen, para que sepan en qué puertos escuchará su aplicación de forma predeterminada. Cuando se configura con un archivo de redacción, estos metadatos solo se configuran en el contenedor. Puede ver los puertos expuestos cuando ejecuta un docker inspect
en la imagen o el contenedor.
Hay algunas herramientas que dependen de puertos expuestos. En Docker, la -P
bandera publicará todos los puertos expuestos en puertos efímeros del host. También hay varios servidores proxy inversos que utilizarán de forma predeterminada un puerto expuesto al enviar tráfico a su aplicación si no configura explícitamente el puerto del contenedor.
Aparte de esas herramientas externas, la exposición no tiene ningún impacto en la red entre contenedores. Solo necesita una red acoplable común y conectarse al puerto del contenedor para acceder a un contenedor desde otro. Si esa red es creada por el usuario (por ejemplo, no es la red puente predeterminada llamada bridge
), puede usar DNS para conectarse a los otros contenedores.
Estoy totalmente de acuerdo con las respuestas anteriores. Solo me gustaría mencionar que la diferencia entre exposición y puertos es parte del concepto de seguridad en Docker. Va de la mano con la conexión en red de Docker. Por ejemplo:
Imagine una aplicación con un front-end web y un back-end de base de datos. El mundo exterior necesita acceso al front-end web (quizás en el puerto 80), pero solo el back-end necesita acceso al host y al puerto de la base de datos. Al utilizar un puente definido por el usuario, solo es necesario abrir el puerto web y la aplicación de base de datos no necesita ningún puerto abierto, ya que el front-end web puede acceder a él a través del puente definido por el usuario.
Este es un caso de uso común al configurar una arquitectura de red en Docker. Entonces, por ejemplo, en una red puente predeterminada, no se puede acceder a ningún puerto desde el mundo exterior. Para ello puede abrir un punto de entrada con "puertos". Con el uso de "exponer" se define la comunicación dentro de la red. Si desea exponer los puertos predeterminados, no necesita definir "exponer" en su archivo docker-compose.