gitlab-runner 中的 Docker-in-Docker

笔者个人理解:gitlab-runner 安装后就是一个监听状态的 runner,而通过 gitlab-runner register 注册的“实例”其实只是预定义的配置节,当消息抵达后,gitlab-runner 根据消息内容选择相应的配置节启动执行线程。为了方便阐述和理解,本文也将每个配置节/执行线程称为 runner 实例

runner executor

runner 实例的执行环境,一般用的较多的是 shelldocker,这两者的区别无需赘述。

让人困惑的是其它一些 executor:比如 Docker-SSHDocker-SSH+machine(从 GitLab Runner 10.0 开始, Docker-SSH 和 Docker-SSH+machine executors 被废弃了,并且将在后续某个版本中移除);还有 Docker machine,这个概念原本是 Docker 提出的,但是后面被 Docker 弃用了,GitLab 为了向前兼容保留了下来,也可以不用细究。

对于 docker executor 来说,runner 执行 job 的流程如下(摘自官网):

  1. The runner starts a Docker container using the defined entrypoint. The default from Dockerfile that may be overridden in the .gitlab-ci.yml file.
  2. The runner attaches itself to a running container.
  3. The runner prepares a script (the combination of before_script, script, and after_script).
  4. The runner sends the script to the container’s shell stdin and receives the output.

显然,第 1 步要启动容器,如果 runner 本身是以 docker 容器方式安装运行的,那么就涉及到 Docker-in-Docker 的概念了。

Docker-in-Docker

有些时候,我们需要在容器内部执行 docker 指令,一般有两种方式:

  1. 挂载宿主机 docker 环境。启动容器时挂载 /var/run/docker.sock,这样在容器内执行 docker 指令其实就等同于在容器外(宿主机中)执行 docker 指令。比如 docker build 构建一个镜像,该镜像并不存在于容器内部,而是在宿主机中。所以该方法并不是严格意义上的 docker in docker
  2. 容器内部有自己的一套 docker 环境。使用 docker:dind 镜像,可以直接使用它作为主容器,或是作为其它容器的服务容器(其它容器与之通信)。它在 docker 镜像(该镜像只包含客户端指令集)基础上安装了 Docker Daemon,因此可作为独立的 docker 环境使用,是真正意义上的 docker in docker。然而,除非你真正需要在容器内嵌套容器,或者某些场景下无法使用第 1 种方式,否则还是建议避免使用该方式。

这两种方式需要执行指令的容器处于 privileged mode,有一定的安全风险(privileged=true 将使得容器内 root 拥有宿主 root 的权限,否则只是宿主机上的普通用户),因此市面上又出现了一种 Using Nestybox sysbox Docker runtime 的方法,感兴趣的朋友请查阅参考资料,此处按过不表。

in gitlab-runner

如前所述,以 docker 方式安装 runner,且 executor 采用 docker,那么就要 Docker-in-Docker。因为 runner 只是启动新容器,不要求启动的容器在 runner 容器内部,我们可以采用第 1 种方式,如下:

docker run -d --name gitlab-runner --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \  # 挂载 socket
  gitlab/gitlab-runner:latest

另外,如果 docker executor 在 CI/CD job 中涉及到 docker 指令,那么也要 Docker-in-Docker。关键步骤如下:

  1. 注册 runner 实例,并配置其启动的容器为 privileged mode(注意配置的是每次 job 执行时启动的容器,而 runner 所在的容器,且 runner 并不一定是 docker 形式)。
sudo gitlab-runner register -n \
  --executor docker \
  --docker-image "docker:20.10.16" \
  --docker-privileged \  # privileged mode
  --other arguments
  1. 接下来,可以选择任一种方式实现 Docker-in-Docker:
    • config.toml 中增加卷映射 volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    • 或者在 .gitlab-ci.yml 中指定 docker:dind 如:
    services:
        - docker:20.10.16-dind
    

TLS 配置

如果在第 2 步采用 docker:dind 方式,那么由于涉及到容器间通信,需要选择是否启用 TLS。

若是,则在注册 runner 实例时,增加一个参数 --docker-volumes "/certs/client", 也可手动编辑 config.toml,增加卷映射 volumes = ["/certs/client", "/cache"];然后在 .gitlab-ci.yml 中设置变量 DOCKER_TLS_CERTDIR: "/certs"

若否,则在 .gitlab-ci.yml 中设置变量 DOCKER_TLS_CERTDIR: ""DOCKER_HOST: tcp://docker:2375

TLS 若未正确配置,会报 Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running? 错误。

参考资料

How To Run Docker in Docker Container 3 Easy Methods

本文转载于网络 如有侵权请联系删除

相关文章

  • 好文:机器人位姿描述与坐标变换

    机器人的位姿描述与坐标变换是进行工业机器人运动学和动力学分析的基础。本节简要介绍上述内容,明确位姿描述和坐标变换的关系,用到的基本数学知识就是——矩阵。1位姿表示位姿代表位置和姿态。任何一个刚体在空间坐标系(OXYZ)中可以用位置和姿态来精确、唯一表示其位置状态。位置:x、y、z坐标姿态:刚体与OX轴的夹角rx、与OY轴的夹角ry、与OZ轴的夹角rz假设基坐标系为OXYZ,刚体坐标系为O`X`Y`Z`。对于机器人而言,空间中的任何一个点都必须要用上述六个参数明确指定,即(x,y,z,rx,ry,rz),即便(x,y,z)都一样,(rx,ry,rz)不同代表机器人以不同的姿态去到达同一个点。刚体的位置可以用一个3x1的矩阵来表示,即刚体坐标系中心O`在基坐标系中的位置,即刚体的姿态可以用一个3x3的矩阵来表示,即刚体坐标系在基坐标系中的姿态,即其中,第一列表示刚体坐标系的O`X`轴在基坐标系的三个轴方向上的分量,称为单位主矢量。同理,第二列和第三列分别是刚体坐标系的O`Y`轴和O`Z`轴在基坐标系的三个轴方向上的分量。举个例子,在下图中,刚体M沿坐标系O中平移了(0,20,15),绕Z轴

  • 深入了解定制 Bash | Linux 中国

    Bash概览Bash参考手册中写道:根本上来说,shell只是一个能执行命令的宏处理器。宏处理器这个词意味着通过扩展文本跟符号,从而构成更复杂的表达式。 Bash参考手册第五版,Bash5.02019年5月除了能使用其它程序之外,Bashshell还含有一些内置命令和关键字。Bash内置功能很强大,甚至能够作为一门高级语言独当一面。Bash的几个关键字和操作符类似于C语言。Bash能够以交互式或非交互式模式启动。Bash的交互模式是一个很多人都熟悉的典型的终端/命令行界面。GNOME终端默认以交互模式打开Bash。Bash在非交互模式下运行的例子是,当命令和数据从文件或shell脚本通过管道传送到Bash时。其它Bash可以运行的模式包括:登录(login)、非登录(non-login)、远程(remote)、POSIX、Unixsh、受限(restricted),以及使用与用户不同的UID/GID模式。各种模式是可以相互组合的。比如,交互式+受限+POSIX或者非交互式+非登录+远程。不同的启动模式,决定着Bash所读取的启动文件。理解这些操作模式,有助于帮助我们修改启动文件。根据B

  • HTTP: 前端拾遗--同源策略和跨域处理

    什么是同源策略协议(http/https),端口(80/8080),域名(baidu/google)要相同才行document.domainJSONPjsonp-script标签的src属性不受同源策略限制,用此方式对非同源服务器请求资源,返回的JS代码会调用指定的函数,携带的参数就是所需的数据,这样就完成了跨域请求。JSONP(JSONwithPadding(填充))是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。1、jsonp没有使用XMLHttpRequest对象。2、jsonp只是在一种跨域的技巧。3、jsonp只支持Get方式letscriptDom=document.createElement("script"); scriptDom.src="请求地址?callback=函数名"; document.body.appendChild(scriptDom); 复制CORSCORS-Cross-OriginResourceSharing(跨域资源共享)是一种允许当前域(origin)的资源(比如html/js/w

  • 面试必备:形象理解深度学习中八大类型卷积

    WhatareConvolutions?Mathematically,Aconvolutionisanintegrationfunctionthatexpressestheamountofoverlapofonefunctiongasitisshiftedoveranotherfunctionf.数学上,卷积是一个积分函数,表示一个函数g在另一个函数f上移位时的重叠量。 Intutively,Aconvolutionactsasablenderthatmixesonefunctionwithanothertogivereduceddataspacewhilepreservingtheinformation.凭直觉,卷积就像一个搅拌机,将一个函数与另一个函数混合,在保留信息的同时减少数据空间。 IntermsofNeuralNetworksandDeepLearning:卷积在神经网络和深度学习方面的特征:卷积是带有可学习参数的过滤器(矩阵/向量),用于从输入数据中提取低维特征;它们具有保存输入数据点之间的空间或位置关系的属性;卷积神经网络通过加强相邻层神经元之间的局部连接模式来利用空间

  • Security+备考之路

    本人于2019年4月4日参加了Security+考试。本来是2018年12月报名的学习,因为事情比较多,一拖再拖到了三月底,本打算在奖学金获取时间结束前考试。备考时间一共为4天,时间过为仓促,只取得了765分,不过还是值了。下面分享一下我这四天的备考过程。备考经历:安全牛对于Security+(SY0-501)考试一共发了三本纸质材料。分别为Security+官方教材、Security+直播课讲义、练习题。我的备考步骤主要分为3阶段。首先花费两天将官方教材看完,看书过程中将每章节中的知识点总结,将重点内容记录在笔记本中,以备第三阶段的复习。在看完教材后开始做题,一次做两章,300道题左右,不懂的知识点可以查找书籍,将不会和做错的题目记录下来,花费时间一天半。最后使用半小时将讲义看完,如果哪里不能理解可以配合安全牛录播课1.75倍速播放。拖图题一定要理解记住,考试基本为原题。均为中文标准翻译。纸质材料练习题中几乎没有原题,所以不要死记硬背答案,要搞懂知识点,个人建议做题三遍,我是因为个人原因时间过紧,从事安全行业7年经验,所以一遍过。考试需要携带身份证、信用卡,提前半小时到场,进行检录后

  • 从Word2Vec到Bert,聊聊词向量的前世今生(一)

    阅读大概需要11分钟作者:小川Ryan整理:机器学习与自然语言处理 原文链接:https://zhuanlan.zhihu.com/p/58425003由于近日所做的工作与预训练模型联系比较紧密,却发现自己对几个词向量内部的细节有所遗忘了,因此打算写篇文章来拾起一些记忆,同时也方便以后供自己和他人查阅。一、语言模型1、n-grammodel谈到词向量则必须要从语言模型讲起,传统的统计语言模型是对于给定长度为m的句子,计算其概率分布P(w1,w2,...,wm),以表示该句子存在的可能性。该概率可由下列公式计算得到:但实际过程中句子的长度稍长便会为估计带来很大难度,因此n-gram模型对上述计算进行简化:假定第i个词的出现仅与其前n-1个词有关,即:实际计算中,通常采用n元短语在语料中出现的频率来估计其概率:为保留句子原有的顺序信息,我们当然希望n越大越好,但实际上当n略大时,该n元短语在语料中出现的频率就会越低,用上式估计得到的概率就容易出现数据稀疏的问题。而神经网络语言模型的出现,有效地解决了这个问题。2、NeuralNetworkLanguageModel神经网络语言模型不使用频率

  • Hive操作表部分总结

    创建表:createtabletableName(timeINT,useridBIGINT,urlSTRING,ipSTRINGCOMMENT'IPAddressoftheUser')COMMENT'ThisisthetableNametable'PARTITIONEDBY(dtSTRING,countryString) CLUSTEREDBY(userid)SORTEDBY(time)INTO32BUCKETS ROWFORMATDELIMITEDFIELDSTERMINATEDBY'001' MAPKEYSTERMINATEDBY'\003' STOREDasSEQUENCEFILE;按照userid进行分区划分到不同的桶中,并按照time值的大小进行排序存储。这样的组织结构允许通过userid属性高效地对集群列进行采样。删除表:droptabletableName;修改表、分区语句:altertabletableNameaddpartition_spec[LOCATION'location1

  • 【极客资讯】你了解过“互联网”的发展史吗?

    互联网·发展史如今的“互联网”已经渗透到了我们日常生活的点点滴滴,你出门都可以只带一部可以联网的手机便可以走遍天下。可你在享受“互联网”带来便利的同时,想过互联网的曾经和未来吗?今天小编就带粉丝们来一览“互联网”的曾经、如今和未来。(以下大部分内容来源于:百度百科)(以下内容中“WebX.0”相等于“互联网X.0”)互联网1.0···曾经···Web1.0时代是一个群雄并起,逐鹿网络的时代,虽然各个网站采用的手段和方法不同,但第一代互联网有诸多共同的特征,表现在技术创新主导模式、基于点击流量的盈利共通点、门户合流、明晰的主营兼营产业结构、动态网站。在Web1.0时代比较有意义的产品有:Netscape研发的第一款商用浏览器、Yahoo提吹了第一款互联网黄页以及Google推出了闻名至今的搜索引擎服务。Web1.0特征如下:一、互联网基本采用的是技术创新主导模式,信息技术的变革和使用对于网站的新生与发展起到了关键性的作用。新浪的最初就是以技术平台起家,搜狐以搜索技术起家,腾讯以即时通讯技术起家,盛大以网络游戏起家,在这些网站的创始阶段,技术性的痕迹相当之重。二、Web1.0的盈利都基于一

  • Django初探

    对于我来说,现在处于一个特殊的状态,就是知道哪些东西是需要的,相对重要的,但是我也很清楚的知道,这些东西是我目前不擅长的。所以为了能够落实自己的想法,同时逼迫自己学习一些原本陌生的东西,其实是一件很有意思的事情,前提是不能把自己逼得太紧,否则除了压力就是各种纰漏。Python这些年火得厉害,web框架也是应运而生。Django算是其中比较典型的一个web框架,Django遵守BSD版权,初次发布于2005年7月,并于2008年9月发布了第一个正式版本1.0,这个时间点上,国内的Java正是如火如荼的时候,web框架层出不穷,Python相对来说还算小众。没想到风水轮流转,没过多少年,就赶上了大数据的快车,数据分析里有Python的身影,devops近年来很火,自动化平台还是清一色的python框架,基本还是Django,所以说到Django,很多人并不陌生。我花时间简单学习了下,发现和我的预期相符。原因在后面再解释下。因为Python的跨平台,在windows下,linux都是兼容的,所以为了方便,我就直接在windows上做了测试。说几个坑。一个是下载了安装包之后,Python版本是

  • 海量之道系列文章之弱联网优化 (五)

    接系列文章《海量之道系列文章之弱联网优化(一)》《海量之道系列文章之弱联网优化(二)》《海量之道系列文章之弱联网优化(三)》《海量之道系列文章之弱联网优化(四)》3.1.2.接入调度① 就快接入在客户端接入服务器调度策略的演化过程中,我们最早采用了“就近接入”的策略,在距离客户端更近的地方部署服务器或使用CDN,期望通过减少RTT来提高网络交互响应性能。这个策略在国内的落地执行还需要加一个前缀:“分省分运营商”,这就给广大负责IDC建设的同学带来了巨大的精神和肉体折磨。在持续运营的过程中,根据观察到的数据,发现并非物理距离最近的就是最快的。回忆一下前面谈到的吞吐量指标BDP,它与链路带宽和RTT成正比关系,而RTT是受物理距离、网络拥塞程度、IDC吞吐量、跨网时延等诸多因素综合影响的,单纯的就近显然不够精细了。“就快接入”在“就近接入”策略的基础上改善提升,它利用客户端测速和报告机制,通过后台大数据分析,形成与客户端接入IP按就快原则匹配接入服务器的经验调度策略库,令客户端总能优先选择到最快的服务器接入点。对于接入服务器,我们按照访问目标数据属性纬度的不同,可以分为至少两个集合,它们分

  • 令人震惊的实验表明:我们的大脑使用「量子计算」

    都柏林三一学院的科学家们近日认为,我们人类的大脑使用量子计算。他们对一个原本用来证明量子引力存在的想法稍加改动,以探索人类大脑及其工作方式,之后得出了这一发现结果。测量的大脑功能还与短期记忆表现和潜意识相关,这表明量子过程也是大脑认知和意识功能的一部分。如果这个团队的研究结果能够得到证实——可能需要运用先进的多学科方法,它们将加深我们对于大脑如何运作以及如何维持甚至治愈大脑的大体理解。它们还可能有助于寻找到创新技术,并建造更先进的量子计算机。ChristianKerskens博士是都柏林三一学院神经科学研究所(TCIN)的首席物理学家,也是这篇刚刚发表在《物理通讯杂志》上的研究论文的合著者。他说:“我们对一个为证明量子引力存在的实验而开发的想法稍加改动;这样一来,你就可以运用已知的量子系统,它们可与未知系统相互作用。如果已知系统纠缠在一起,那么未知系统也肯定是量子系统。它避开了我们为一无所知的东西寻找测量仪器的困难。”“在实验中,我们使用‘脑水’的质子自旋作为已知系统。‘脑水’在我们人类的大脑中自然不断积聚,形成液体,而质子自旋可以用核磁共振成像(MRI)来加以测量。然后,通过使用特定

  • B树-查找

    B树系列文章 1. B树-介绍 2. B树-查找 3. B树-插入 4. B树-删除   查找 假设有一棵3阶B树,如下图所示。 下面说明在该B树中查找52的过程 首先,从根结点出发,根结点有两个键40和70,52在40和70之间,因此查找根结点的第二个儿子结点   接着,查找根结点的第二个儿子结点,该结点的第一个键值为55,52小于55,因此查找52可能在该结点的第一个儿子结点上   此时到达叶子结点,遍历该结点的键值列表,发现52在该键值列表上,说明该B树上有目标键值,搜索结束 到达叶子结点时,如果叶子结点上没有目标键值,说明B树上没有目标键值,搜索结束。   可以看出来,上述都给经历过的每个结点的 第一个不小于52的键值 标红处理了 这个键值在键值数组的下标刚好是要访问的儿子结点在儿子结点列表里的下标。  这里是查找的代码 /** *查找key,返回key所在结点及下标 *采用递归的方法 **/ func(bTreeNode*BTreeNode)search(k

  • Python实现字符串反转的方法

    第一种:使用字符串切片 >>>s="python" >>>s[::-1] 'nohtyp' >>>复制 第二种:使用列表的reverse方法 >>>s="python" >>>lst=list(s) >>>lst.reverse() >>>"".join(lst) 'nohtyp' >>>复制 手写reverse >>>defreverseString(s:str)->str: lst=list(s) i,j=0,len(s)-1 whilei<j: lst[i],lst[j]=lst[j],lst[i] i,j=i+1,j-1 return"".join(lst) >>>s='python' >>>reverseString(s) 'nohtyp' >>>复制 第三种:使用reduce >>>fromfunct

  • 修改Gradle本地仓库

    问题描述 Gradle默认的本地仓库为C:\Users\用户名\.gradle,不想让其一直下载东西占用C盘资源。 解决方法 新建环境变量名:GRADLE_USER_HOME,变量值为:D:\Gradle\.gradle; 这时候Eclipse上的Gradle会报错(原先路径的依赖找不到了),鼠标右键项目->Gradle->RefreshGradleProject...即可。

  • 时序数据库技术体系 – InfluxDB TSM存储引擎之TSMFile

    本文转自  http://hbasefly.com/2018/01/13/timeseries-database-4/   为了更加系统的对时序数据库技术进行全方位解读,笔者打算再写一个系列专题(嘿嘿,好像之前事务专题还有几篇关于分布式事务的文章没有写完,后续一定会补上)-时序数据库技术专题,详细解读当前主流时序数据库中会涉及到的相关技术点。这个专题前面已经写过三篇暖场文章: 《时序数据库–为万物互联插上一双翅膀》-介绍时序数据库的应用场景、时序数据库关注的核心技术点以及主流的几款时序数据库调研 《时序数据库技术体系–时序数据库存储模型设计》-介绍主流的几款时序数据库在顶层设计层面的取舍,嗯,非常重要 《时序数据库技术体系–初识InfluxDB》-介绍InfluxDB的一些基本概念、系统体系架构,为InfluxDB之后技术文章做个铺垫   接下来笔者将会用5篇左右的文章结合源码详细解读InfluxDB和Druid这两款时序数据库的核心技术实现,大体的文章脉络为: 《时序数据库技术体系–InfluxDBTSM存储引擎之TSMFile》-介绍InfluxDB中

  • javascript高级程序设计第3版——第1Java章 DOM扩展

    虽然DOM为与XML及HTML文档交互制定了一系列核心API,但仍然有几个规范对标准的DOM进行了扩展。这些扩展中有很多原来是浏览器专有的,但后来成为了事实标准,于是其他浏览器也都提供了相同的实现。

  • 背包问题

    背包问题 时间限制:3000 ms | 内存限制:65535 KB 难度:3   描述现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10);如果给你一个背包它能容纳的重量为m(10<=m<=20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大。   输入第一行输入一个正整数n(1<=n<=5),表示有n组测试数据;随后有n测试数据,每组测试数据的第一行有两个正整数s,m(1<=s<=10);s表示有s个物品。接下来的s行每行有两个正整数v,w。输出输出每组测试数据中背包内的物品的价值和,每次输出占一行。样例输入 1 315 510 28 39 复制 样例输出 65复制 #include<iostream> #include<cstring> #include<cstdio> #include<memory> #include<queue> #inc

  • 转载:腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口

    腾讯的接口是,返回数组http://fw.qq.com/ipaddress 返回值varIPData=newArray("61.135.152.194","","北京市",""); 新浪的接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js多地域测试方法:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=218.192.3.42 返回值varremote_ip_info={"ret":1,"start":"218.192.0.0","end":"218.192.7.255","country":"\u4e2d\u56fd","province":"\u5e7f\u4e1c","city":"\u5e7f\u5dde","district":"","isp":"\u6559\u80b2\u7f51","type":"\u5b66\u6821","desc":"\u5e7f\u5dde\u5927\u5

  • Navigation Basics

    参考官方文档:https://docs.flutter.dev/cookbook/navigation 一、切换页面的方式 直接切换,类似Android中的布局替换,因为flutter中都是组件,也就是组件直接替换。(不推荐) 路由跳转页面 基本路由+传参数(一般) Navigator.push()或者Navigator.of(context).push()跳转和传参数 MaterialPageRoute(builder:(context)=>constSecondRoute(title:"你好flutter")) Navigator.pop() 或者Navigator.of(context).pop() 返回页面类似Android中的onBackPressed()方法 命名路由+传参数(推荐) 普通命名路由直接传参数与接收(常用比较简单和自由) 需要在MaterialApp下的routes进行注册页面 Navigator.pushNamed(context,"路由名称","参数")进行跳转和传参数  接收参数 Mo

  • MySQL 查询优化之 or

    当使用or的时候是不会用到索引的 mysql>explainSELECT*FROMaladdin_resourceWHEREstate=1ORstate=2; +----+-------------+------------------+------+---------------+------+---------+------+-------+-------------+ |id|select_type|table|type|possible_keys|key|key_len|ref|rows|Extra| +----+-------------+------------------+------+---------------+------+---------+------+-------+-------------+ |1|SIMPLE|aladdin_resource|ALL|state|NULL|NULL|NULL|59074|Usingwhere| +----+-------------+------------------+------+-------------

  • 一个简单的存储过程(实现事务执行两个sql语句,修改可实现执行更多条sql语句)

     //实现数据库事务       publicstaticvoidExecuteSqlTran(stringSQLString1,stringSQLString2)       {           using(OracleConnectionconn=newOracleConnection(_DBConnectionString))           {               conn.Open();     &n

相关推荐

推荐阅读