学习Docker(2017-9-30)

本节学习目录

  • 虚悬镜像
  • 中间层镜像
  • 列出部分镜像
  • 利用 Commit 理解镜像构成
  • 慎用 docker commit

衔接上一篇的内容,继续学习 Docker 的相关知识

虚悬镜像

中间层镜像

列出部分镜像

docker images 会列出所以镜像,当添加多个镜像只好几个参数

以特定格式显示

1
docker images -q 显示所有镜像的id信息

下面的命令会直接列出镜像结果,并且只包含镜像 ID 和仓库名:

1
docker images -format "{{.ID}}:{{.Repository}}"

或者打算以表格等距显示,并且有标题行,和默认一样,不同自己定义列:

1
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"

效果

利用 Commit 理解镜像构成

回顾知识:镜像是多层存储,每一层是前一层的基础上进行的修改;而容器也是多层存储,是在以镜像为基础层,在其基础上加一层作为容器运行时的存储层

我们定制一个 Web 服务器为例子,来讲解镜像是如何构建的。

1
docker run --name webserver -d -p 80:80 nginx

这条命令会用nginx镜像启动一个容器,名称为webserver,并且映射了80端口,如果使用的是 Docker for Windows 直接 通过 loclhost 访问。如果使用的是 Docker Toolbox ,或者是在虚拟机、云服务器上安装的 Docker ,则需要将 loclhost 换位虚拟机地址或者云服务器的地址

出现问题图片

1
2
3
4
5
docker: Error response from daemon: Conflict. The container name "/webserver"
is already in use by container
"9ea8beeb72c9f62b300ce1628f9a1660b37091636c8fc95774a3cb682b8b0819".
You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.

问题:上述命令下载nginx 镜像后,再次报错?
解决:上述出错信息是你不能使用80端口,所以我们修改了端口,解决后的命令如下

1
docker run --name webserver -d -p 81:80 nginx

如果你的机器运行失败,使用docker ps -l查看正在运行的镜像,然后docker kill commit_ID结束并删除docker rm commit_ID,然后在使用上面的命令,成功后返回一个 id

最后通过localhost:81访问

我们可以通过docker exec命令进入容器,修复其内容

1
docker exec -it webserver bash

解释:我们以交互式终端方式进入 webserver 容器,并执行了 bash 命令, 也就是获得一个可以操作的 Shell。

然后,我们用 Hello ,Docker! 内容覆盖/usr/share/nginx/html/index.html的内容

我们修改了容器的文件,也就是改动了容器的储存层。我们可以通过 docker diff 命令看到具体的改动

1
docker diff webserver

现在我们定制好了变化,将其保存下来形成镜像。Docker 提供了一个 docker commit 命令, 可以将容器的存储层保存下来成为镜像。 换句话说,就是在原有镜像的基础上,在叠加容器的存储层,并构成新的镜像

1
docker commit [选项] <容器ID或容器名>[<仓库名>[:<标签>]]
1
2
3
4
5
docker commit \
--author "didiaoyuan <didiaoyuan@gmail.com>" \
--message "修改了默认网页" \
webserver \
nginx:v2

现在我们可以在 docker images 中看到这个修改后的镜像:

1
2
docker images nginx
(注意在生成新nginx:v2的时候注意拼写错误,本人在这上面卡了一会!)

通过docker history查看镜像内的历史变化

1
docker history nginx:v2

然后我们允许新的镜像

1
docker run --name web2 -d -p 82:80 nginx:v2

通过localhost:82访问

慎用 docker commit

大部分引用书上的解释和自己的理解,文书出处与 GitBook《Docker 从入门与实践》

虽然,上面解释 docker commit 可以直观的理解镜像的分层概念,但是实际上不会使用 commit 来生成镜像,而是使用 dockerfile 生成镜像。

原因:

  1. 如果你仔细发现 docker diff webserver 的结果,会发现,除了我们修改的 index.html 文件外还有许多文件被改动了或者添加。如果是安装了软件包、编译构建,那会产生大量的无关内容被添加进来,会导致镜像十分臃肿。
  2. 使用 docker commit 对镜像的操作都是暗箱操作,生成的镜像都是黑箱镜像,因为除了制作人知道怎么生成,别人都不清楚,何况时间久了制作人也不清楚具体的操作,所以这种操作维护起来很难。
  3. 回顾之前的分层储存概念,除当前层外,之前的层是不会发生变化的,就是任何改变结果仅仅是在当前层进行操作(标记、添加、修改..)而不会改动上一层,使用 commit 制作镜像,以及后期修改,每一层都会让镜像更臃肿一次,所删除的上一层的东西不会消失,会一直如影随形的跟着这个镜像,只会让这个镜像更加臃肿。
(*^▽^*)