当前位置: 首页 > 科技观察

如何在Docker中使用Docker

时间:2023-03-17 10:41:36 科技观察

一、典型应用场景在CI中,通常有一个CIEngine负责解析流程并控制整个构建过程,而真正的构建则交给Agent来完成。比如Jenkins,GitLab都是一样的。如下图所示,连接CIEngine的Agent有很多种。这是为了满足不同项目对施工环境的要求。同时Agent是动态的,只在构建时需要,构建完成后销毁。CI非常适合实践容器、serverless等技术,因此Agent在生产过程中往往会被容器化。那么问题来了?如果CIEngine也容器化了,如何使用Agent容器在容器中构建呢?如果Agent已经容器化了,如何在Agent上建立镜像?这就是本文要给出的答案,如何在Docker中使用Docker。2、两种使用模式我们要知道Docker是工作在C/S模式下的,主要分为两部分,DockerCLI和DockerDaemon。DockerCLI,即客户端,为用户提供对Docker的命令行操作,如dockercreate/images/ps等。DockerDamon,即守护进程,负责接受用户指令,维护生命周期的容器。2.1Docker中的DockerDocker中的Docker,以下简称DinD。如上图,可以直接在Container中运行一个DockerDaemon,然后在Container中使用DockerCLI工具来操作容器。这样容器中的DockerDaemon就完全独立于外部,具有很好的隔离特性。看起来Container类似于一个VM,但是DinD的作者并不是很推荐。主要原因是安全问题。DinD需要以特权模式启动,这种嵌套存在安全隐患。这样,响应命令的容器就嵌套在了使用docker命令的容器中。2.2Docker之外的DockerDocker之外的Docker,以下简称DooD。如上图所示,Docker工作在C/S模式。在使用时,用户侧重于C端,而生命周期管理则在S端。因此,只需要将容器的外部DockerDaemon服务挂载到Container中即可。让Container误认为DockerDaemon在本地运行。当使用DockerCLI命令进行操作时,外部的DockerDaemon会响应请求。这样,响应命令的容器与使用docker命令的容器处于同一级别。3.Docker环境下的演示3.1DinD运行DinD容器$dockerrun--privileged-eDOCKER_TLS_CERTDIR=""-d--namedockerddocker:dindd6414f2ff0076c42de19a8a1fe122481c1a72b3bd45fd490dbe1c427414b4139运行带CLI的容器链接DinD容器$dockerrun--rm-it--linkdockerd:dockerdocker:latestsh在DinD容器中拉取镜像#拉取镜像$dockerpullshaowenchen/devops-java-sample#查看镜像$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEshaowenchen/devops-java-samplelatestfa4651c24a186weeksago122MB与独立的DockerDaemon环境一样。检查外部是否受到影响。输入exit退出容器,宿主机上的DockerDaemon$dockerimages|grepfa4651c24a18如预期。DinD使用独立的Docker守护进程,对外部实例没有直接影响。3.2DooD运行一个容器$dockerrun--rm-it-v/var/run/docker.sock:/var/run/docker.sockalpinesh安装curl这里为了避免安装DockerCLI,直接使用curl调用APIDocker守护进程。$apkupdate&&apkaddcurl拉取镜像$curl-XPOST--unix-socket/var/run/docker.sockhttp://localhost/images/create?fromImage=shaowenchen/docker-robotframework&tag=latest...{"status":"状态:Downloadednewerimageforshaowenchen/docker-robotframework"}查看拉取的镜像,输入exit退出容器,在主机$dockerimages|greprobotframeworkshaowenchen/docker-robotframeworklatestd99cfa7ee71612monthsago1.5GB使用DockerDaemon,达到预期。DooD直接使用的外部Docker守护进程。4.Kubernetes环境下演示4.1DinD创建一个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","sleep86400;"]CreateDeployment$kubectlapply-fdind.yaml查看创建的Pod名称$kubectlgetpod|grepdinddind-5446ffbc8d-68q282/2Running012s输入Pod$kubectlexec-itdind-5446ffbc8d-68q28-cdocker-clish测试是否使用独立的DockerDaemon$dockerpullnginx$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEnginxlatestdaee903b4e433daysago133MB符合预期,这里只展示了刚刚拉取的Nginx镜像,完全独立于宿主机的DockerDaemon。4.2DooD创建一个dood.yaml文件,内容如下:apiVersion:apps/v1kind:Deploymentmetadata:name:doodspec:replicas:1selector:matchLabels:app:doodtemplate:metadata:labels:app:doodspec:containers:-image:docker:最新名称:docker-clisecurityContext:privileged:falsecommand:["/bin/sh"]args:["-c","sleep86400;"]volumeMounts:-mountPath:/var/run/docker.sockname:volume-dockervolumes:-hostPath:path:/var/run/docker.socktype:""name:volume-dockerCreateDeployment$kubectlapply-fdood.yaml查看创建的Pod名称$kubectlgetpod|grepdooddood-667d8bcfc6-d5fzf1/1Running015s输入Pod$kubectlexec-itdood-667d8bcfc6-d5fzf-cdocker-clish测试主机的DockerDaemon$dockerimages|wc694828509是否按预期使用,这里的Docker命令使用的是外部DockerDaemon。5.参考https://medium.com/better-programming/about-var-run-docker-sock-3bfd276e12fdhttps://github.com/jpetazzo/dind