当前位置:首页 > 技术之家 > docker > 正文内容

Docker系列-docker.sock探究

预备知识

搞清楚/var/run/docker.sock参数的前提是了解docker的client+server架构,如下图
在这里插入图片描述
可见在电脑上运行的docker由client和server组成,我们输入docker version命令实际上是通过客户端将请求发送到同一台电脑上的Doceker Daemon服务,由Docker Daemon返回信息,客户端收到信息后展示在控制台上。

可是这个又跟docker.sock有什么关系呢?别急,我们再了解一下docker一些比较重要的组件

Docker 的主要组件

安装 docker ,其实是安装了 docker 客户端、dockerd 等一系列的组件,其中比较重要的有下面几个。

Docker CLI(docker)
docker 程序是一个客户端工具,用来把用户的请求发送给 docker daemon(dockerd)。

该程序的安装路径为:

/usr/bin/docker

Dockerd
docker daemon(dockerd),一般也会被称为 docker engine。

该程序的安装路径为:

/usr/bin/dockerd

Containerd
在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。

该程序的安装路径为:

/usr/bin/docker-containerd

Containerd-shim
它是 containerd 的组件,是容器的运行时载体,主要是用于剥离 containerd 守护进程与容器进程,引入shim,允许runc 在创建和运行容器之后退出,并将 shim 作为容器的父进程,而不是 containerd 作为父进程,这样做的目的是当 containerd 进程挂掉,由于 shim 还正常运行,因此可以保证容器不受影响。此外,shim 也可以收集和报告容器的退出状态,不需要 containerd 来 wait 容器进程。我们在 docker 宿主机上看到的 shim 也正是代表着一个个通过调用 containerd 启动的 docker 容器。

该程序的安装路径为:

/usr/bin/docker-containerd-shim

RunC
RunC 是一个轻量级的工具,它是用来运行容器的,容器作为 runC 的子进程开启,在不需要运行一个 Docker daemon 的情况下可以嵌入到其他各种系统,也就是说可以不用通过 docker 引擎,直接运行容器。docker是通过Containerd调用 runC 运行容器的

该程序的安装路径为:

/usr/bin/docker-runc

在这里插入图片描述

从 hello world 开始

我们通过hello-world镜像分析来进行:

[vagrant@docker-host docker]$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64) 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/For more examples and ideas, visit:
 https://docs.docker.com/get-started/

上面的输出信息指出,hello-world 容器的运行经历了如下四步:

  1. Docker 客户端向 docker daemon 发送请求

  2. Docker daemon 从 Docker Hub 上拉取镜像

  3. Docker daemon 使用镜像运行了一个容器并产生了输出

  4. Docker daemon 把输出的内容发送给了 docker 客户端

这是一个很抽象也很容器理解的过程,但是我们还想知道更多:docker daemon 是如何创建并运行容器的?
其实容器部分的操作和管理都被 dockerd 外包给 containerd 了,下图描述了运行一个容器时各个组件之间的关系:
在这里插入图片描述

进入正题

Docker Daemon 的连接方式

  1. UNIX 域套接字

    默认就是这种方式, 会生成一个 /var/run/docker.sock 文件, UNIX 域套接字用于本地进程之间的通讯, 这种方式相比于网络套接字效率更高, 但局限性就是只能被本地的客户端访问。

  2. tcp 端口监听

    服务端开启端口监听 dockerd -H IP:PORT , 客户端通过指定IP和端口访问服务端 docker -H IP:PORT 。通过这种方式, 任何人只要知道了你暴露的ip和端口就能随意访问你的docker服务了, 这是一件很危险的事, 因为docker的权限很高, 不法分子可以从这突破取得服务端宿主机的最高权限。

什么是unix socket?

unix socket可以让一个程序通过类似处理一个文件的方式和另一个程序通信,这是一种进程间通信的方式(IPC)。
当你在host上安装并且启动好docker,docker daemon 会自动创建一个socket文件并且保存在/var/run/docker.sock目录下。docker daemon监听着socket中即将到来的链接请求(可以通过-H unix:///var/run/docker.sock设定docker daemon监听的socket文件,-H参数还可以设定监听tcp:port或者其它的unix socket),当一个链接请求到来时,它会使用标准IO来读写数据。

docker.sock 是docker client 和docker daemon 在localhost进行通信的socket文件。
可以直接call这个socket文件来拉去镜像,创建容器,启动容器等一系列操作。(其实就是直接call docker daemon API而不是通过docker client的方式去操控docker daemon)。

官方说明

我们从Docker Daemon进行,查看它的官方文档
在这里插入图片描述

上图是Docker Daemon的配置参数

翻译过来就是:--host=[]指定Docker守护程序将在何处侦听客户端连接。如果未指定,则默认为/var/run/docker.sock

所以docker客户端只要把请求发往这里,daemon就能收到并且做出响应。

按照上面的解释来推理:我们也可以向/var/run/docker.sock发送请求,也能达到docker psdocker images这样的效果;

验证

1.查看镜像:

  • docker-cli方式:

    [vagrant@docker-host ~]$ docker images
    REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
    spring_demo                            latest              b7c0355e0a01        6 days ago          151MB
    nginx                                  latest              f35646e83998        2 weeks ago         133MB
    hello-world                            latest              bf756fb1ae65        9 months ago        13.3kB
    ampregistry:5000/sng-biz-base-alpine   2.1.0               54c2c81fffbe        17 months ago       137MB
  • 请求到Docker Daemon:

    该请求返回的是json串,使用| jq .是为了格式化json,方便查看

    jq是linux里面的一个json格式化工具,如果没有安装可以去掉后面的| jq .代码,拷贝返回的json串手动格式化也可以

    [vagrant@docker-host ~]$ curl -s --unix-socket /var/run/docker.sock http:/images/json | jq .[
      {
        "VirtualSize": 151316494,
        "Size": 151316494,
        "Containers": -1,
        "Created": 1603359433,
        "Id": "sha256:b7c0355e0a01f296e6ac94071b19c227839c8c19fecb2376dd8677ecbbe48017",
        "Labels": null,
        "ParentId": "sha256:4a5e4dd8fb964affb9750f01f66fb5f381988fcdbf8928902ce3f77b14fe990a",
        "RepoDigests": null,
        "RepoTags": [
          "spring_demo:latest"
        ],
        "SharedSize": -1
      },
      {
        "VirtualSize": 132861270,
        "Size": 132861270,
        "Containers": -1,
        "Created": 1602578384,
        "Id": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35",
        "Labels": {
          "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
        },
        "ParentId": "",
        "RepoDigests": [
          "nginx@sha256:ed7f815851b5299f616220a63edac69a4cc200e7f536a56e421988da82e44ed8"
        ],
        "RepoTags": [
          "nginx:latest"
        ],
        "SharedSize": -1
      },
      {
        "VirtualSize": 13336,
        "Size": 13336,
        "Containers": -1,
        "Created": 1578014497,
        "Id": "sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b",
        "Labels": null,
        "ParentId": "",
        "RepoDigests": [
          "hello-world@sha256:8c5aeeb6a5f3ba4883347d3747a7249f491766ca1caa47e5da5dfcf6b9b717c0"
        ],
        "RepoTags": [
          "hello-world:latest"
        ],
        "SharedSize": -1
      }]

2.查看容器:

先运行一个nginx容器:docker run --name mynginx -p 80:80 -d nginx

  • docker-cli方式:

    CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES919b34a22018        nginx               "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   mynginx
  • 请求Docker Daemon:

    [vagrant@docker-host ~]$ curl -s --unix-socket /var/run/docker.sock http:/containers/json | jq .[
      {
        "Mounts": [],
        "Networksettings": {
          "Networks": {
            "bridge": {
              "DriverOpts": null,
              "MacAddress": "02:42:ac:11:00:02",
              "GlobalIPv6PrefixLen": 0,
              "GlobalIPv6Address": "",
              "IPv6Gateway": "",
              "IPAMConfig": null,
              "Links": null,
              "Aliases": null,
              "NetworkID": "89d9f74c2884582696971298095e85c9c7df332a356c4b3a4dc09807eb6d457f",
              "EndpointID": "53d712df1ad9bd9093b8492c1abace5fe72785cd80189aa4c64d7652dff38490",
              "Gateway": "172.17.0.1",
              "IPAddress": "172.17.0.2",
              "IPPrefixLen": 16
            }
          }
        },
        "HostConfig": {
          "NetworkMode": "default"
        },
        "Status": "Up 11 minutes",
        "State": "running",
        "Id": "919b34a2201822a04fb1160c1c2369580d7b9ef9e7f1e9c77ad4da8761649fb9",
        "Names": [
          "/mynginx"
        ],
        "Image": "nginx",
        "ImageID": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35",
        "Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
        "Created": 1603879410,
        "Ports": [
          {
            "Type": "tcp",
            "PublicPort": 80,
            "PrivatePort": 80,
            "IP": "0.0.0.0"
          }
        ],
        "Labels": {
          "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
        }
      }]

如果去看看 Engine API,你会发现其它的请求也都是用类似方式发送的,更多API可以参考官方文档,目前最新的版本是v1.40:https://docs.docker.com/engine/api/v1.40/

至此,我们对docker的client、server架构有了清楚的认识:Docker Daemon相当于一个server,监听来自/var/run/docker.sock的请求,然后做出各种响应,例如返回镜像列表,创建容器。


扫描二维码推送至手机访问。

版权声明:本文章来源于网络,版权归原作者所有,如果本站文章侵犯了您的权益,请联系我们删除,联系邮箱:luxd@aliyun.com,感谢支持理解。


本文链接:https://luxd.cc/post/194.html

“Docker系列-docker.sock探究” 的相关文章

docker从入门到精通,看这一篇就够了

docker从入门到精通,看这一篇就够了

一、Docker简介1、背景物理机时代一个物理机上安装操作系统,然后直接运行我们的软件。也就是说你电脑上直接跑了一个软件,并没有开虚拟机什么的,资源极其浪费。缺点  ·  部署慢  ·  成本高虚拟机都不开,直接上物理机部署应用,那成本能不...

如何将当前在用的centos 7.6系统及数据 转成docker镜像

如何将当前在用的centos 7.6系统及数据 转成docker镜像

将当前正在使用的CentOS 7.6系统及数据转换成Docker镜像的步骤如下:首先,安装Docker。可以通过运行以下命令来安装Docker:sudo yum install docker然后启动Docker服务并设置为在系统启动时自动启动:sudo sys...

Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. Error: open /proc/sel

Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg. Error: open /proc/sel

问题描述:在Centos8系统中,使用docker run时,出现如下报错:Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.Error: open /proc/self/uid_map: no...

DOCKER 第二步 现有 CentOS8 系统打包 Docker 镜像

DOCKER 第二步 现有 CentOS8 系统打包 Docker 镜像

一、现有系统 Centos8.5 操作:系统里最好不安装 Docker,否则会报错卸载不必要软件包ndf remove -y iwl* *firmware* --exclude=kernel-firmware清理yum缓存ndf clean allrm -rf /var/cache/dnf ...

Docker 的 docker file 准备

Docker 的 docker file 准备

1、构建 Dockerfile,以 Ubuntu 20.04 为基础,增加 nginx FROM  ubuntu:20.04 MAINTAINER alan 19082062@qq.comRUN apt-get updateRUN apt-get install -y...

CentOS虚拟机直接将现有的系统环境文件打包成Docker镜像文件

CentOS虚拟机直接将现有的系统环境文件打包成Docker镜像文件

一、现有A系统Centos7操作:备注:A系统里最好不安装Docker,否则会报错卸载不必要软件包yum remove -y iwl* *firmware* --exclude=kernel-firmware1清理yum缓存yum clean allrm -rf /var/cache/yum12打包...