Docker—基础(2)

77 阅读11分钟

docker引擎的发展

docker首发架构由两大核心组件构成:LXC(Linux Container)与 Docker Daemon。

  • 首发架构的两大问题:
    • 严重依赖于 LXC,出现了“卡脖子”问题,及无法实现 Docker 跨平台。所以在 0.9 版本使用了 Docker 自研的 Libcontainer 替换了 LXC。
    • Docker Daemon 中的“大而全”使得版本更新难、性能出现瓶颈、不符合软件哲学(由Unix 团队提出),关键是,其还存在着“中心化”问题。所以在 1.1 版本中其实现了 OCI规范,将容器运行时 Runc 从 Docker Daemon 中剥离了出来。

Docker 引擎架构

  • Docker Client:用户提交 Docker 命令
  • Dockerd:负责 REST API、处理镜像相关命令、网络、容器编排等。
  • Containerd:负责容器生命周期管理(负责处理容器相关的命令),但不负责创建容器。

当 docker run 命令到来时会 fork 出 Runc 与 Shim 两个进程。

  • Runc:负责创建容器进程,容器创建并启动完毕后,Runc 将容器进程交付给 Shim 进程管理,然后自己退出。
  • Shim:负责将容器与 Docker Daemon 进行解耦。

docker安装

安装文档地址:docs.docker.com/engine/inst…

image.png

  • x86_64/amd64:传统的架构指的是冯诺依曼架构,台式机一般都是指的这个架构。
  • arm64/aarch64:移动设备和小型家电或设备上所使用的架构,这种架构现在发展比较快,aarch64现在叫armv8,现在一般提到arm基本上指的就是armv8。
  1. 安装yum-utils 中提供了 yum-config-manager 工具,用于完成配置管理
[root@dawn share]# yum install yum-utils -y
  1. 添加docker-ce下载仓库

    • 官网给出的是一个国外地址仓库: image.png

    • 从国外服务器上下载 Docker 安装包非常慢,可以从国内服务器上下载。可以使用“docker 的阿里云镜像地址”,然后将原来命令中的国外地址替换为这个阿里云地址即可。mirrors.aliyun.com/docker-ce/l…

      [root@dawn share]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
      
  2. 安装docker-ce

    • 安装最新版本
    sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
    • 安装指定版本 image.png
  3. Docker启停

    docker以服务的形式运行在系统中,可使用systemctl对其操作

    启动docker

    systemctl start docker
    

    重启Docker

    systemctl restart docker
    

    查看Docker运行状态

    systemctl status docker
    

    设置Docker开机自启动

    systemctl enable docker
    

    关闭Docker开机自启动

    systemctl disable docker
    

之后 停止Docker

systemctl stop docker

查看是启动成功

docker version查看docker client和server的信息 image.png

  1. docker 引擎的卸载
    • 移除docker安装的组件 image.png
    • 删除/var/lib 下的 docker 与 containerd 两个目录。这两个目录中存放着镜像、容器、数据卷,它们在前面删除时不能被自动删除,需要手动删除。 image.png
    • 手动删除一些自己编辑、定义的配置文件

配置国内加速器

运行hello-world镜像,首次运行时会下载hello-world镜像,如果命令执行失败可能是由于网络导致的超时,此时需要配置国内加速器。

国内镜像中心常用的为阿里云与网易云。在本地Docker中指定要使用的国内加速器地址后,就可以直接从国内镜像中心下载镜像了。

  1. 配置阿里云加速器

若要配置阿里云加速器,必须要有阿里云的账号。登录阿里云后,打开阿里云的容器镜像服务页面 cr.console.aliyun.com 并按照配置页面执行相关命令。

image.png

  1. 配置网易云加速器

    配置网易云加速器,无需注册网易云用户。只需将前面的daemon.json文件中的那个URL替换成如下的URL即可。

    {
        "registry-mirrors":["http://hub-mirror.c.163.com"]
    }
    

    替换完成后,仍需要重新加载服务配置文件,重启Docker引擎。

配置完加速器后再次运行 docker run hello-world

Docker镜像

镜像是一种轻量级、可执行的独立软件包,也可以说是一个精简的操作系统。镜像中包含应用软件及应用软件的运行环境。具体来说镜像包含运行某个软件所需的所有内容,包括代码、库、环境变量和配置文件等。几乎所有应用,直接打包为 Docker 镜像后就可以运行。由于镜像的运行时是容器,容器的设计初衷就是快速和小巧,所以镜像通常都比较小,镜像中不包含内核,其共享宿主机的内核;镜像中只包含简单的 Shell,或没有 Shell。

  • 镜像中心

    镜像中心默认使用的都是 Docker 官方的 Docker Hub。不过,镜像中心是可配置的,可以使用指定的第三方镜像中心。对于第三方镜像中心中的仓库名称<repository>由三部分构成:<domain-name>/<username>/<software-name>。其中的<domain-name>指的是第三方镜像中心的域名或 IP。

  • 镜像定位

    对于任何镜像,都可通过<repository>:<tag>进行唯一定位。其中<tag>一般称为镜像的版本号。<tag>中有一个比较特殊的版本latest。如果不指定,默认<tag>即为 latest。不过,虽然其字面意思是最新版,一般其也的确存放的是最新版,但并不能保证其真的就是最新版。

  • 镜像的分类

    镜像中心中存储着大量的镜像仓库 Image Repository,每个镜像仓库中包含着大量相关镜像。根据这些镜像发布者的不同,形成了四类不同的镜像仓库。

    image.png

    1. Docker Official Image

      Docker 官方镜像仓库。该类仓库中的镜像由 Docker 官方构建发布,代码质量较高且安全,有较完善的文档。该类仓库中的镜像会及时更新。一般常用的系统、工具软件、中间件都有相应的官方镜像仓库。例如,Zookeeper、Redis、Nginx 等。官方镜像仓库的名称<repository>一般直接为该类软件的名称<software-name>

    2. Verified Publisher

      已验证发布者仓库。该类仓库中的镜像由非 Docker 官方的第三方发布。但该第三方是由 Docker 公司审核认证过的,一般为大型企业、团体或组织。审核通过后,Docker 公司会向其颁发“VERIFIED PUBLISHER”标识。这种仓库中镜像的质量还是有保证的。除了官方镜像仓库,其它都是非官方镜像仓库。非官方镜像仓库名称<repository>一般由发布者用户名与软件名称两部分构成,形式为:<username>/<software-name>

    3. Sponsored OSS

      由 Docker 公司赞助开发的镜像仓库。该类仓库中的镜像也由非 Docker 官方的第三方发布,但该镜像的开发是由 Docker 公司赞助的。该类型的第三方一般为个人、团队或组织。这种仓库中镜像的质量也是有保证的。

    4. 无认证发布

      没有以上任何标识的仓库。这种仓库中镜像的质量良莠不齐,质量上无法保证,在使用时需谨慎。

镜像的常用命令

docker pull

docker pull 可将指定的镜像从 docker hub 拉取到本地。如果没有指定镜像则会抛出一个 Error

  1. 通过<repository>:<tag>拉取,<tag>可不写默认为latest。docker pull -q nginx 加上-q在拉取镜像的时候会简化输出 image.png

  2. 通过digest 拉取,docker pull <repository>@<digest>

    image.png

    digest,镜像内容散列Content Hash,是镜像内容的一个Hash值。只要镜像内容发生了变更,其内容散列值就一定会发生改变。注意,digest 是包含前面的 sha256 的,表示该 digest 的产生所采用的 Hash 算法是 SHA256。 image.png

docker images

  1. 通过 docker images 命令可查看本地所有镜像资源信息。这些镜像会按照镜像被创建的时间由近及远排序。

    image.png

    • REPOSITORY:镜像仓库名称
    • TAG:镜像版本号
    • IMAGE ID:镜像的唯一标识
    • CREATE:镜像的创建时间
    • SIZE:镜像大小
  2. 查看指定镜像docker images mysql

    image.png

  3. 查看完整的镜像ID,默认显示的镜像id是截取后的前12位,使用--no-trunc可显示的是完整的镜像id

    image.png

  4. 查看镜像的digest docker images --digests

    image.png

  5. 仅显示镜像ID docker images -q

    image.png

  6. 过滤镜像 -f 选项可以过滤指定的镜像

    docker images -f dangling=true

    dangling=true 用于过滤出悬虚镜像,即没有 Repository 与 Tag 的镜像。对于悬虚镜像的REPOSITORY 与 TAG,显示的是<none>

    docker images -f before=hello-world

    • -f before 用于列举出本地镜像中指定镜像创建时间之前创建的所有镜像
    • -f since 用于列举出本地镜像中指定镜像创建时间之后的创建的所有镜像
    • -f reference 用于列举出<repository>:<tag>与指定表达式相匹配的所有镜像。 image.png
  7. 格式化显示

    该选项用于格式化输出 docker images 的内容,格式需要使用 GO 模板指定 image.png

docker search

docker search 可从 docker hub 上查看指定名称的镜像。

  • --filter is-offical=true 过滤出官方的镜像
  • --limit=4 显示4条

image.png

以上检索方式与从 docker hub 官网 hub.docker.com 查看是一样的,但没有官网查看的直观。

docker rmi

rmi,remove images。用于删除指定的本地镜像。

  • docker rmi <repository>:<tag>:如果省略要删除镜像的 tag,默认删除的是 lastest 版本。
  • docker rmi ImageID:通过ImageId指定要删除的镜像
  • docker rmi -f redis:已经运行容器对应的镜像默认是不能删除的,必须要先停止并删除了相关容器后才能删除其对应的镜像。而 -f 选项可以强制删除。
  • docker rmi -f $(docker images -q):使用组合命令删除所有镜像。如果不加-f 选项,则不会删除已打开容器的镜像。

image.png

导入导出(save/load)镜像

在本地生成一个镜像,想将其导出后在另一电脑上使用,则可通过导出/导入镜像。

  1. 导出镜像save

    docker save命令将一个或者多个镜像导出为一个tar文件

    docker save -o /root/docker/dawn-images-pkg.tar redis:latest nginx:latest

  2. 导入镜像load

    docker load 用于将一个 tar文件导为镜像

    docker load -i /root/docker/dawn-images-pkg.tar

image.png

镜像的分层

Docker 镜像由一些松耦合的只读镜像层组成,Docker Daemon 负责堆叠这些镜像层,并将它们关联为一个统一的整体,即对外表现出的是一个独立的对象。通过 docker pull 命令拉取指定的镜像时,每个 Pull complete 结尾的行就代表下载完毕了一个镜像层。

image.png 例如,下面的 nginx:latest 镜像就包含 6 个镜像层。

image.png

  • 每个分层都是只读的,所有对分层的修改都是以新分层的形式出现,并不会破坏原分层内容;
  • 每个分层只记录变更内容,可节省存储空间
  • 不同镜像间实现资源共享,即不同镜像对相同下层镜像的复用。对于 docker pull 命令,其在拉取之前会先获取到其要拉取镜像的所有 ImageID,然后在本地查找是否存在这些分层。如果存在,则不再进行拉取,而是共享本地的该分层。这样就大大的节省了存储空间与网络带宽,提升了拉取效率。

镜像的构成

每个镜像层由两部分构成:镜像文件系统与镜像 json 文件。这两部分具有相同的 ImageID。

  • 镜像文件系统:对镜像占有的磁盘空间进行管理的文件系统,拥有该镜像所有镜像层的数据内容
  • 镜像json文件:用于描述镜像的相关属性的集合,通过 docker inspect [镜像]就可以直观看到
  1. 镜像FS的构成

    一个 docker 镜像的文件系统 FS 由多层只读的镜像层组成,每层都完成了特定的功能。而这些只读镜像层根据其位置与功能的不同可分为两类:基础镜像层与扩展镜像层。

    image.png

    • 基础镜像层:所有镜像的最下层都具有一个可以看得到的基础镜像层 Base Image,基础镜像层的文件系统称为根文件系统 rootfs。而 rootfs 则是建立在 Linux 系统中“看不到的”引导文件系统bootfs 之上
    • 扩展镜像层:是在基础镜像层之上的镜像层也是对基础镜像层功能的扩展。在 Dockerfile 中,每条指令都是用于完成某项特定功能的,而每条指令都会生成一个扩展镜像层。
    • 容器层:运行镜像就会形成容器,而容器是一个运行中的Linux系统是具有文件系统的。容器的这个文件系统是在docker镜像最外层之上增加了一个可读写的容器层,对文件的任何更改都只存在于容器层。因此任何对容器的操作都不会影响到镜像本身。如果容器层需要修改某个文件,系统会从容器层开始向下一层层的查找该文件直至找到。任何对于文件的操作都会记录在容器层。如果要修改某文件,容器层会首先把从镜像层找到的文件copy到容器层后再进行修改。删除文件也只会将存在于容器层中的文件副本删除。 可见,Docker容器就是一个叠加后的文件系统,而这个容器层称为 Union File System,联合文件系统。

    image.png

  2. Linunx OS 启动过程 image.png

    • 现代操作系统都是 C/S 模式的微内核架构的,由两大部分构成:内核(Server)与服务模块(Client)。
    • Linux 的 bootfs 文件系统由两部分构成:bootloader 与 kernel。各个容器中的 rootfs 就是由宿主机的 kernel 驱动的。
    • bootloader 主要负责将 kernel 加载到内存,并引导 kernel 启动。当 kernel 启动后,内存的使用权就由 bootfss 完全转交给了 kernel,然后 kernel 就会将 bootfs 卸载。 image.png
  3. 镜像摘要

    • 摘要digest是镜像内容的一个Hash值,即所谓的 Content Hash(内容散列)要是镜像内容发生了变更,其内容散列值就一定会发生改变。也就是说,一个镜像一旦创建完毕,其 digest 就不会发生改变了,因为镜像是只读的。Docker 默认采用的 Hash 算法是SHA256是一个长度为 256 位的Hash二进制值。Docker 使用 16 进制表示,即变为了长度为 64 位的字符串。

    • 摘要的作用

      • 摘要的主要作用是区分相同<repository>:<tag>的不同镜像;假如镜像 server-common:2.8.0 在生产运行过程中发现存在一个 BUG。现对其进行了修复,并使用原标签将其 push 回了仓库,那么原镜像被覆盖。但生产环境中遗留了大量运行中的修复前镜像的容器。此时,通过镜像标签已经无法区分镜像是修复前的还是修复后的了,因为它们的标签是相同的。此时通过查看镜像的 digest 就可以区分出修改前后版本,因为内容发生了变化,digest 一定会变。为了确保再次拉取到的是修复后的镜像,可通过 digest 进行镜像拉取。其用法是:docker pull <repository>@<digest>
    • 分发散列值

      • push 或 pull 镜像时,都会对镜像进行压缩以减少网络带宽和传输时长。但压缩会改变镜像内容,从而导致经过网络传输后的镜像内容与其digest不相符。因此Docker为镜像配置了 Distribution Hash(分发散列值)。在镜像被压缩后立即计算分发散列值,并将此值随压缩过的镜像一同被发送。当接收方接收后,立即计算压缩镜像的分发散列值,再与携带的分发散列值对比。如果相同,则说明传输没有问题。
    • 查看镜像摘要

      • docker pull 镜像结束后会给出该拉取的镜像的摘要digest。
      • docker inspect 命令可以查看指定镜像的详细信息其中包含了镜像的摘要信息。
      • docker images --digests 命令也可以查看到镜像的摘要信息
  4. 自动化镜像

    什么是自动化镜像?就是使用 Docker Hub 连接一个包含 Dockerfile 文件(专门构建镜像用的文件)的 GitHub 仓库或 Bitbucket 仓库的源码托管平台,然后 Docker Hub 就会自动根据 Dockerfile 内容构建镜像。这种构建出的镜像会被标记为 AUTOMATED,这种构建镜像的方式称为 Trusted Build(受信构建)。只要 Dockerfile文件内容发生变化,那么 Docker Hub 就会构建出新的镜像。

多架构镜像

Multi-architecture Image,即多架构镜像,是某<repository>中的某<tag>镜像针对不同操作系统/系统架构的不同镜像实现。即多架构镜像中包含的镜像的<repository>:<tag>都是相同的,但它们针对的操作系统/系统架构是不同的。

  1. 多架构镜像原理

    无论用户使用的是什么操作系统/系统架构,其通过 docker pull 命令拉取到的一定是针对该操作系统/系统架构的镜像,无需用户自己考虑操作系统/系统架构问题。Docker Hub 能够根据提交 pull 请求的 Docker 系统的架构自动选择其对应的镜像。

    image.png

    在 Docker Hub 中,镜像的多架构信息保存在 Manifest 文件中。在拉取镜像时,Docker会随着 pull 命令将当前 Docker 系统的 OS 与架构信息一并提交给 Docker Hub。Docker Hub 首先会根据镜像的<repository>:<tag>查找是否存在 Manifest。如果不存在,则直接查找并返回<repository>:<tag>镜像即可;如果存在,则会在 Manifest 中查找是否存在指定系统/架构的镜像。如果存在该系统/架构,则根据 Manifest 中记录的地址找到该镜像的位置。

Docker 容器

通过 docker run 命令可以启动运行一个容器。该命令在执行时首先会在本地查找指定的镜像,如果找到了,则直接启动,否则会到镜像中心查找。如果镜像中心存在该镜像,则会下载到本地并启动,如果镜像中心也没有,则直接报错。

image.png

启动容器的目的就是启动运行该容器中的应用。容器中的应用运行完毕后,容器就会自动终止。所以,如果不想让容器启动后立即终止运行,则就需要使容器应用不能立即结束。使应用处于与用户交互的状态等待状态

容器的运行模式

docker run 命令用于创建并启动容器,同时其会运行容器中指定的应用。这个指定的应用要么通过 docker run 中的[command]指定,要么通过容器镜像的 Dockerfile 中的 CMD指令指定。对于容器的运行,有两种运行模式:交互模式-it,分离模式-d

  1. 交互模式

    image.png

    • --name :指定容器的名称
    • -it:以交互的方式运行容器,并为容器分配一个伪终端
    • /bin/bash:指定容器启动后需要运行的命令,而该命令会启动一个 bash 终端。
    • root@cd7d70422795:/data# ls:这个就是 docker 生成的伪客户端,而数字 cd7d70422795 表示的是docker 容器的 ID。
  2. 分离模式

    image.png

    • -d 选项表示以分离模式(detached mode)运行容器,即命令在后台运行,命令的运行与宿主机的运行分离开来。

    image.png

    • -p:指定宿主机和容器之间的端口映射关系,无论IPv4 还是IPv6,都可以通过宿主机访问docker容器

    image.png

    • 为何容器已经启动但通过 docker ps 命令却查不到?通过 docker ps –a 命令得知容器不过只是退出。而docker ps 查看的都是 up 状态的容器。

容器相关命令

docker create

仅创建容器但不启动,用法与 docker run 非常相似。但没有-d 选项。 image.png

docker ps

  • docker ps:查看所有正在运行的容器
  • docker ps -a: 查看所有容器包括已经退出的容器。
  • docker ps -aq:查看所有容器ID
  • docker ps -l:查看最后一个容器
  • docker ps -n 3:查看最后创建的指定个数的容器无论容器是否处于运行状态

docker attach/exec

进入容器命令(针对运行中的容器)如果想进入到容器中对容器内部进行一些操作,此时就需要用到 exec/attach 命令了

image.png

  • exec会创建一个新的独立于容器的进程,exit后仅用于结束该新建进程,不会结束容器
  • attach并不会再创建新的进程,而是将标准输入与标准输出直接附着在容器进程之上,一般不使用选项,但需要考虑退出容器方式是使用 exit 还是 ctrl+p+q。

image.png

  • docker exec -it dawn-redis /bin/bash
  • docker exec -it dawn-redis ls /bin

image.png

  • exit:退出并结束当前进程
  • Ctrl+P+Q:退出但不结束当前进程

docker top 容器内进程查看

docker top:查看指定容器正在运行容器进程详情,这个详情包括当前这个进程正在运行的命令。 image.png

docker logs 容器日志查看

docker logs:可以查看指定容器中应用的运行日志,无论该容器是运行还是停止状态。而所查看的日志内容是由docker run 命令的[command]决定(如果没有则由 Dockerfile 中的 CMD指令决定)

image.png

  • 通过添加选项-n 或--tail 可以指定要显示的最后几条日志

    • docker logs -n 5 dawn-rabbitmq
    • docker logs --tail 5 dawn-rabbitmq
  • 查看指定时间内的日志:指定的时间是绝对时间或者相对时间

    • --since 显示指定时间以后的日志。
    • --until 显示指定时间以前的日志。

image.png

  • -t:查看日志的时间戳 image.png
  • -f:查看实时日志
    image.png

容器的启停、暂停、删除

容器可以通过容器名称或容器 ID 指定

  • docker start 启动已经停止的容器
  • docker restart 容器重启
  • docker stop 优雅的停止指定容器,其他进程访问,则等待访问完毕后停止
  • docker kill 强制停止容器,无论是否被其他进程访问,都强制停止
  • docker stop $(docker ps -aq):组合命令优雅停止所有容器
  • docker kill $(docker ps -aq):组合命令优雅停止所有容器
  • docker pause:暂停容器对外提供服务
  • docker unpause:解除容器的暂停服务状态
  • docker rm:删除容器,默认删除的容器必须是已经停止的容器
  • docker rm -f:强制删除容器。无论容器是否停止都会删除 image.png

docker cp

docker cp:容器与宿主机中文件/目录的相互复制,此命令不支持容器间文件的复制 docker cp 本质就是用于完成从一个文件系统复制到另一个文件系统而已,与容器是否运行无关

image.png

提交容器

docker commit:可以将一个容器文件系统的当前快照生成为一个新的镜像。

image.png 打包的centos7:empty镜像是安装了vim、net-tools等的,所以可直接访问ifconfig命令 image.png

生成悬虚镜像

悬虚镜像,即没有<repository><tag>的镜像。悬虚镜像一般都是由于某些失误操作或其它一些操作而生成的副产物,一般是要被清除掉的。如果非要使用悬虚镜像,可通过ImageID来使用了。

生成为一个悬虚镜像,即没有指定<repository>与<tag> image.png

导入、导出容器

  • docker save/load:导出/导入镜像tar文件

  • docker export/import:导出/导入容器tar文件 image.png

  • export 和 save 对比

    • export 作用于容器,save 作用于镜像,但它们导出的结果都为 tar 文件
    • export 一次只能对一个容器进行导出,save 一次可以对多个镜像进行导出
    • export 只是对当前容器的文件系统快照进行导出,其会丢弃原镜像的所有历史记录与元数据信息,save 则是保存了原镜像的完整记录
  • import 和 load 对比

    • import 导入的是容器包,load 加载的是镜像包,但最终都会恢复为镜像
    • import 恢复为的镜像只包含当前镜像一层,load 恢复的镜像与原镜像的分层是完全相同的
    • import 恢复的镜像就是新构建的镜像,与原镜像的 ImageID 不同;load 恢复的镜像与原镜像是同一个镜像,即 ImageID 相同
    • import 可以为导入的镜像指定<repository>与<tag>,load 加载的镜像不能指定<repository>与<tag>,与原镜像的相同
  • 与docker commit的对比

    • 相同点:export、import、commit都会将一个容器变为一个镜像
    • 不同点:export 是对镜像分层合并后视图的文件系统快照的导出,仅包含合并后的一层镜像信息,不包含原镜像的分层历史记录。docker commit 生成的镜像中包含容器的原镜像的所有分层信息。

docker system 命令集

docker system 是一个命令集,其有四个子命令

image.png

  • docker system df

    • docker system df:查看docker各部分的占用情况 image.png

    • docker system df -v:查看更为详细的信息 image.png

  • docker system event

    • docker system events 等价于 docker events,可查看指定日间之内(--since)或之外(--until)在 docker 上所发生的所有事件。这些事件包含运行过的命令有 docker 内部执行的一些操作。 image.png
  • docker system info

    • docker system info 等价于docker info,用于查看当前docker的详情。包括dockerClient与 docker Server 详情。其中 docker server 包含镜像、容器情况,docker 所在系统的软硬件情况等。

    image.png

  • docker system prune

    • docker system prune 命令用于删除 docker 中的无用数据,这些无用数据包含已经停止的容器、没有任何连接容器的网络、悬空镜像,及悬空镜像的构建缓存。 image.png