Docker引擎

Docker Engine是容器的核心,是容器运行的基础。Docker具有模块化设计,这意味着您可以交换/自定义其某些组件。

docker-engine-arch

Docker架构有五个组件:

  • docker CLI

  • dockerd

  • containerd

  • containerd-shim

  • runc

runc

runclibcontainer的轻量级CLI包装器,用于生成和运行容器。

您可以仅使用CLI运行容器而无需Docker。为此,您必须拥有符合OCI标准的捆绑包。容器的捆绑包是一个包含名为config.json的规范文件和根文件系统的目录。config.json用于在特定状态下创建容器。

config.json示例

{  
  "ociVersion": "0.6.0-dev",  
  "platform": {     
    "os": "linux",     
    "arch": "amd64"   
  },   
  "process": {   
    "terminal": true,   
    "args": ["sh"],   
    "env": ["PATH=/usr/local/sbin:/usr/local/bin:/bin", ...]
  ...
}

给定捆绑包,您可以使用runc简单运行容器

# 创建一个空文件夹
mkdir ~/mycontainer
cd ~/mycontainer
# 创建rootfs,一种方法是复用docker导出
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -
# 为捆绑包创建名为"config.json"的新规范文件
runc spec
# 运行容器
runc run mycontainerid

Docker是runc的更高级抽象,runclibcontainer的CLI。此外,您还可以将docker设置为您自己的运行时dockerd守护进程--add-runtime

containerd

containerd是Docker模块化架构中的一层。当您向dockerd发出请求时,containerd管理与镜像分发相关的进程,例如将镜像推送/拉取到/从注册表。使用镜像,containerd为容器生成OCI捆绑包。

containerd管理容器生命周期:启动、停止、暂停或删除它。它还管理镜像分发:将镜像推送/拉取到/从注册表。

那么使用containerd实际上能得到什么呢? 您获得推送和拉取功能以及镜像管理。您获得容器生命周期API来创建、执行和管理容器及其任务。一个专门用于快照管理的完整API。基本上,您需要构建容器平台的一切,而无需处理底层操作系统细节。 更多信息见Docker containerd integration

containerd-shim

containerd-shim允许您拥有无守护进程的容器。这是如何实现的:

  • containerd为每个新容器分叉一个runc实例

  • runc进程在容器创建后退出

  • 一旦容器由runc创建,containerd-shim就成为容器进程的新父进程

您可以通过创建docker容器并检查进程来看到这一点。

$ docker run -d alpine sleep 30
$ ps fxa | grep dockerd -A 3  
2239 ?        Ssl    0:28 /usr/bin/dockerd -H fd://
2397 ?        Ssl    0:19  \_ docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock ...
15476 ?        Sl     0:00      \_ docker-containerd-shim 3de8... /var/run/docker/libcontainerd/3da7.. docker-runc  
15494 ?        Ss     0:00          \_ sleep 30

那里没有使用runc,因为它被containerd-shim替代了。

containerd-shim负责STDIN/STDOUT以及向Docker守护进程报告退出状态。

dockerd

dockerd是一个守护进程和服务器,处理Docker API请求,然后利用containerd功能管理容器的生命周期。

docker CLI

Docker CLI是与Docker服务器dockerd通信的方式之一。您可以使用它运行docker命令,如docker rundocker build

运行容器

running-container
  1. 用户使用docker CLI执行命令:

    docker container run -it --name <NAME> <IMAGE>:<TAG>
  2. Docker客户端向守护进程的API发送POST请求

  3. Docker守护进程接收指令并调用containerd启动新容器

  4. containerd从Docker镜像创建OCI捆绑包

  5. containerd告诉runc使用OCI捆绑包创建容器

  6. runc与操作系统内核接口创建容器

  7. 容器进程作为子进程启动

  8. runc在启动容器后退出

  9. containerd-shim接管子进程并成为其父进程

  10. 容器正在运行!

参考资料

最后更新于