Agregar dinámicamente asignaciones de puertos a contenedores Docker en ejecución

Agregar dinámicamente asignaciones de puertos a contenedores Docker en ejecución

La asignación de puertos es un aspecto crucial en el desarrollo y despliegue de aplicaciones en contenedores. Normalmente, establecemos una conexión entre un puerto interno del contenedor y un puerto de la máquina host al crear un contenedor. Sin embargo, existen situaciones en las que necesitamos agregar nuevas asignaciones de puertos de forma dinámica a un contenedor que ya está en ejecución. Esto puede ser especialmente útil durante el desarrollo, la depuración o cuando se exponen temporalmente nuevos puntos finales de servicio. Este artículo explicará en detalle cómo agregar dinámicamente asignaciones de puertos a un contenedor sin tener que detenerlo.

1.Conocimientos previos

Principios fundamentales de la asignación de puertos en contenedores

En Docker, la conexión entre un puerto interno del contenedor y el puerto de la máquina host se facilita mediante la asignación de puertos. Normalmente, especificamos las asignaciones de puertos usando los parámetros -p o --publish al iniciar un contenedor, como se muestra a continuación:

docker run -d -p 8080:80 nginx

El comando anterior asigna el puerto 8080 de la máquina host al puerto 80 dentro del contenedor. Como resultado, los usuarios externos pueden acceder al servicio web que se ejecuta dentro del contenedor a través del puerto 8080 del host.

Desafíos de agregar asignaciones de puertos dinámicamente

Una vez que un contenedor ha iniciado, Docker generalmente no admite agregar nuevas asignaciones de puertos de forma dinámica. En otras palabras, las asignaciones de puertos iniciales permanecen fijas durante todo el ciclo de vida del contenedor. Si necesita agregar más asignaciones de puertos, el enfoque tradicional implica detener y reiniciar el contenedor, lo que puede interrumpir los servicios y no es aceptable en entornos de producción.

2.Soluciones de implementación

Para agregar dinámicamente asignaciones de puertos a un contenedor en ejecución, se pueden emplear varios métodos:

2.1 Crear un contenedor proxy usando docker network

Se puede crear un nuevo contenedor proxy dentro de la misma red que el contenedor original y agregar las nuevas asignaciones de puertos al contenedor proxy. Los pasos específicos son los siguientes:Primero, cree un contenedor proxy en la misma red que el contenedor original:

docker run -d --name proxy-container --net container:your-container nginx

Luego, agregue la asignación de puertos deseada al contenedor proxy:

docker run -d -p 8081:81 --net container:your-container nginx

Utilice el código con precaución.Si bien este método permite agregar nuevas asignaciones de puertos sin modificar el contenedor original, introduce una instancia de contenedor adicional y puede no ser adecuado para todos los escenarios.

2.2 Agregar manualmente reglas de reenvío de puertos usando iptables

Modificando iptables, puede reenviar solicitudes desde un puerto específico de la máquina host al puerto interno del contenedor Docker en ejecución. Por ejemplo, para asignar el puerto 8081 del host al puerto 81 del contenedor, use el siguiente comando:

iptables -t nat -A DOCKER -p tcp --dport 8081 -j DNAT --to-destination <container_ip>:81

Donde <container_ip> es la dirección IP interna del contenedor, que se puede obtener usando el comando docker inspect.Este método ofrece total flexibilidad para agregar asignaciones de puertos, pero requiere un buen conocimiento de iptables y no se recomienda su uso frecuente en entornos de producción debido a su complejidad.

2.3 Usar socat para crear reenvío de puertos

socat es una herramienta de red versátil que puede establecer reenvío de puertos entre la máquina host y un contenedor. Puede ejecutar el siguiente comando para reenviar un puerto específico de la máquina host a un puerto designado en el contenedor:Bash

socat TCP-LISTEN:8081,fork TCP:<container_ip>:81

Utilice el código con precaución.La ventaja de este método es que no requiere detener el contenedor. Sin embargo, dado que socat es un proceso adicional, debe tener en cuenta su rendimiento y estabilidad. Otras herramientas de reenvío de puertos pueden lograr resultados similares.

2.4 Actualizar servicios dinámicamente usando Docker Compose

Si su aplicación utiliza Docker Compose para administrar contenedores, puede agregar nuevas asignaciones de puertos actualizando el archivo docker-compose.yml y luego ejecutando docker-compose up. Este método es conveniente y ofrece una gestión unificada, pero cada actualización requiere volver a aplicar el archivo Compose, lo que podría provocar interrupciones temporales del servicio.

2.5 Modificar forzosamente el archivo de configuración del contenedor

Primero, modifique directamente el archivo /var/lib/docker/containers/<container_id>/config.v2.json, agregando la asignación de HostPort 8081 al puerto 81 del contenedor. Tenga en cuenta que debe modificar dos secciones. En una sección, solo necesita agregar HostPort 8081:

    "ExposedPorts": {
      "8080/tcp": {}
      "8081/tcp": {}
    },

En la otra sección, debe agregar la relación de asignación completa:

   "Ports": {
      "80/tcp": [
        {
          "HostIp": "0.0.0.0",
          "HostPort": "8080"
        },
      ],
      "81/tcp": [
        {
          "HostIp": "0.0.0.0",
          "HostPort": "8081"
        },
      ]
    },

Además, también necesita modificar /var/lib/docker/containers/<container_id>/hostconfig.json y agregar la nueva asignación:

  "PortBindings": {
    "80/tcp": [
      {
        "HostIp": "",
        "HostPort": "8080"
      },
     "81/tcp": [
      {
        "HostIp": "",
        "HostPort": "8081"
      }
    ]
  },

Finalmente, debe reiniciar dockerd:

sudo systemctl restart docker

Este método puede agregar permanentemente asignaciones de puertos al contenedor, pero también tiene el efecto secundario de detener todos los contenedores en la máquina host debido al reinicio de dockerd. Si los contenedores no están configurados para iniciarse automáticamente, no se iniciarán automáticamente incluso después de reiniciar dockerd. Si bien este método es efectivo, puede tener un impacto significativo en los contenedores en ejecución y no se recomienda en entornos de producción.

3.Conclusión

Aunque agregar dinámicamente asignaciones de puertos a contenedores no es una función nativa de Docker, los métodos descritos anteriormente pueden ayudar a lograrlo hasta cierto punto. Cada método tiene sus ventajas y desventajas, y los desarrolladores pueden elegir el más adecuado según sus necesidades específicas. En entornos de producción, se recomienda usar contenedores proxy o Docker Compose, ya que son relativamente simples y conllevan menos riesgos.Para aplicaciones que requieren cambios frecuentes en las asignaciones de puertos, se recomienda considerar una arquitectura de red flexible durante la fase de diseño para evitar modificaciones frecuentes en las asignaciones de puertos mientras el contenedor está en ejecución, minimizando así las interrupciones del servicio.

¡Puede visitar Novita AI para obtener más detalles!