[Docker系列]3 Docker组件

426 阅读7分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

Docker相关组件

  • docker

对于我们最直观的即 Docker 命令,作为 Docker 客户端的完整实现,通过 Docker 命令来实现所有的 Docker 客户与服务端的通信

Docker 客户端于服务端的交互过程是怎么样的呢

Docker 组件向服务端发送请求后,服务端根据请求执行具体的动作并将结果返回给 DockerDocker 解析服务端的返回结果,并将结果通过命令行标准输出展示给用户。这样一次完整的客户端服务端请求就完成了

  • 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 为例

此时的 1 号进程为为 sh 进程,如果加上 --init

你会发现,此时的 1 号进程为 docker-init,而不是 sh

  • docker-proxy

docker-proxy 用来将容器启动的端口映射到主机,方便主机的访问。

假设目前启动一个 nginx 容器并将容器的 80 端口映射到主机的 8080 端口

查看容器 IP

此时使用 ps 查看主机是否有 docker-proxy 进程

可以发现当进行端口映射的时候,docker 为我们创建了一个 docker-proxy 进程,并且通过参数将容器的 IP 和端口传递给 docker-proxy,然后 proxy 通过 iptables 完成 nat 的转发

从最后一句可以看出,当我们主机访问 8080 端口的时候,iptable 将流量会转发给 172.17.0.2 的 80 ,从而实现主机上直接访问容器的业务

使用 curl 访问一下 nginx 容器


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 pull 拉取远程仓库的镜像
  • 重命名镜像:通过 docker tag 重命名镜像
  • 查看镜像:通过 docker image ls 查看本地已经存在的镜像
  • 删除镜像:通过 docekr rmi 删除没有用的镜像
  • 构建镜像
    • 第一种是通过 docker build 命令基于 dockerfile 构建镜像,推荐
    • 第二种是通过 docker commit 基于运行的容器提交为镜像

拉取镜像

拉取镜像直接使用 docker pull 命令即可,命令的格式如下

  • registry 为注册的服务器,docker 默认会从官网 docker.io 上拉取镜像,当然可以将 registry 注册为自己的服务器
  • repository 为镜像仓库,library 为默认的镜像仓库
  • image 为镜像的名称
  • tag 为给镜像打的标签

现在举个例子,这里有个镜像叫做 busybox,这个镜像集成了上百个常用的 Linux 命令,可以通过这个镜像方便快捷的查找生产环境中的问题,下面我们一起操作一波

  • docker pull busybox

首先会在本地镜像库查找,如果不存在本地库则直接去官网拉取镜像。拉取完镜像后随即查看镜像

  • 查看镜像---docker images

如果要查看指定的镜像,则使用docker image ls命令进一步查询

  • 重命名镜像采用打标签的方式重命名,格式如下

我们仔细观察这两个镜像,就会发现这两个镜像的 IMAGE ID其实是一样的,这是什么原因呢

实际上他们都是指向的同一个镜像文件,只不过其别名不一样而已,如果此时不想要mybox镜像,想删除这个镜像

  • 使用 docker rmi 删除镜像

此时再次使用 docker images 查看确实删除了

如何自己构建自己镜像呢

之前说过,有两种方式,一种是通过 docker commit 的方式,一种是 docker build 的方式。首先看看使用容器提交镜像的方式

此时启动了一个busybox容器并进入到容器,并在容器中创建一个文件,并写入内容

此时就在当前目录下创建了一个hello.txt文件并写入了内容。现在新建另外一个窗口,然后提交为一个镜像

然后使用 docker image ls 查看发现确实生成了镜像

然后我们再看看使用 dockerfile 的方式

  • dockerfile的每一行的命令都会生成独立的镜像层并拥有唯一的id
  • dockerfile命令是完全透明的,通过查看dockerfile的内容,就可以知道镜像是怎么一步步构建的
  • dockerfile为纯文本,方便做版本控制

先看看都有哪些命令

这么多,不存在的,我们先看一个dockerfile就知道如何用了

  • 首先第一行表示基于什么镜像构建

  • 第二行是拷贝文件 nginxrepo 到容器内的 /etc/yum.repos.d

  • 第三行为容器中运行 yum install 命令,安装 nginx 命令到容器

  • 第四行为生命容器使用 80 端口对外开放

  • 第五行定义容器启动时的环境变量 HOST=mynginx,容器启动后可以获取到环境变量 HOST 的值为 mynginx

  • 第六行定义容器的启动命令,命令格式为 json 数组。这里设置了容器的启动命令为 nginx ,并且添加了 nginx 的启动参数 -g 'daemon off;' ,使得 nginx 以前台的方式启动。

基本操作已经会了,现在我们看看镜像的实现原理

  • 第一行:创建一个 busybox 镜像层

  • 第二行:拷贝本机 test 文件到镜像内

  • 第三行 在 tmp 文件夹创建一个目录 testdir

为了清楚的看见镜像的存储结构,通过 docker build 构建镜像

因为我的 docker 使用的是 overlay2 文件驱动,所以进入到 /var/lib/docker/overlay2 ,使用 tree 查看

可以清楚的看到,dockerfile 的每一行命令都会生成一个镜像层