通过前文的讲解对 Docker 有了基本认识之后, 我们开始进入实战操作, 本文先演示 Docker 三要素之镜像原理和相关命令.
本文的演示环境仍然沿用上一篇文章在本地 Centos7 中安装的环境, 如果你本地没有搭建 Docker 环境, 也可以直接使用前文提到的 Docker 练习场 (play-with-docker) 在线进行练习.
在正式开始之前, 我们先回顾下几个常用的命令, 尤其是 Docker 帮助命令是掌握众多命令的万能钥匙, 一定要多用.
一, Docker 帮助命令
1.1 查看 Docker 版本命令
查看 Doceker 版本信息可以使用 docker version 命令或 - v 参数(--version), 其中 - v 参数是 --version 的缩写.
- docker -v
- [root@docker ~]# docker -v
- Docker version 19.03.6, build 369ce74a3c
- docker --version
- [root@docker ~]# docker --version
- Docker version 19.03.6, build 369ce74a3c
- docker version
- [root@docker ~]# docker version
- Client: Docker Engine - Community
- Version: 19.03.6
- API version: 1.40
- Go version: go1.12.16
- Git commit: 369ce74a3c
- Built: Thu Feb 13 01:29:29 2020
- OS/Arch: Linux/amd64
- Experimental: false
- Server: Docker Engine - Community
- Engine:
- Version: 19.03.6
- API version: 1.40 (minimum version 1.12)
- Go version: go1.12.16
- Git commit: 369ce74a3c
- Built: Thu Feb 13 01:28:07 2020
- OS/Arch: Linux/amd64
- Experimental: false
- containerd:
- Version: 1.2.10
- GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339
- runc:
- Version: 1.0.0-rc8+dev
- GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
- docker-init:
- Version: 0.18.0
- GitCommit: fec3683
1.2 查看 Docker 详细信息命令
我们还可以使用 docker info 命令查看 docker 相关的更广泛的操作系统范围内的信息
- docker info
- [root@docker ~]# docker info
- Client:
- Debug Mode: false
- Server:
- Containers: 1
- Running: 0
- Paused: 0
- Stopped: 1
- Images: 1
- Server Version: 19.03.6
- Storage Driver: devicemapper
- Pool Name: docker-253:1-1912367-pool
... 省略部分内容
Docker Root Dir: /var/lib/docker
... 省略部分内容
[root@docker ~]#
显示内容太多了, 我省略了一部分, 其中可以查看容器总数, 有多少容器在运行, 有多少容器已经停止, 镜像总数以及内存, 容量等信息.
1.3 万能帮助命令
命令何其多, 不一定能全记住, 也没必要全记住. 就像可以在 Linux 下可以通过 man 命令查看各个命令的用法一样, Docker 也提供了帮助命令.
- docker --help
- [root@docker ~]# docker --help
- Usage: docker [OPTIONS] COMMAND
... 省略
里边包含了每个命令的各种详细用法, 根据需要查询即可.
二, Docker 镜像原理
前文已提到 Docker 三要素: 镜像, 容器, 仓库. 镜像是最基础的, 就像我们在做面向对象编程开发时写的实体类, 只有有了类才能生成实例对象. 接下来我们分析下镜像的原理和特点.
2.1 Docker 镜像原理及 UnionFS
2.1.1 Docker 镜像是什么
我们搞技术不像搞数据公式, 要明确给事物一个非常严苛的名称. 对于一门技术的命名或定义, 个人认为只要理解就好, 至于名称你可以任意给他取.
我给 Docker 的定义是一个轻量级可运行的独立软件包, 只不过这个软件包除了包含我们自己开发的业务代码软件之外, 还包含了运行该软件所需的所有环境, 也就是他包含了代码, 运行时环境, 库, 配置文件等等软件运行所需的所有内容.
2.1.2 Docker 镜像原理
Docker 镜像本质就是一个文件, 底层依赖于联合文件系统(UnionFS).
什么是 UnionFS?
UnionFS 是一种分层, 轻量级, 高性能的文件系统, 支持对文件系统的修改作为一次提交来层层叠加. 这很类似于我们生活中的千层饼或鸡蛋, 由蛋黄, 蛋清, 蛋壳一层一层的最终构成了一个鸡蛋.
UnionFS 的特性
联合文件系统最大特点就是分层和联合加载.
在加载时可以一次同时加载多层文件系统, 通过联合加载把各层文件系统叠加起来, 从外部看只能看到一个文件系统, 最终的文件系统保护所有底层的文件和目录.
Docker 镜像分层结构及加载原理
由于 docker 镜像底层采用联合文件系统, 自然而然 docker 镜像也是分层的. docker 采用的联合文件系统为 aufs (advanced multi layered unification filesystem), 是一种可堆叠的联合文件系统.
按照 docker 官网的说法, docker 文件系统分为两层: bootfs 和 rootfs.
bootfs 层
bootfs 包含了 bootloader 和 Linux 内核, 用户是不能对这层作任何修改的, 在内核启动之后, bootfs 实际上会 unmount 掉.
rootfs 则包含了一般系统上的常见目录结构, 类似于 / dev, /proc, /bin 等等以及一些基本的文件和命令.
rootfs 层
对于 Linux 上不同版本的问题, docker 可以同时运行多个 rootfs.
Docker 的文件系统是分层的, 它的 rootfs 在 mount 之后会转为只读模式, Docker 在它上面添加一个新的文件系统, 来达成它的只读. 由于共享一个内核, 这也是为什么 docker 比虚拟机消耗资源更少的根本原因.
images 层
从下图中, 我们能看到多个只读的文件系统, Docker 中把他们称为层. image 是只读的, container 部分则是可写的. 如果用户想要修改底层只读层上的文件, 这个文件就会被先拷贝到上层, 修改后驻留在上层, 并屏蔽原有的下层文件.
container 层
最后一部分是容器(container), 容器是可读写的.
在系统启动时, Docker 会首先一层一层的加载 image, 直到最先面的 base image, 这些 image 都是只读的. 最后, 在最上层添加可读写的一个容器, 这里存放着诸如 unique id, 网络配置之类的信息.
既然是可读写的, 就会有状态. 容器共有两种状态: running 和 exited. 用户也可以用 docker commit 命令将一个容器压制为 image, 供后续使用.
docker 镜像为什么要分层
docker 镜像采用基于联合文件系统的分层结构主要是为了共享公用文件, 除了节约存储空间, 还能实现对文件的高效管理.
镜像可以通过分层来进行继承, 基于父镜像可以制作各种具体的应用镜像. 如果你有面向对象编程语言的开发经验, 这就很好理解, 它类似于继承与多态, 子类可以继承父类功能并能派上新功能.
关于镜像的分层, 在使用后续的 docker pull 命令时可以很好的进行验证. 比如使用 docker pull 命令下载一个 MySQL 镜像, 将会看到是一层一层的下载. 另外如果不同镜像包含相同的公用部分(层), 假设之前已经下载过包含了公用层的镜像的话, 再下载包含公用层的其他镜像, 会提示这些公用层已经存在于本地了, 这个镜像的下载过程就不在去下载公用层, 整个过程就会明显快很多.
2.2 Docker 镜像的特点
由于 docekr 镜像采用了联合文件系统, 因此也继承了联合文件系统过的特点.
总结起来就是: 分层, 只读, 可继承, 如前所述, 镜像是一层一层叠加起来, 并且是只读的, 子镜像可以继承父镜像并派生出新的镜像.
镜像是只读的, 但是当我们基于镜像创建容器是希望能进行读写操作, 那是怎么做到的呢?
当一个 docker 容器启动时, 一个新的可写层被加载到镜像顶部, 这一层称为 "容器层", 容器层下边是 "镜像层", 我们读写操作都是在容器层进行, 我们的程序也是运行在这一层的.
2.3 Docker 架构图
我们之前已经执行了一些命令, 这些命令的执行流程是怎么样的呢? 先要搞清楚 Docker 的架构以及命令执行过程, 我们才能更好的使用 docker.
Docker 架构图
从官方的架构图中可以看到主要包含几个部分: 客户端 Client,Docker daemon, 仓库 Registry.
我们输入命令的工具称之为客户端 Client, 当我们在客户端输入命令时, 命令会发送到 docker 所在主机的 daemon 进程, 由该进程执行命令. 当执行的是创建容器的命令时, 如果对应的镜像不存在于本地, 那么 daemon 会向远程 docker 仓库请求下载镜像, 等镜像下载到本地后在创建容器.
下图包含了 docker 的镜像, 容器, 仓库相关的命令, 接下来主要演示与镜像相关的命令, 其他的命令将在后续的文章中继续演示.
docker 命令图
ps: 这部分内容比较抽象, 可以先大概了解, 经过后边的学习之后再返回来看就会有更深刻的理解.
三, Docker 镜像常用命令
3.1 查看本地镜像
命令格式:
docker images [选项] [仓库: 版本]
参数:
参数 | 作用 |
---|---|
-a | 即 --all,查看所有本地镜像(默认情况不显示中间镜像) |
-q | 只显示镜像 id |
--digests | 显示摘要 |
--no-trunc | 不截断输出(默认显示的镜像 id 为 12 位) |
可以使用 docker images --help 或 man docker images 查看具体的用法和各项参数的意义, 并且支持 tab 补全命令.
案例:
- [root@docker ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- hello-world latest fce289e99eb9 14 months ago 1.84kB
- [root@docker ~]# docker images -q
- fce289e99eb9
输出标题中各项的含义:
REPOSITORY: 镜像名称, 用于标识镜像
TAG: 版本号
IMAGE ID : 镜像 ID, 与镜像名称一样, 可以唯一标识一个镜像
CREATED : 镜像创建日期
SIZE: 镜像大小
3.2 查看远程仓库中的镜像
命令格式:
docker search [选项] 镜像名称
参数:
参数 | 作用 |
---|---|
-f 或 --filter | 根据指定条件过滤 |
--limit | 限制最多返回的条数 |
--no-trunc | 不截断输出 |
案例:
(1)查询点赞数大于等于 5000 的 MySQL 镜像
- [root@docker ~]# docker search -f=stars=5000 MySQL
- NAME DESCRIPTION STARS OFFICIAL AUTOMATED
- MySQL MySQL is a widely used, open-source relation... 9164 [OK]
- [root@docker ~]#
你可以先自行执行 docker search 命令, 什么参数都不加, 然后对比一下结果. 本例中是在 Docker Hub 上查找 stars 星级数大于等于 5 千的 MySQL 的镜像.
(2)只查看官网的 MySQL 镜像
- [root@docker ~]# docker search -f=is-official=true MySQL
- NAME DESCRIPTION STARS OFFICIAL AUTOMATED
- MySQL MySQL is a widely used, open-source relation... 9164 [OK]
- mariadb MariaDB is a community-developed fork of MyS... 3263 [OK]
- [root@docker ~]#
3.3 下载镜像
命令格式:
docker pull [选项] 镜像名称[:TAG]
案例:
下载刚查出的 MySQL 官方镜像
- [root@docker ~]# docker pull MySQL
- Using default tag: latest
- latest: Pulling from library/MySQL
- 6d28e14ab8c8: Pull complete
- dda15103a86a: Pull complete
- 55971d75ab8c: Pull complete
- f1d4ea32020b: Pull complete
- 61420072af91: Pull complete
- 05c10e6ccca5: Pull complete
- 7e0306b13322: Pull complete
- 900b113c001e: Pull complete
- 06cd07c30bf4: Pull complete
- df0d65aee5aa: Pull complete
- 53eeb6e0335c: Pull complete
- 6cf8f9563e97: Pull complete
- Digest: sha256:f91e704ffa9f19b9a267d9321550a0772a1b64902226d739d3527fd6edbe3dfe
- Status: Downloaded newer image for MySQL:latest
- docker.io/library/MySQL:latest
- [root@docker ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- MySQL latest c8ad2be69a22 47 hours ago 465MB
- [root@docker ~]#
另外这里也可以很清楚的看到, 是一层一层的进行下载, 这就是前面讲到的镜像分层结构.
默认会去 Docker Hub 仓库进行下载, 我们也可以直接登录 Docker Hub 查看 MySQL 镜像
https://hub.docker.com/_/mysql?tab=tags 我们可以看到有很多不同的版本, 使用时按需下载即可.
特别注意, 如果没指定 tab 版本号, 默认是 latest 版本, 也就是最新版. 所以在生产环境中最好是明确指定一个版本.
默认情况下去 docker hub 下载镜像比较慢, 由于是在国外所以不太稳定, 自己可以配置为国内的镜像仓库, 如阿里云仓库.
下载完成后, 就可以在本地通过 docker images 命令查到该镜像
3.4 删除本地镜像
命令格式:
docker rmi [选项] 镜像名或 id
参数:
参数 | 作用 |
---|---|
-f | 即为 --force,强制删除镜像。当要删除的镜像有容器存在时,只能强制删除 |
案例:
(1)删除第一篇文章中下载的 hello-world 镜像
由于当时我们已经用该镜像创建了一个容器, 即使此容器没有运行, 在删除时也用 - f 参数强制删除.
- [root@docker ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- hello-world latest fce289e99eb9 14 months ago 1.84kB
- [root@docker ~]# docker rmi hello-world
- Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container cf1753d712db is using its referenced image fce289e99eb9
- [root@docker ~]# docker rmi -f hello-world
- Untagged: hello-world:latest
- Untagged: hello-world@sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752
- Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
- [root@docker ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- [root@docker ~]#
另外如果同一个镜像有不同版本, 需要添加 tag 参数来删除指定镜像. 如果要删除多个镜像, 只需要在命令末尾以空格分隔多个容器即可.
(2)删除全部镜像
[root@docker ~]# docker rmi -f $(docker images -qa)
可以结合 Linux 命令获取所有镜像 id, 然后再全部删除.
3.5 将容器打包为镜像
命令: docker commit
可以通过该命令将当前运行的容器打包为镜像. 后文会讲到构建镜像有两种方式: 一种是通过容器 commit; 另外一种是通过编写 DocekerFile 编辑镜像.
什么场景需要将容器打包成镜像呢?
比如我们想扩展某个镜像的功能, 我们可以把镜像运行为一个容器, 然后在里边实现各种定制化需求(比如安装特定的软件), 然后在重新 commit 提交为一个镜像, 以后就基于新镜像去创建容器.
ps: 在后边演示完容器相关命令后, 在单独演示 commit 和 push 命令. 如果你有 Git 或 SVN 的使用经验, 这 2 个 pull 和 push 命令很好理解, 都是和仓库进行交互.
3.6 将容器上传到远程仓库
命令: docker push
本地通过 docker commit 打包的镜像, 可以通过 docker push 上传到远程 Docker Hub 仓库. 这个命令与 docker pull 是相对的, pull 则是从远程仓库下载到本地.
要上传到远程仓库, 还需要在 Docker Hub 上注册相应的账号, 这在后续的文章中会单独进行演示.
至此, 我们大概弄明白了 Docker 的体系结构以及 Docker 镜像原理, 并演示了大部分 Docker 镜像相关的命令, 如果看完还有些迷茫, 先不着急, 有个大概的印象即可, 等看完后续文章中容器的操作之后就会有更深刻的认识.
下一篇 文章我们将讲解 Docker 容器相关知识, 敬请期待.
如果觉得文章不错, 关注一波不迷路!
来源: https://www.cnblogs.com/heimatengyun/p/12695854.html