Docker相关组件
- docker
对于我们最直观的即 Docker 命令,作为 Docker 客户端的完整实现,通过 Docker 命令来实现所有的 Docker 客户与服务端的通信
Docker 客户端于服务端的交互过程是怎么样的呢
Docker 组件向服务端发送请求后,服务端根据请求执行具体的动作并将结果返回给 Docker,Docker 解析服务端的返回结果,并将结果通过命令行标准输出展示给用户。这样一次完整的客户端服务端请求就完成了
- dockerd
dockerd 为 Docker 服务端后台的常驻进程,负责接收客户端的请求,处理具体的任务并将结果返回客户端
那么 Docke r客户端采用哪几种方式发送请求
第一种方式:通过 unix 套接字与服务端通信,配置的格式为:unix://socket_path。默认的 dockerd 生成的 socket文件存放在 /var/run/docker.sock,此文件只能是 root 用户才能访问,这也是为什么刚安装完 Docker 后只能root 来进行访问操作
第二种方式:采用 TCP 的方式与服务端通信,配置格式为:tcp://host:por,为了保证安全,通常还需要使用TLS认证
第三种方式:通过 fd 文件描述符的方式,配置格式为:fd://这种格式一般用于 systemd 管理的系统中。
- docker-init
在 Linux 中,有一个叫做 init 的进程,是所有进程的父进程,用来回收那些没有回收的进程,同样的道理,在容器内部,可以通过加上参数 --init 的方式,让 1 号进程管理所有的子进程,例如回收僵尸进程
举个例子示范,以镜像 busybox 为例
![[Docker系列]3 Docker组件_nginx](https://file.cfanz.cn/uploads/png/2022/03/30/8/dab8b42aI8.png)
此时的 1 号进程为为 sh 进程,如果加上 --init
![[Docker系列]3 Docker组件_nginx_02](https://file.cfanz.cn/uploads/png/2022/03/30/8/P68MS328e6.png)
你会发现,此时的 1 号进程为 docker-init,而不是 sh 了
- docker-proxy
docker-proxy 用来将容器启动的端口映射到主机,方便主机的访问。
假设目前启动一个 nginx 容器并将容器的 80 端口映射到主机的 8080 端口
![[Docker系列]3 Docker组件_服务端_03](https://file.cfanz.cn/uploads/png/2022/03/30/8/364I20cQd2.png)
查看容器 IP
![[Docker系列]3 Docker组件_docker_04](https://file.cfanz.cn/uploads/png/2022/03/30/8/284d431AIS.png)
此时使用 ps 查看主机是否有 docker-proxy 进程
![[Docker系列]3 Docker组件_服务端_05](https://file.cfanz.cn/uploads/png/2022/03/30/8/K8E476092D.png)
可以发现当进行端口映射的时候,docker 为我们创建了一个 docker-proxy 进程,并且通过参数将容器的 IP 和端口传递给 docker-proxy,然后 proxy 通过 iptables 完成 nat 的转发
![[Docker系列]3 Docker组件_nginx_06](https://file.cfanz.cn/uploads/png/2022/03/30/8/46F5K27102.png)
从最后一句可以看出,当我们主机访问 8080 端口的时候,iptable 将流量会转发给 172.17.0.2 的 80 ,从而实现主机上直接访问容器的业务
使用 curl 访问一下 nginx 容器
![[Docker系列]3 Docker组件_docker_07](https://file.cfanz.cn/uploads/png/2022/03/30/8/e8bP6NfeX6.png)
contained组件
- containerd
contained主要负责容器的生命周期管理,同时还会负责一些其他的功能
主要负责那些功能?
镜像的管理
接收dockerd的请求
管理存储相关资源
管理网络资源
- containerd-shim
containerd-shim 的意思是垫片,类似于拧螺丝时夹在螺丝和螺母之间的垫片。containerd-shim 的主要作用是将 containerd 和真正的容器进程解耦,使用 containerd-shim 作为容器进程的父进程,从而实现重启 containerd 不影响已经启动的容器进程。
- ctr
ctr 实际上是 containerd-ctr,它是 containerd 的客户端,主要用来开发和调试,在没有 dockerd 的环境中,ctr 可以充当 docker 客户端的部分角色,直接向 containerd 守护进程发送操作容器的请求。
Docker镜像使用
来,继续,我们看看镜像是什么。镜像是一个只读的镜像模版且包含了启动容器所需要的文件结构内容。镜像不包含动态数据,构建完成将不会改变
对于镜像都有哪些操作?
![[Docker系列]3 Docker组件_服务端_08](https://file.cfanz.cn/uploads/png/2022/03/30/8/CccQa14461.png)
对于镜像的操作分为:
- 拉取镜像:通过docker pull拉取远程仓库的镜像
- 重命名镜像:通过docker tag重命名镜像
- 查看镜像:通过docker image ls查看本地已经存在的镜像
- 删除镜像:通过docekr rmi删除没有用的镜像
- 构建镜像
- 第一种是通过docker build命令基于dockerfile构建镜像,推荐
- 第二种是通过docker commit基于运行的容器提交为镜像
拉取镜像
拉取镜像直接使用 docker pull 命令即可,命令的格式如下
![[Docker系列]3 Docker组件_服务端_09](https://file.cfanz.cn/uploads/png/2022/03/30/8/M261QMf0M2.png)
- registry为注册的服务器,docker 默认会从官网docker.io上拉取镜像,当然可以将registry注册为自己的服务器
- repository为镜像仓库,library为默认的镜像仓库
- image为镜像的名称
- tag为给镜像打的标签
现在举个例子,这里有个镜像叫做 busybox,这个镜像集成了上百个常用的 Linux 命令,可以通过这个镜像方便快捷的查找生产环境中的问题,下面我们一起操作一波
- docker pull busybox
首先会在本地镜像库查找,如果不存在本地库则直接去官网拉取镜像。拉取完镜像后随即查看镜像
- 查看镜像---docker images
如果要查看指定的镜像,则使用docker image ls命令进一步查询
- 重命名镜像采用打标签的方式重命名,格式如下
![[Docker系列]3 Docker组件_服务端_10](https://file.cfanz.cn/uploads/png/2022/03/30/8/28C2W21I0H.png)
我们仔细观察这两个镜像,就会发现这两个镜像的 IMAGE ID其实是一样的,这是什么原因呢
实际上他们都是指向的同一个镜像文件,只不过其别名不一样而已,如果此时不想要mybox镜像,想删除这个镜像
- 使用 docker rmi 删除镜像
此时再次使用 docker images 查看确实删除了
如何自己构建自己镜像呢
之前说过,有两种方式,一种是通过 docker commit 的方式,一种是 docker build 的方式。首先看看使用容器提交镜像的方式
![[Docker系列]3 Docker组件_服务端_11](https://file.cfanz.cn/uploads/png/2022/03/30/8/N987A7V4aZ.png)
此时启动了一个busybox容器并进入到容器,并在容器中创建一个文件,并写入内容
![[Docker系列]3 Docker组件_nginx_12](https://file.cfanz.cn/uploads/png/2022/03/30/8/48B6Z2Q21f.png)
此时就在当前目录下创建了一个hello.txt文件并写入了内容。现在新建另外一个窗口,然后提交为一个镜像
![[Docker系列]3 Docker组件_nginx_13](https://file.cfanz.cn/uploads/png/2022/03/30/8/BX4N3AB4S1.png)
然后使用 docker image ls 查看发现确实生成了镜像
然后我们再看看使用 dockerfile 的方式
- dockerfile的每一行的命令都会生成独立的镜像层并拥有唯一的id
- dockerfile命令是完全透明的,通过查看dockerfile的内容,就可以知道镜像是怎么一步步构建的
- dockerfile为纯文本,方便做版本控制
先看看都有哪些命令
![[Docker系列]3 Docker组件_nginx_14](https://file.cfanz.cn/uploads/png/2022/03/30/8/4793e2V178.png)
这么多,不存在的,我们先看一个dockerfile就知道如何用了
![[Docker系列]3 Docker组件_docker_15](https://file.cfanz.cn/uploads/png/2022/03/30/8/0663640E94.png)
- 首先第一行表示基于什么镜像构建
- 第二行是拷贝文件
nginx。repo 到容器内的/etc/yum.repos.d - 第三行为容器中运行
yum install 命令,安装nginx 命令到容器 - 第四行为生命容器使用 80 端口对外开放
- 第五行定义容器启动时的环境变量
HOST=mynginx,容器启动后可以获取到环境变量HOST 的值为mynginx。 - 第六行定义容器的启动命令,命令格式为
json 数组。这里设置了容器的启动命令为nginx ,并且添加了nginx 的启动参数-g 'daemon off;' ,使得nginx 以前台的方式启动。
基本操作已经会了,现在我们看看镜像的实现原理
![[Docker系列]3 Docker组件_docker_16](https://file.cfanz.cn/uploads/png/2022/03/30/8/1e05484D96.png)
- 第一行:创建一个
busybox 镜像层 - 第二行:拷贝本机
test 文件到镜像内 - 第三行 在
tmp 文件夹创建一个目录testdir
为了清楚的看见镜像的存储结构,通过 docker build 构建镜像
![[Docker系列]3 Docker组件_docker_17](https://file.cfanz.cn/uploads/png/2022/03/30/8/81166MK8M6.png)
因为我的 docker 使用的是 overlay2 文件驱动,所以进入到 /var/lib/docker/overlay2 ,使用 tree 查看
可以清楚的看到,dockerfile 的每一行命令都会生成一个镜像层
![[Docker系列]3 Docker组件_docker_18](https://file.cfanz.cn/uploads/png/2022/03/30/8/80d1S540fG.png)










