GitLab CI 使用 Docker in Docker 无法访问 services 的坑

标签:Docker

昨天在给一个新项目写 .gitlab-ci.yml 配置时,发现一个域名无法解析的问题,部分配置如下:

variables:
  MYSQL_DATABASE: test
  MYSQL_ROOT_PASSWORD: test

test:
  stage: test
  services:
    - mysql:5.7
    - redis:4
  script:
    - apk update && apk add mysql-client
    - mysql -h mysql -u root -ptest < init.sql
    - docker build -t test .
    - docker run -t test pytest tests

在执行 mysql -h mysql -u root -ptest < init.sql 的时候,代码顺利地通过了;但在执行 docker run -t test pytest tests 的时候,却会报解析不了 mysql 的异常。

以我所知,Docker in Docker(dind) 实际上是调用宿主机的 Docker 进程,因此我尝试分析了一下原因:
假设宿主机叫 ci,在执行 test job 时,它会先启动 mysqlredis 这两个服务。这两个服务是运行在容器里的,ci 知道它们的 IP,但并不修改自己的域名解析。
接着 ci 再启动一个容器(假设叫 container1),加载 dind 镜像,向 /etc/hosts 注入 mysqlredis 这两个域名的 IP,然后执行 script 里的代码。因此,container1 是能解析 mysqlredis 这两个域名的。
然后 container1 在执行 docker run -t test pytest tests 的时候,实际上是调用 ci 的 Docker 来启动一个新容器(假设叫 container2)。然而 ci 并不会向 container2 注入这个两域名,container2 也无法通过桥接的网络来解析它们,于是就报错了。

虽然我不知道 GitLab CI 是否有标准的解决方案,但至少我手动注入域名是可以解决的:
script:
  - apk update && apk add mysql-client
  - mysql -h mysql -u root -ptest < init.sql
  - mysql=`grep mysql /etc/hosts | awk '{print $1}'`
  - redis=`grep redis /etc/hosts | awk '{print $1}'`
  - docker build -t test .
  - docker run --add-host mysql:$mysql --add-host redis:$redis -t test pytest tests

0条评论 你不来一发么↓

    想说点什么呢?