【DevOps工具篇】Gitlab Runner设置(使用Docker in docker作为Runner)

2020-12-18T14:11:24+08:00 | 7分钟阅读 | 更新于 2020-12-18T14:11:24+08:00

Macro Zhao

【DevOps工具篇】Gitlab Runner设置(使用Docker in docker作为Runner)

@TOC

推荐超级课程:

强烈建议学习本文之前,先阅读学习此篇:


在这篇文章中,我们将使用另一种称为“Docker in Docker”的方法,在GitLab运行程序服务中注册docker执行器,以便构建、测试和部署我们的容器化项目。

Docker in Docker

Docker in Docker简而言之,就是你在docker容器内运行一个docker引擎(守护进程),而不是在宿主机上运行docker引擎。如果你想要在一个专用的docker引擎中管理容器,与宿主机的docker引擎隔离,并且担心访问宿主机的docker引擎可能会出现问题,那么Docker in Docker可能会很有用。

更新Docker Compose文件

在我们开始注册docker-in-docker执行器之前,我们需要对我们的docker-compose.yml文件进行一些小的更新。

version: '3.8'  
services:  
  
  gitlab-server:  
    image: 'gitlab/gitlab-ce:latest'  
    container_name: gitlab-server  
    environment:  
      GITLAB_ROOT_EMAIL: "admin@example.com"  
      GITLAB_ROOT_PASSWORD: "Abcd@0123456789"  
      GITLAB_OMNIBUS_CONFIG: |  
        external_url 'http://localhost:8000'  
        nginx['listen_port'] = 8000  
    ports:  
      - '8000:8000'  
    volumes:  
      - ./gitlab/config:/etc/gitlab  
      - ./gitlab/data:/var/opt/gitlab  
  
    # 添加gitlab服务器到自定义网络的更改  
    networks:  
      - gitlab-in-docker  
  
  gitlab-runner:  
    image: gitlab/gitlab-runner:alpine  
    container_name: gitlab-runner  
    network_mode: 'host'  
    volumes:  
      - /var/run/docker.sock:/var/run/docker.sock  

添加自定义docker网络的更改

networks:  
  gitlab-in-docker:  
    name: gitlab-in-docker  
    driver: bridge

我们在这里所做的更新是将GitLab服务器容器放在一个名为gitlab-in-docker的自定义docker网络中,驱动程序为bridge。我们这样做的原因是,使用docker in docker的docker执行器无法与docker host网络一起工作,因为docker in docker使用容器链接,而宿主网络不能与容器链接一起使用。

至少当我在尝试使用dind服务时,这是发生的情况

因此,为了在我们的流水线作业中克隆项目仓库,作业的容器将使用其容器名称访问我们的GitLab服务器,即http://gitlab-server:8000。由于我们没有使用host网络,所以无法从作业的容器内通过[http://localhost:8000](http://localhost:8000/)访问GitLab服务器。 因此,我们需要将GitLab服务器容器和作业执行器容器都放在一个名为gitlab-in-docker的自定义网络中,这样它们就可以通过容器名称而不是localhost相互访问。

在注册运行器执行器时,运行器需要访问服务器容器。它将通过localhost获得访问权限,因为服务器可以通过http://localhost:8000访问,并且运行器容器在host网络上,所以它可以访问localhost。 作业在克隆仓库时需要访问服务器。它将通过使用服务器容器名称gitlab-server来访问,因为作业容器和服务器容器都在同一个网络中,即gitlab-in-docker网络。

对网络感到厌倦了?让我们跳转到运行器注册部分

注册Docker in Docker执行器

转到仓库 → 设置 → CI/CD → 运行器

点击新建项目运行器按钮

添加标签,以便运行器可以使用匹配的执行器通过标签挑选作业。给出一些描述,然后点击创建运行器按钮。这将重定向您到以下页面,您可以在步骤1中看到运行器注册命令。

步骤1复制运行器注册命令,并使用以下docker compose命令登录到您的GitLab运行器容器。

docker compose exec -it gitlab-runner /bin/bash

一旦登录到运行器容器,将上述步骤1中的命令粘贴到运行器容器内,并添加以下附加参数。 确保从您的步骤1中更新以下注册命令中的--token

gitlab-runner register  --url http://localhost:8000   
                        --token glrt-qL_FTjkAGqy7SHcYYStx   
                        --executor docker   
                        --name "Docker in Docker Runner"   
                        --docker-image "docker:27.2.0"   
                        --docker-privileged   
                        --docker-volumes "/certs/client"   
                        --docker-network-mode "gitlab-in-docker"   
                        --clone-url "http://gitlab-server:8000"

我们将executor设置为docker,这与我们上一篇文章 中的操作相同。然后给它一个有意义的名称并设置默认的docker镜像。我们在这里使用docker镜像docker:27.2.0,以便在我们的流水线作业中运行docker命令时可以使用docker CLI。 为了启动构建和服务(docker in docker)容器,它使用privileged模式。如果您想要使用Docker-in-Docker,您必须在您的Docker容器中始终使用privileged = true。 我们还为服务和作业容器挂载了/certs/client,这对于Docker客户端使用SSL证书以TLS模式连接是必需的。 最后,我们将网络设置为gitlab-in-docker,这是我们的自定义网络,并将克隆URL设置为前面讨论的http://gitlab-server:8000。 一旦您的命令准备就绪,按Enter键,并在提示输入时继续按Enter键,除非您想在提示时更新任何值。

一旦这个命令成功运行,您的运行器页面上应该会出现一个成功消息。

点击查看运行器按钮,您应该能看到包括您新注册的docker in docker运行器在内的所有运行器。

现在我们的作业执行器已经准备好了。让我们通过转到仓库 → 构建 → 流水线编辑器 → 配置流水线来更新我们的.gitlab-ci.yml

然后粘贴以下代码片段。

使用docker in docker构建:

  stage: build  
  image: docker:27.2.0  
  services:  
    - docker:27.2.0-dind  
  variables:  
    DOCKER_HOST: tcp://docker:2376  
    DOCKER_TLS_CERTDIR: "/certs"  
  
  tags:  
    - docker-in-docker  
  script:  
    - docker ps  
    - docker run -d --rm --name nested-container1-in-pipelinejob alpine sleep 20  
    - docker run -d --rm --name nested-container2-in-pipelinejob alpine sleep 20  
    - docker ps  
    - sleep 20

services: docker:27.2.0-dind 实际上是Docker官方提供的Docker in Docker服务。当我们为作业定义一个service时,作业将首先等待该服务启动,一旦服务准备就绪,实际的作业容器将启动并处理作业的script部分。 variables将作为环境变量传递给作业容器,以便在运行docker CLI命令时从作业容器内访问docker引擎。DOCKER_TLS_CERTDIR将设置SSL证书目录,而DOCKER_HOST将通过SSL端口即2376设置与docker引擎的默认连接。 如果您想不使用TLS连接,请按以下方式设置变量。

variables:  
    DOCKER_HOST: tcp://docker:2375  
    DOCKER_TLS_CERTDIR: ""

一旦docker in docker容器/服务准备就绪,执行器将开始通过拉取docker:27.2.0镜像来启动作业容器,然后运行script命令。

同时,您可以在宿主机的docker引擎上检查,您有两个新容器。一个用于服务(dind),一个用于作业执行。

一旦作业到达script部分并开始运行这两个docker命令来运行docker容器

  • docker run -d –rm –name nested-container1-in-pipelinejob alpine sleep 20
  • docker run -d –rm –name nested-container2-in-pipelinejob alpine sleep 20 这将在docker in docker服务内运行两个新容器。您可以通过登录到服务容器来确认这两个新容器
docker exec -it 0e7a68f4dfbf sh

0e7a68f4dfbf是docker in docker容器的ID 然后运行以下命令以获取在dind服务内运行的所有容器。

docker --tlscacert=/certs/client/ca.pem   
       --tlscert=/certs/client/cert.pem   
       --tlskey=/certs/client/key.pem   
       --tlsverify=1   
       ps

结果应该看起来像这样。

在这里,您可以看到我们将父容器(即gitlab runnerjob executor)及其子容器彼此分离,与宿主机的docker引擎隔离。

Docker in Docker的已知问题

Docker in Docker是推荐的配置,但GitLab文档在这里指出了某些已知问题点击查看

  • docker-compose命令:在此配置中默认情况下不提供此命令。
  • 缓存:每个作业都在一个新的环境中运行。因为每个构建都通过其services获得Docker引擎的自己的实例,所以并发作业不会引起冲突。然而,作业可能会更慢,因为没有缓存层。

Docker执行器的替代方案

要在运行器上不启用privileged模式或不挂载宿主机docker套接字的情况下构建Docker镜像,GitLab提供了以下两种替代方案,

© 2011 - 2025 Macro Zhao的分享站

关于我

如遇到加载502错误,请尝试刷新😄

Hi,欢迎访问 Macro Zhao 的博客。Macro Zhao(或 Macro)是我在互联网上经常使用的名字。

我是一个热衷于技术探索和分享的IT工程师,在这里我会记录分享一些关于技术、工作和生活上的事情。

我的CSDN博客:
https://macro-zhao.blog.csdn.net/

欢迎你通过评论或者邮件与我交流。
Mail Me

推荐好玩(You'll Like)
  • AI 动·画
    • 这是一款有趣·免费的能让您画的画中的角色动起来的AI工具。
    • 支持几十种动作生成。
我的项目(My Projects)
  • 爱学习网

  • 小乙日语App

    • 这是一个帮助日语学习者学习日语的App。
      (当然初衷也是为了自用😄)
    • 界面干净,简洁,漂亮!
    • 其中包含 N1 + N2 的全部单词和语法。
    • 不需注册,更不需要订阅!完全免费!
  • 小乙日文阅读器

    • 词汇不够?照样能读日语名著!
    • 越读积累越多,积跬步致千里!
    • 哪里不会点哪里!妈妈再也不担心我读不了原版读物了!
赞助我(Sponsor Me)

如果你喜欢我的作品或者发现它们对你有所帮助,可以考虑给我买一杯咖啡 ☕️。这将激励我在未来创作和分享更多的项目和技术。🦾

👉 请我喝一杯咖啡

If you like my works or find them helpful, please consider buying me a cup of coffee ☕️. It inspires me to create and share more projects in the future. 🦾

👉 Buy me a coffee