首页 文章

Gitlab CI运行器无法公开嵌套Docker容器的端口

提问于
浏览
16

当使用GitLab CI以及 gitlab-ci-multi-runner 时,我无法获得内部启动的Docker容器以将其端口暴露给"host",这是运行构建的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

我在这做错了什么?

Original Question Follows - above is a shorter, easier-to-test example

我有一个监听端口 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

seems 就像我的应用程序容器正在监听 9143 ,它似乎实际上是暴露的 . 它在我的本地机器上工作正常 - 是否有一些特殊的解决方法/调整我需要在GitLab上运行的Docker容器中进行此工作?

4 回答

  • 0

    通常,docker机器不会在localhost上运行,而是在具有其他ip地址的docker主机上运行 . 尝试使用 docker-machine ip 来获取您的docker主机ip .

  • 1

    官方gitab-ci on gitlab.com documentation指的是example of PostgreSQL

    Its working CI不会尝试连接到localhost,而是尝试连接到service name

    services关键字仅定义在构建期间运行的另一个docker镜像,并链接到image关键字定义的docker镜像 . 这允许您在构建期间访问服务映像 . 可以在主机名mysql下访问MySQL的服务容器 . 因此,为了访问您的数据库服务,您必须连接到名为mysql的主机,而不是socket或localhost .

    您可以检查这是否适用于您的情况,并尝试在 app:9143 而不是 localhost:9143 中访问您的应用程序服务 .

  • 5

    你的 docker-compose.yml 似乎还可以 .

    但我认为您的IP或端口路由存在错误 . 正如我从您的共享信息中看到的那样,您的应用程序在 port 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

    或者您可以使用服务按服务名称运行它documentation建议:

    services关键字仅定义在构建期间运行的另一个docker镜像,并链接到image关键字定义的docker镜像 . 这允许您在构建期间访问服务映像 .

    可以在 hostname mysql 下访问MySQL的服务容器 . 因此,为了访问您的数据库服务,您必须连接到名为mysql的主机而不是套接字或 localhost .

  • 1

    使用 docker:dind 时,会创建一个容器,并在其中设置docker-compose容器 . 它将端口暴露给 docker:dind 容器中的localhost . 您无法从执行代码的环境中将其作为 localhost 进行访问 .

    设置了 docker 的主机名,供您引用此 docker:dind 容器 . 您可以使用 cat /etc/hosts 进行检查 .

    而不是引用 localhost:9143 ,你应该使用 docker:9143 .

相关问题