Tengo algunos contenedores Docker que se ejecutan como:
- Nginx
- Aplicación web 1
- Aplicación web 2
- PostgreSQL
Dado que Nginx necesita conectarse a los servidores de aplicaciones web dentro de la aplicación web 1 y 2, y las aplicaciones web necesitan hablar con PostgreSQL, tengo enlaces como este:
- Nginx --- enlace ---> Aplicación web 1
- Nginx --- enlace ---> Aplicación web 2
- Aplicación web 1 --- enlace ---> PostgreSQL
- Aplicación web 2 --- enlace ---> PostgreSQL
Esto funciona bastante bien al principio. Sin embargo, cuando desarrollo una nueva versión de la aplicación web 1 y la aplicación web 2, necesito reemplazarlas. Lo que hago es eliminar los contenedores de la aplicación web, configurar nuevos contenedores e iniciarlos.
Para los contenedores de aplicaciones web, sus direcciones IP al principio serían algo como:
- 172.17.0.2
- 172.17.0.3
Y después de que los reemplace, tendrán nuevas direcciones IP:
- 172.17.0.5
- 172.17.0.6
Ahora, esas variables de entorno expuestas en el contenedor Nginx todavía apuntan a las antiguas direcciones IP. Aquí viene el problema. ¿Cómo reemplazo un contenedor sin romper la conexión entre contenedores? El mismo problema también le sucederá a PostgreSQL. Si quiero actualizar la versión de la imagen de PostgreSQL, ciertamente necesito eliminarla y ejecutar la nueva, pero luego necesito reconstruir todo el gráfico del contenedor, por lo que esto no es ideal para el funcionamiento del servidor en la vida real.
fuente
Puede utilizar un contenedor de embajador . Pero no vincule el contenedor del embajador a su cliente, ya que esto crea el mismo problema que el anterior. En su lugar, use el puerto expuesto del contenedor ambassador en el host de la ventana acoplable (normalmente 172.17.42.1). Ejemplo:
volumen de postgres:
contenedor de postgres:
embajador-contenedor para postgres:
Ahora puede iniciar un contenedor de cliente postgresql sin vincular el contenedor ambassador y acceder a postgresql en el host de la puerta de enlace (normalmente 172.17.42.1):
Ahora puede reiniciar el contenedor ambassador sin tener que reiniciar el cliente.
fuente
Si alguien todavía tiene curiosidad, debe usar las entradas de host en el archivo / etc / hosts de cada contenedor de la ventana acoplable y no debe depender de las variables ENV, ya que no se actualizan automáticamente.
Habrá una entrada de archivo de host para cada contenedor vinculado en el formato LINKEDCONTAINERNAME_PORT_PORTNUMBER_TCP, etc.
Lo siguiente es de docker docs
fuente
Esto se incluye en la compilación experimental de Docker hace 3 semanas, con la introducción de los servicios: https://github.com/docker/docker/blob/master/experimental/networking.md
Debería poder instalar un enlace dinámico ejecutando un contenedor acoplable con los
--publish-service <name>
argumentos. Este nombre será accesible a través del DNS. Esto es persistente en los reinicios del contenedor (siempre que reinicie el contenedor con el mismo nombre de servicio que es, por supuesto)fuente
wget -qO- https://experimental.docker.com/ | sh
para instalar la versión experimentalpublish-service
opción experimental . Ahora tienen alias de ámbito de red. Sin embargo, esencialmente lo mismo.Puede utilizar enlaces acoplables con nombres para solucionar este problema.
La configuración más básica sería crear primero un contenedor de base de datos con nombre :
luego cree un contenedor web que se conecte a db:
Con esto, no es necesario que conecte contenedores manualmente con sus direcciones IP.
fuente
db
en este caso), recibirá una nueva dirección IP. Su otro contenedor (reiniciado o no) retendrá los valores ENV desde el momento en que lo lanzó y es inútil.net-alias
nombre del contenedor o).con el enfoque OpenSVC, puede solucionarlo mediante:
Cada vez que reemplaza un contenedor, está seguro de que se conectará a la dirección IP correcta.
Tutorial aquí => Docker Multi Containers con OpenSVC
no se pierda la parte de "orquestación compleja" al final de tuto, que puede ayudarlo a iniciar / detener contenedores en el orden correcto (1 subconjunto de postgresql + 1 subconjunto de aplicaciones web + 1 subconjunto de nginx)
el principal inconveniente es que expone los puertos de la aplicación web y PostgreSQL a la dirección pública y, en realidad, solo el puerto nginx tcp debe exponerse en público.
fuente
También puede probar el método ambassador de tener un contenedor intermediario solo para mantener el enlace intacto ... (consulte https://docs.docker.com/articles/ambassador_pattern_linking/ ) para obtener más información
fuente
Puede vincular los puertos de conexión de sus imágenes a puertos fijos en el host y configurar los servicios para usarlos en su lugar.
Esto también tiene sus inconvenientes, pero podría funcionar en su caso.
fuente
Otra alternativa es utilizar la
--net container:$CONTAINER_ID
opción.Paso 1: cree contenedores de "red"
Paso 2: inyectar servicios en contenedores de "red"
Mientras no toque los contenedores de "red", las direcciones IP de sus enlaces no deberían cambiar.
fuente
En este caso, lo que necesita es un alias de ámbito de red . Es una característica bastante nueva, que se puede utilizar para "publicar" un contenedor que proporciona un servicio para toda la red, a diferencia de los alias de enlaces accesibles solo desde un contenedor.
No agrega ningún tipo de dependencia entre los contenedores: pueden comunicarse siempre que ambos estén en ejecución, independientemente de los reinicios y el orden de reemplazo y lanzamiento. Utiliza DNS internamente, creo, en lugar de / etc / hosts
Úselo así:
docker run --net=some_user_definied_nw --net-alias postgres ...
y puede conectarse usando ese alias desde cualquier contenedor en la misma red.No funciona en la red predeterminada, desafortunadamente, debe crear uno con
docker network create <network>
y luego usarlo con--net=<network>
para cada contenedor ( compose también lo admite ).Además de que el contenedor está inactivo y, por lo tanto, inalcanzable por alias, varios contenedores también pueden compartir un alias, en cuyo caso no se garantiza que se resuelva en el correcto. Pero en algún caso, probablemente eso puede ayudar con una actualización perfecta.
No está todo muy bien documentado hasta el momento, es difícil de entender con solo leer la página de manual.
fuente