services - gitlab runner docker
El corredor de Gitlab CI no puede exponer los puertos de los contenedores Docker anidados (4)
Al usar la docker:dind
cree que se crea un contenedor y los contenedores de composición de la ventana acoplable se configuran dentro de él. Expone los puertos a localhost dentro de la docker:dind
container. No puede acceder a esto como localhost
desde el entorno en el que se ejecuta su código.
Se ha configurado un nombre de host de la docker
para que haga referencia a esta docker:dind
contenedor de docker:dind
. Puede verificar usando cat /etc/hosts
.
En lugar de hacer referencia a localhost:9143
, debe utilizar la docker:9143
.
Al usar GitLab CI, así como el gitlab-ci-multi-runner
, no puedo hacer que los contenedores de Docker iniciados internamente expongan sus puertos al "host", que es la imagen de Docker en la que se está ejecutando la compilación.
Mi archivo .gitlab-ci.yml
:
test:
image: docker
stage: test
services:
- docker:dind
script:
- APP_CONTAINER_ID=`docker run -d --privileged -p "9143:9143" appropriate/nc nc -l 9143`
- netstat -a
- docker exec $APP_CONTAINER_ID netstat -a
- nc -v localhost 9143
Mi orden:
gitlab-ci-multi-runner exec docker --docker-privileged test
La salida:
$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 runner--project-1-concurrent-0:54664 docker:2375 TIME_WAIT
tcp 0 0 runner--project-1-concurrent-0:54666 docker:2375 TIME_WAIT
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
$ docker exec $APP_CONTAINER_ID netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:9143 0.0.0.0:* LISTEN
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
$ nc -v localhost 9143
ERROR: Build failed: exit code 1
FATAL: exit code 1
¿Qué estoy haciendo mal aquí?
La pregunta original sigue: el ejemplo anterior es más corto y fácil de probar.
Tengo una imagen de aplicación que escucha en el puerto 9143
. Su inicio y configuración se gestionan a través de docker-compose.yml
, y funciona muy bien en mi máquina local con docker-compose up
. Puedo acceder a localhost:9143
sin problemas.
Sin embargo, cuando se ejecuta en GitLab CI (la versión gitlab.com
) a través de un corredor compartido, el puerto no parece estar expuesto.
La parte relevante de mi .gitlab-ci.yml
:
test:
image: craigotis/buildtools:v1
stage: test
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com/craigotis/myapp
- docker-compose up -d
- sleep 60 # a temporary hack to get the logs
- docker-compose logs
- docker-machine env
- docker-compose port app 9143
- netstat -a
- docker-compose ps
- /usr/local/bin/wait-for-it.sh -h localhost -p 9143 -t 60
- cd mocha
- npm i
- npm test
- docker-compose down
La salida es:
$ docker-compose logs
...
app_1 | [Thread-1] INFO spark.webserver.SparkServer - == Spark has ignited ...
app_1 | [Thread-1] INFO spark.webserver.SparkServer - >> Listening on 0.0.0.0:9143
app_1 | [Thread-1] INFO org.eclipse.jetty.server.Server - jetty-9.0.z-SNAPSHOT
app_1 | [Thread-1] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@6919dc5{HTTP/1.1}{0.0.0.0:9143}
...
$ docker-compose port app 9143
0.0.0.0:9143
$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 runner-e11ae361-project-1925166-concurrent-0:53646 docker:2375 TIME_WAIT
tcp 0 0 runner-e11ae361-project-1925166-concurrent-0:53644 docker:2375 TIME_WAIT
tcp 0 0 runner-e11ae361-project-1925166-concurrent-0:53642 docker:2375 TIME_WAIT
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
$ docker-compose ps
stty: standard input: Not a tty
Name Command State Ports
----------------------------------------------------------------------------------------
my_app_1 wait-for-it.sh mysql_serve ... Up 8080/tcp, 0.0.0.0:9143->9143/tcp
mysql_server docker-entrypoint.sh --cha ... Up 3306/tcp
$ /usr/local/bin/wait-for-it.sh -h localhost -p 9143 -t 60
wait-for-it.sh: waiting 60 seconds for localhost:9143
wait-for-it.sh: timeout occurred after waiting 60 seconds for localhost:9143
El contenido de mi docker-compose.yml
:
version: ''2''
networks:
app_net:
driver: bridge
services:
app:
image: registry.gitlab.com/craigotis/myapp:latest
depends_on:
- "db"
networks:
- app_net
command: wait-for-it.sh mysql_server:3306 -t 60 -- java -jar /opt/app*.jar
ports:
- "9143:9143"
db:
image: mysql:latest
networks:
- app_net
container_name: mysql_server
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=true
Parece que mi contenedor de aplicaciones está escuchando en 9143
, y está expuesto correctamente al corredor de GitLab compartido, pero no parece estar realmente expuesto. Funciona bien en mi máquina local. ¿Hay alguna solución / ajuste especial que necesito para que esto funcione dentro de un contenedor Docker que se ejecuta en GitLab?
La documentación oficial de gitab-ci en gitlab.com se refiere al ejemplo de PostgreSQL
Su CI de trabajo no intenta conectarse a localhost, sino al nombre del servicio
La palabra clave de
services
define solo otra imagen de ventana acoplable que se ejecuta durante su compilación y está vinculada a la imagen de ventana acoplable que define la palabra clave de imagen. Esto le permite acceder a la imagen de servicio durante el tiempo de construcción.El contenedor de servicios para MySQL será accesible bajo el nombre de host
mysql
.
Entonces, para acceder a su servicio de base de datos, debe conectarse al host llamadomysql
lugar de a un socket olocalhost
.
Puede verificar si esto se aplica en su caso e intentar acceder a su servicio de app:9143
en la app:9143
lugar de localhost:9143
.
Por lo general, una máquina acoplable no se ejecuta en localhost, sino en un host acoplador con alguna otra dirección IP. Trate de usar docker-machine ip
para obtener su ip de host docker.
Tu docker-compose.yml
parece estar bien.
Pero creo que hay un error en tu ip o enrutamiento de puertos. Como puedo ver en su información compartida, su aplicación se está ejecutando en el puerto 9143 en ip 0.0.0.0 como 0.0.0.0:9143 .
y lo está accediendo como localhost:9143
, que puede interpretarse como 127.0.0.1:9143
.
Según this .
127.0.0.1 is the loopback address (also known as localhost).
0.0.0.0 is a non-routable meta-address used to designate an invalid, unknown, or non-applicable target (a ‘no particular address’ place holder).
¿Puedes intentar ejecutar tu aplicación en 127.0.0.1:9143
luego compartir el resultado?
ACTUALIZAR
o puede usar el servicio para ejecutarlo por nombre de servicio como la documentación sugiere:
La palabra clave de servicios define solo otra imagen de ventana acoplable que se ejecuta durante su compilación y está vinculada a la imagen de ventana acoplable que define la palabra clave de imagen. Esto le permite acceder a la imagen de servicio durante el tiempo de construcción.
El contenedor de servicios para MySQL será accesible bajo el nombre de host mysql
. Entonces, para acceder a su servicio de base de datos, debe conectarse al host llamado mysql en lugar de a un socket o localhost
.