Лидер Gitlab CI не смог открыть порты вложенных контейнеров 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 [email protected]{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, но на самом деле он не отображается. Он отлично работает на моей локальной машине - есть ли какое-то специальное решение/настройка, мне нужно сделать эту работу внутри контейнера Docker, работающего на GitLab?
Ответы
Ответ 1
Официальная gitab-ci в документации gitlab.com относится к примеру PostgreSQL
Его рабочий CI не пытается подключиться к localhost, а скорее к имени службы
Ключевое слово services
определяет только другое изображение докеров, которое выполняется во время сборки и связано с изображением докера, которое определяется ключевым словом изображения. Это позволяет вам получить доступ к служебному изображению во время сборки.
Сервисный контейнер для MySQL будет доступен под именем хоста mysql
.
Итак, для доступа к службе базы данных вам нужно подключиться к узлу с именем mysql
вместо сокета или localhost
.
Вы можете проверить, применимо ли это в вашем случае, и попытаться получить доступ к службе вашего приложения в app:9143
вместо localhost:9143
.
Ответ 2
Обычно докер-машина не запускается на локальном хосте, а на хост-докере с другим IP-адресом. Попробуйте использовать docker-machine ip
, чтобы получить IP-адрес вашего докере.
Ответ 3
Ваш docker-compose.yml
выглядит нормально.
Но я думаю, что есть ошибка в вашей маршрутизации ip или порта.
Как я могу видеть из вашей общей информации, ваше приложение работает на порту 9143 на ip 0.0.0.0 как 0.0.0.0:9143.
и вы обращаетесь к нему как localhost:9143
,
который можно интерпретировать как 127.0.0.1:9143
.
Согласно 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).
Можете ли вы попробовать запустить приложение на 127.0.0.1:9143
, а затем поделиться результатом.
UPDATE
или вы можете использовать сервис для запуска его по имени службы
как документация предлагают:
Ключевое слово services определяет только другое изображение докеров, которое выполняется во время сборки и связано с изображением докера, которое определяется ключевым словом изображения. Это позволяет вам получить доступ к служебному изображению во время сборки.
Сервисный контейнер для MySQL будет доступен под именем хоста mysql
.
Итак, для доступа к службе базы данных вам нужно подключиться к узлу с именем mysql вместо сокета или localhost
.
Ответ 4
При использовании docker:dind
создается контейнер, и ваши контейнеры для компоновки докеров устанавливаются внутри него. Он предоставляет порты localhost в контейнере docker:dind
. Вы не можете получить доступ к этому как localhost
из среды, в которой выполняется ваш код.
Имя хоста docker
настроено для ссылки на этот контейнер docker:dind
. Вы можете проверить, используя cat /etc/hosts
.
Вместо ссылки localhost:9143
вы должны использовать docker:9143
.