web-dev-qa-db-fra.com

Le coureur Gitlab CI ne peut pas exposer les ports des conteneurs Docker imbriqués

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?

17
Craig Otis

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 de localhost.

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.

6
VonC

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.

2
Jason Prawn

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.

1
Yoav Aharoni