Gitlab CI runner не может открыть порты вложенных контейнеров Docker

При использовании GitLab CI, а также gitlab-ci-multi-runnerЯ не могу заставить контейнеры Docker с внутренним запуском выставлять свои порты "хосту", который является образом Docker, в котором выполняется сборка.

мой .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

Моя команда:

gitlab-ci-multi-runner exec docker --docker-privileged test

Выход:

$ 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

Что я здесь не так делаю?

Далее следует оригинальный вопрос - выше приведен более короткий и простой в тестировании пример

У меня есть изображение приложения, которое слушает порт 9143, Его запуск и конфигурация управляются через docker-compose.ymlи прекрасно работает на моей локальной машине с docker-compose up - Я могу получить доступ localhost:9143 без проблем.

Тем не менее, при работе на GitLab CI (gitlab.com версия) через общего бегуна, порт, кажется, не выставлен.

Соответствующая часть моего .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

Выход:

$ 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

Содержание моего 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

Кажется, что мой контейнер приложения прослушивает 9143и он должным образом выставлен общему GitLab Runner, но, похоже, на самом деле не подвергается. Он отлично работает на моей локальной машине - есть ли какой-то особый обходной путь / твик, который мне нужен, чтобы сделать эту работу внутри контейнера Docker, работающего на GitLab?

5 ответов

Когда используешь docker:dind Контейнер создан, и ваши контейнеры docker-compose настроены в нем. Это выставляет порты на локальный хост в пределах docker:dind контейнер. Вы не можете получить доступ к этому как localhost из среды, в которой выполняется ваш код.

Имя хоста docker настроен для вас, чтобы ссылаться на это docker:dind контейнер. Вы можете проверить с помощью cat /etc/hosts,

Вместо ссылки localhost:9143 ты должен использовать docker:9143,

Официальная документация gitab-ci на gitlab.com ссылается на пример PostgreSQL.

Его рабочий CI не пытается подключиться к localhost, а скорее к имени службы

services Ключевое слово определяет просто еще одно изображение Docker, которое запускается во время вашей сборки и связано с образом Docker, который определяет ключевое слово image. Это позволяет получить доступ к образу сервиса во время сборки.

Сервисный контейнер для MySQL будет доступен под именем хоста mysql,
Итак, чтобы получить доступ к службе базы данных, вам необходимо подключиться к хосту с именем mysql вместо розетки или localhost ,

Вы можете проверить, применимо ли это в вашем случае, и попытаться получить доступ к службе приложений в app:9143 вместо localhost:9143,

Если вы запускаете GitLab CI Runner с Docker -executor через привязку сокета, используйте host.docker.internal-host, потому что ваше приложение работает на хост-машине, но не на гостевой.

      # Run and ssh into dind-container
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker:20.10-dind /bin/sh
      # Next commands run in dind-container

docker run --rm -d -p 8888:80 nginx:alpine
...

wget -qO- "http://localhost:8888/"
wget: can't connect to remote host (127.0.0.1): Connection refused

wget -qO- "http://127.0.0.1:8888/"
wget: can't connect to remote host (127.0.0.1): Connection refused

wget -qO- "http://docker:8888/"
wget: bad address 'docker:8888'

wget -qO- "http://host.docker.internal:8888/"
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Обычно докер-машина запускается не на локальном хосте, а на хосте докера с другим IP-адресом. Попробуйте использовать docker-machine ip чтобы получить ваш док-хост IP.

Ваш docker-compose.yml кажется, все в порядке.

Но я думаю, что есть ошибка с вашим IP или маршрутизацией порта. Как я вижу из вашей общей информации, ваше приложение работает на порту 9143 по IP- адресу 0.0.0.0 как 0.0.0.0:9143.

и вы получаете доступ к нему как localhost:9143, что можно интерпретировать как 127.0.0.1:9143,

По этому.

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).

Можете ли вы попробовать запустить приложение на 127.0.0.1:9143 тогда поделись результатом.

ОБНОВИТЬ

или вы можете использовать сервис, чтобы запустить его по имени сервиса, как указано в документации:

Ключевое слово services определяет просто еще одно изображение Docker, которое запускается во время вашей сборки и связано с образом Docker, который определяет ключевое слово image. Это позволяет получить доступ к образу сервиса во время сборки.

Сервисный контейнер для MySQL будет доступен под именем хоста mysql , Итак, чтобы получить доступ к службе базы данных, вам нужно подключиться к хосту с именем mysql вместо сокета или localhost ,

Другие вопросы по тегам