1. 典型适用场景

在 CI 中,通常会有一个 CI Engine 负责解析流程,控制整个构建过程,而将真正的构建交给 Agent 去完成。例如,Jenkins 、GitLab 均是如此。

如下图, 连接 CI Engine 的 Agent, 种类很多。这是为了满足不同项目对构建环境的要求。

同时 Agent 是动态的,构建时才需要,构建完成时即销毁。CI 非常适合实践容器、Serverless 等技术,因此在生产过程中 Agent 经常是容器化的。

那么问题就来了?如果 CI Engine 也是容器化的,在容器中如何使用 Agent 容器去构建呢?如果 Agent 已经是容器化的,那么在 Agent 上如何构建镜像呢?这就是本篇将给出的回答,如何在 Docker 中使用 Docker。

2. 两种使用模式

我们需要知道 Docker 以 C/S 模式工作,主要分为两个部分,Docker CLI 和 Docker Daemon 。Docker CLI ,也就是客户端,提供给用户命令行操作 Docker,例如 docker create/images/ps 等。Docker Damon ,也就是守护进程,负责接受用户指令,维护容器的生命周期。

2.1 Docker in Docker

Docker in Docker ,以下简称 DinD 。

如上图,可以在 Container 中直接运行一个 Docker Daemon ,然后使用 Container 中的 Docker CLI 工具操作容器。

这种方式下,容器中的 Docker Daemon 完全独立于外部,具有良好的隔离特性。看起来,Container 类似一个 VM ,但 DinD 的作者自己也不是很推荐。

主要原因还是安全问题。DinD 需要以特权模式启动,这种嵌套会带来潜在的安全风险。

这种方式下,响应命令的容器嵌套于使用 docker 命令的容器。

2.2 Docker outside of Docker

Docker outside of Docker ,以下简称 DooD 。

如上图,Docker 以 C/S 模式工作,使用时用户关注的是 C 端,而生命周期的管理在 S 端。

因此,只需要将 Container 的外部 Docker Daemon 服务挂载到 Container 。让 Container 误以为本地运行了 Docker Daemon,使用 Docker CLI 命令操作时,外部的 Docker Daemon 会响应请求。

这种方式下,响应命令的容器与使用 docker 命令的容器处于同一层级。

3. Docker 环境下的演示

3.1 DinD

  • 运行 DinD 容器

docker run --privileged -e DOCKER_TLS_CERTDIR="" -d --name dockerd  docker:dind

d6414f2ff0076c42de19a8a1fe122481c1a72b3bd45fd490dbe1c427414b4139
  • 运行带 CLI 的容器链接 DinD 容器

docker run --rm -it --link dockerd:docker docker:latest sh
  • 在 DinD 容器中,拉取镜像

拉取镜像

docker pull shaowenchen/devops-java-sample

查看镜像

docker images

REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZEshaowenchen/devops-java-sample   latest              fa4651c24a18        6 weeks ago         122MB

使用起来和一个独立的 Docker Daemon 环境一样。

  • 查看外部是否受影响

键入 exit 退出容器,通过主机上的 Docker Daemon

docker images |grep fa4651c24a18

符合预期。DinD 使用的是独立的 Docker Daemon,对外部的实例没有直接影响。

3.2 DooD

  • 运行一个容器

docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock alpine sh
  • 安装 curl

这里为了避免安装 Docker CLI ,直接使用 curl 调用 Docker Daemon 的 API。

apk update && apk add curl
  • 拉取镜像

curl -XPOST --unix-socket /var/run/docker.sock http://localhost/images/create?fromImage=shaowenchen/docker-robotframework&tag=latest

...{"status":"Status: Downloaded newer image for shaowenchen/docker-robotframework"}
  • 查看拉取的镜像

键入 exit 退出容器,通过主机上的 Docker Daemon

docker images |grep robotframework

shaowenchen/docker-robotframework                              latest                         d99cfa7ee716        12 months ago       1.5GB

符合预期。DooD 方式直接使用的外部 Docker Daemon。

4. Kubernetes 环境下的演示

4.1 DinD

  • 创建一个 dind.yaml 文件,内容如下:

apiVersion: apps/v1kind: Deploymentmetadata:name: dindspec:replicas: 1selector:matchLabels:app: dindtemplate:metadata:labels:app: dindspec:containers:- name: dockerdimage: 'docker:dind'env:- name: DOCKER_TLS_CERTDIRvalue: ""securityContext:privileged: true- name: docker-cliimage: 'docker:latest'env:- name: DOCKER_HOSTvalue: 127.0.0.1command: ["/bin/sh"]args: ["-c", "sleep 86400;"]
  • 创建 Deployment

kubectl apply -f dind.yaml
  • 查看创建的 Pod 名

kubectl get pod |grep dind

dind-5446ffbc8d-68q28   2/2     Running       0          12s
  • 进入 Pod

kubectl exec -it dind-5446ffbc8d-68q28  -c docker-cli sh
  • 测试是否使用独立的 Docker Daemon

docker pull nginx
docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZEnginx               latest              daee903b4e43        3 days ago          133MB

符合预期,这里仅显示了刚拉取的 Nginx 的镜像,完全独立于主机的 Docker Daemon。

4.2 DooD

  • 创建一个 dood.yaml 文件,内容如下:

apiVersion: apps/v1kind: Deploymentmetadata:name: doodspec:replicas: 1selector:matchLabels:app: doodtemplate:metadata:labels:app: doodspec:containers:- image: docker:latestname: docker-clisecurityContext:privileged: falsecommand: ["/bin/sh"]args: ["-c", "sleep 86400;"]volumeMounts:- mountPath: /var/run/docker.sockname: volume-dockervolumes:- hostPath:path: /var/run/docker.socktype: ""name: volume-docker
  • 创建 Deployment

kubectl apply -f dood.yaml
  • 查看创建的 Pod 名

kubectl get pod  |grep dood

dood-667d8bcfc6-d5fzf   1/1     Running   0          15s
  • 进入 Pod

kubectl exec -it dood-667d8bcfc6-d5fzf  -c docker-cli sh
  • 测试是否使用的是主机的 Docker Daemon

docker images |wc

69       482      8509

符合预期,这里 Docker 命令使用的就是外部的 Docker Daemon。

5. 参考

  • https://medium.com/better-programming/about-var-run-docker-sock-3bfd276e12fd

  • https://github.com/jpetazzo/dind

docker中使用git_如何在 Docker 中使用 Docker相关推荐

  1. react 中渲染html_如何在React中识别和解决浪费的渲染

    react 中渲染html by Nayeem Reza 通过Nayeem Reza 如何在React中识别和解决浪费的渲染 (How to identify and resolve wasted r ...

  2. ppt中加入html,如何在ppt中插入html网页.ppt

    如何在ppt中插入html网页 如何在PPT中插入html网页 来自 晓冬 痕迹 -- 在演示ppt的时候,如果能直接调用设计精美的html页面,将会让你的演示锦上添花,此处介绍一种使用控件将网页插入 ...

  3. typescript中函数_如何在TypeScript中合成Canvas动画

    typescript中函数 by Changhui Xu 徐昌辉 如何在TypeScript中合成Canvas动画 (How to Compose Canvas Animations in TypeS ...

  4. 在oracle中使用存储过程,如何在ORACLE中使用JAVA存储过程(详解)

    如何在Oracle中使用Java存储过程 (详解) 一.如何缔造java存储过程? 通常有三种步骤来缔造java存储过程. 1.使用oracle的sql语句来缔造: e.g.使用create or r ...

  5. html中加入echarts,如何在react中使用echarts

    如何在react中echarts 1.安装echarts包npm install echarts --save 2.react使用echartsconst echarts = require('ech ...

  6. wps启用编辑按钮在哪里_如何在wps工具栏中添加按钮 如何在Excel中添加删除命令按钮...

    延伸:如何在Excel中添加删除命令按钮 描述:在Excel 2003中,很多常用的命令按钮都放置在工具栏中,用户可以很方便地进行操作.添加命令主要是通过拖动的方式完成的,其具体的操作如下:骤一,在视 ...

  7. php中调用代码,如何在php中调用javascript代码?

    JavaScript是客户端脚本语言,PHP是用于与数据库交互的服务器端脚本语言.那么如何在php中调用javascript代码?下面本篇文章给大家介绍一下.有一定的参考价值,有需要的朋友可以参考一下 ...

  8. linux中安装pip_如何在Linux中安装PIP

    linux中安装pip In this tutorial, we'll go over the steps to install pip in Linux. The pip command allow ...

  9. html5在li中添加按钮,如何在html5blank_nav()中的ul和li中添加类?

    我尝试在ul li中添加类, 以及如何在html5blank_nav()使用html5blank模板时在ul和li上添加类.如果在html5blank_nav()使用html5blank模板, 如何在 ...

最新文章

  1. 五分钟带你了解哈希算法
  2. 代码之谜(零)- 开篇/前言/序
  3. bug之bootstrap switch Uncaught TypeError: Cannot read property 'apply' of undefined
  4. 2019阿里云开年Hi购季新用户分会场全攻略!
  5. ios UITableView默认选中第一行
  6. 鸡啄米MFC教程笔记之七:对话框:为控件添加消息处理函数
  7. Linux 命令之 typeset -- 声明 shell 变量,设置变量的属性
  8. android 键盘遮盖输入框_Android各种键盘挡住输入框解决办法
  9. Gulp,grunt,seajs/require和browserify/webpack的区别
  10. 容器技术Docker K8s 53 边缘容器服务(ACK@Edge)-阿里云边缘容器服务
  11. mysql主从中断原因_mysql主从中断
  12. Android 官方独立 adb / fastboot 工具包
  13. stm8单片机程序加密方法 id加密技巧
  14. 吉林大学计算机科学与技术学院刘菁,吉林大学2011-2012学年奖学金获奖名单
  15. Python画中国地图-数据导入
  16. Python如何实现行人识别-人体识别
  17. img、link、html使用样式
  18. Shiro 生成秘钥
  19. 62%中国AI毕业生赴美,机器学习人才最高产大学出炉
  20. FFmpeg 音频转换

热门文章

  1. matlab中fval函数,请问matlab中[x,fval,exitflag,output] = simulannealbnd(fun,...)函数怎么调用...
  2. 线段树区改区查标记永久化板子
  3. 数据库自增主键用完了怎么办
  4. linux 常用基础命令
  5. 关于index.html被缓存问题
  6. mysql引擎和事务
  7. Luogu 3267 [JLOI2016/SHOI2016]侦察守卫
  8. CentOS 6.6 搭建Zabbix 3.0.3 过程
  9. 【JavaScript】Uncaught TypeError: Illegal invocation
  10. Java并发编程之volatile变量