Lors de l'utilisation de GitLab CI, ainsi que du gitlab-ci-multi-runner
, je ne parviens pas à faire en sorte que les conteneurs Docker démarrés en interne exposent leurs ports à l'hôte, qui est l'image Docker dans laquelle la construction est en cours d'exécution.
Mon fichier .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
Ma commande:
gitlab-ci-multi-runner exec docker --docker-privileged test
Le résultat:
$ 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'est-ce que je fais mal ici?
La question initiale suit - ci-dessus est un exemple plus court, plus facile à tester
J'ai une image d'application qui écoute sur le port 9143
. Son démarrage et sa configuration sont gérés via docker-compose.yml
et fonctionnent parfaitement sur mon ordinateur local avec docker-compose up
- je peux accéder à localhost:9143
sans problème.
Cependant, lorsqu’il est exécuté sur GitLab CI (la version gitlab.com
) via un coureur partagé, le port ne semble pas être exposé.
La partie pertinente de mon .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 sortie est:
$ 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
Le contenu de mon 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
Il semble que il sembleque mon conteneur d’application écoute sur 9143
et qu’il soit correctement exposé au coureur GitLab partagé, mais il ne semble pas réellement exposé. Cela fonctionne bien sur ma machine locale - existe-t-il une solution de contournement particulière/Tweak J'ai besoin de faire ce travail inside un conteneur Docker s'exécutant sur GitLab?
L'offical gitab-ci dans la documentation de gitlab.com fait référence au exemple de PostgreSQL
Son CI fonctionnel n'essaie pas de se connecter à localhost, mais plutôt au nom du service
Le mot clé
services
définit simplement une autre image de menu fixe qui est exécutée pendant votre construction et qui est liée à l'image de menu fixe définie par le mot clé image. Cela vous permet d'accéder à l'image de service pendant la phase de génération.Le conteneur de services pour MySQL sera accessible sous le nom d’hôte
mysql
.
Donc, pour accéder à votre service de base de données, vous devez vous connecter à l'hôte nommémysql
au lieu d'un socket ou delocalhost
.
Vous pouvez vérifier si cela s'applique à votre cas et essayez d'accéder à votre service d'application avec app:9143
au lieu de localhost:9143
.
Lorsque vous utilisez docker:dind
, un conteneur est créé et vos conteneurs docker-compos sont configurés. Il expose les ports à localhost dans le conteneur docker:dind
. Vous ne pouvez pas accéder à cela en tant que localhost
à partir de l'environnement d'exécution de votre code.
Un nom d’hôte de docker
est configuré pour vous permettre de référencer ce conteneur docker:dind
. Vous pouvez vérifier en utilisant cat /etc/hosts
.
Au lieu de référencer localhost:9143
, vous devriez utiliser docker:9143
.
Habituellement, un ordinateur Docker ne fonctionne pas sur l'hôte local, mais sur un hôte Docker avec une autre adresse IP. Essayez d’utiliser docker-machine ip
pour obtenir l’ip de votre hôte docker.