¿Cómo conectar los servicios Docker Swarm a una red Docker normal?

¿Cómo conectar los servicios Docker Swarm a una red Docker normal?

Tengo un único VPS pequeño que tiene una variedad de servicios, como una instalación de WordPress y algunas aplicaciones web. Durante algún tiempo he ejecutado todos los servicios como contenedores Docker. Como tengo una variedad de dominios y subdominios que apuntan a este cuadro, uso el proxy frontend Traefik para capturar los puertos web y luego enrutarlos internamente en una red Docker.

Empiezo Traefik así:

#!/bin/bash

# Removes the restart policy from previous containers
CONTAINER_LABEL=traefik-instance
../../bin/remove-restart.sh $CONTAINER_LABEL

mkdir --parents /var/log/traefik
mkdir --parents /etc/letsencrypt-traefik

docker run \
    --label $CONTAINER_LABEL \
    --publish 80:80 \
    --publish 443:443 \
    --volume $PWD/traefik.toml:/etc/traefik/traefik.toml \
    --volume $PWD/rules:/etc/traefik/rules \
    --volume /etc/letsencrypt-traefik:/etc/letsencrypt-traefik \
    --volume /var/log/traefik:/log \
    --network dockernet \
    --detach \
    --restart always \
    traefik:1.6

Todo esto funciona muy bien. Recientemente descubrí Docker Swarm y me gustaría convertir todos mis contenedores en servicios, lo que me brindará servicios de replicación, actualizaciones continuas e implementaciones sin tiempo de inactividad. Sin embargo, me gustaría hacer el cambio poco a poco, para que Traefik pueda enrutar tanto a servicios Swarm como a contenedores ordinarios (que no sean Swarm).

Entonces, para lanzar Traefik como servicio, ahora estoy haciendo lo siguiente. Notarás que estoy usando puertos no estándar para realizar pruebas:

#!/bin/bash

# Using "traefik2" while I am experimenting with multiple services
mkdir --parents /var/log/traefik2
mkdir --parents /etc/letsencrypt-traefik

docker service create \
    --publish 8080:80 \
    --publish 8443:443 \
    --mount type=bind,source=$PWD/traefik.toml,target=/etc/traefik/traefik.toml \
    --mount type=bind,source=$PWD/rules,target=/etc/traefik/rules \
    --mount type=bind,source=/etc/letsencrypt-traefik,target=/etc/letsencrypt-traefik \
    --mount type=bind,source=/var/log/traefik2,target=/log \
    --network traefiknet \
    traefik:1.6

Esto también funciona cuando se apunta a un servicio web Swarm que aparece en la misma red.

Entonces, tengo dos redes Docker (entre los diversos valores predeterminados que Docker crea para sí mismo) así:

root@box:~/docker# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1aa479f13faa        dockernet           bridge              local
k71hpg1n0lo9        traefiknet          overlay             swarm

Esto da como resultado que tengo un contenedor Traefik en funcionamiento que puede ver los contenedores Docker y un servicio Traefik en funcionamiento que puede ver los servicios Swarm. Sin embargo, no pueden verse.

Para intentar solucionar este problema, he intentado agregar la red Docker al inicio del servicio Traefik Swarm:

--network dockernet \

En otras palabras, quiero que este servicio se conecte tanto a la red puente (antigua) como a la red superpuesta (nueva). Lamentablemente me sale esto:

Respuesta de error del demonio: la red dockernet no se puede utilizar con servicios. Solo se pueden utilizar redes con alcance del enjambre, como las creadas con el controlador de superposición.

¿Existe alguna forma de que mi nuevo servicio pueda conectarse a la red anterior o, de hecho, hay alguna forma de que mis contenedores antiguos puedan conectarse a la nueva red? Intenté buscar el error, pero no parece haber muchas menciones al respecto; Me pregunto si muchas personas todavía no han encontrado este uso extremo de Swarm.

(Por supuesto, una solución es convertir todos mis contenedores en servicios, pero para evitar un cambio importante, prefiero hacerlo lentamente si es posible).

Probando redes conectables

Luego eliminé mis servicios y probé esto:

docker network rm traefiknet
docker network create driver=overlay --attachable traefiknet

Luego recreé el servicio Traefik y se inicia. Evidentemente sigue funcionando porque dirige el tráfico a un servicio que también se ha unido a la superposición traefiknet.

Sin embargo, creé un contenedor que no es de servicio y lo conecté exclusivamente a traefiknet, y el --network-aliasservicio no puede ver lo que creo con eso. Curiosamente, si entro en este contenedor que no es Swarm,poderHaga ping al contenedor Swarm Traefik para que la red funcione. (He intentado crear un servicio Alpine Shell, conectado a traefiknet, y desde aquí no puedo hacer ping ni al nombre del contenedor que no es Swarm ni a su --network-alias).

Actualización de Docker

Intenté actualizar Docker de 17.03.2-ce a 18.06.1-ce, porque una fraseen el manualIndiqué que mi versión anterior de Docker podría ser la causa del problema:

La comunicación entre un contenedor y un servicio de enjambre configura la comunicación entre un contenedor independiente y un servicio de enjambre, utilizando una red superpuesta conectable. Esto es compatible con Docker 17.06 y versiones posteriores.

Sin embargo, esto tampoco ha ayudado.

Respuesta1

Creo que tengo una solución para esto, aunque todavía hay algunas cosas que no entiendo. Para establecer el contexto para esta respuesta, a continuación se muestra cómo instalo ahora un contenedor Docker que no es Swarm:

#!/bin/bash

# Save pwd and then change dir to the project root
STARTDIR=`pwd`
cd `dirname $0`/../..

# Removes the restart policy from previous containers
CONTAINER_LABEL=ilovephp-staging
NETWORK_ALIAS=${CONTAINER_LABEL}
./bin/remove-restart.sh $CONTAINER_LABEL

docker run \
    --network swarmnet \
    --network-alias ${NETWORK_ALIAS} \
    --env TUTORIAL_ENVIRONMENT_NAME=staging \
    --detach \
    --restart always \
    ilovephp:2018-08-19

# Go back to original dir
cd $STARTDIR

Como puede ver, según la actualización de mi pregunta, ahora puedo colocar un contenedor en una red Swarm conectable.

He descubierto que la razón por la que no se puede hacer ping a esto desde un servicio Swarm es que le falta un archivo --name. Tan pronto como agrego un --name, es accesible. Curiosamente, si intento hacer ping al servicio Swarm o al contenedor Swarm desde el contenedor Docker, funciona:

root@server:~# docker exec -it loving_allen sh
/ # # *** Ping a specific Swarm container ***
/ # ping alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09
PING alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09 (10.0.1.23): 56 data bytes
64 bytes from 10.0.1.23: seq=0 ttl=64 time=0.516 ms
^C
--- alpine-swarm.1.9llv2hvv5xnc1c8diuhfh5m09 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.516/0.516/0.516 ms
/ # # *** Ping the Swarm service ***
/ # ping alpine-swarm
PING alpine-swarm (10.0.1.22): 56 data bytes
64 bytes from 10.0.1.22: seq=0 ttl=64 time=0.376 ms
^C
--- alpine-swarm ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.137/0.231/0.376 ms

Por lo tanto, mi plan original era convertir mi instancia de Traefik de un contenedor a un servicio Swarm, pero eso no funcionará porque no se podrá acceder a contenedores sin nombre que no sean Swarm. Mi solución ahora es convertir todos mis sistemas de contenedores a servicios primero y luego, una vez hecho todo, puedo convertir la instancia de Traefik al final. De esa manera siempre estaré conectándome del contenedor al servicio, y no al revés.

(No puedo agregar --namecorreos electrónicos ya que si se reinicia el host Docker, intentará recrear contenedores con el mismo nombre y fallarán porque los contenedores antiguos todavía tendrán esos nombres contradictorios. Y no puedo usar --rmpara arreglar eso, porque ¡No es compatible con --restart!Más sobre eso aquí).

Todavía no entiendo por qué no se puede hacer ping a un nombre de contenedor generado por Docker desde un contenedor Swarm, ni por qué --network-aliastampoco ayuda. Pero, dado que mi solución sólo necesita ser temporal hasta que todos mis sistemas sean servicios Swarm, probablemente no importe.

información relacionada