Docker 笔记(一)

前言

我对于docker一直有断断续续的使用,但仅限于用 docker hub 寻找漏洞环境,简单的拉取和使用,搭起来博客之后,想来多少应该写点什么,正好在学校“坐牢”的日子里有云计算的大佬玩 k8s 引起一些兴趣,同时有重头系统的学习一些知识的打算,便决定从 docker 的使用开始,顺便搭几个靶场环境,方便学习。

最重要的是做一些简单的摘抄和记录,以供后面翻阅参考,摆脱之前东一榔头西一棒槌的学习模式。接下来记录的内容中有关 Docker 的,主要是 Docker-从入门到实践 的内容,外加其他一些博客等,此外感谢给予指导的大佬们的支持。

Docker 的简单介绍

Docker 是一个开源的应用容器引擎,基于 Go语言开发,使用Linux内核相关技术,对进程进行分装隔离,属于操作系统层面的虚拟化技术,应用了沙箱的机制,相互之间没有任何接口。

Docker 的三个基本概念

镜像(Image)

Docker 镜像是一个特殊的文件系统包含一些为运行准备的配置参数,但不包含任何动态数据,其内容在构建之后也不会被改变。

镜像的多层特性

严格来说,Docker 镜像并不是 ISO 那样的打包文件,而只是一个虚拟的概念,是由一组文件系统在多层上联合组成。Docker 镜像在构建时会一层层构建,前一层是后一层的基础。每一层构建完成后就不会再改变,哪怕是对上一层进行删改,也仅仅只是在当前层进行标记。

也就是说每一层在确定构建完全之前,一定要确认只包含了必要的东西。

镜像的体积

docker 镜像的体积,在仓库中一般显示的是压缩后的大小,而拉取到本地后检视的则是展开的大小。值得注意的是,由于 Docker 镜像是多层存储结构,并可以继承、复用,因此不同镜像可以使用相同的基础镜像,这样一来显示镜像占用的硬盘大小的总和一般比实际要小的多。

要想列出已经下载下来的镜像,可以使用 docker image ls 命令。列表包含了仓库名、标签、镜像 ID、创建时间以及所占用的空间。

运行命令出现镜像仓库名和标签均为 <none> 的情况,这是虚悬镜像 (dangling image) ,可以使用 docker image ls -f dangling=true 来查看,一般这种镜像是因为,官方对镜像进行了维护,镜像名被转移到新的镜像去了,可以使用命令 docker image prune 删除。

中间层镜像

中间层镜像可以加速构建重复利用资源,命令 docker image ls 默认只会显示顶层镜像,如果希望显示可以加 -a 参数。使用后可以看到许多无标签的镜像,但与虚悬镜像不同,不可以随意删除,因为中间层镜像是别的镜像的依赖,同时相同的层在 Docker 中只会保存一遍,对空间占用影响不大。

删除镜像时的两个行为

删除本地的镜像,使用 docker image rm 命令,Docker 镜像的删除行为分两类:

  • Untagged 取消标签
  • Deleted 删除镜像

前面我们知道了,镜像是分层的,而且中间层可以被多个镜像使用。所以在进行删除行为时,会先从上层向基础层依次取消每层的标签,并判断取消后没有其他标签后才会执行删除。也就是说并非所有的 docker image rm 都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。

除镜像的依赖之外,还要注意有没有容器对要删除的镜像有依赖,毕竟容器是以镜像为基础,再加一层容器存储层去运行的。

镜像的构成与定制

Dockerfile 文件

Dockerfile 文件中包含一条条指令,文件用来构建镜像,每一条构建一层。

通过 FROM 指定一个基础镜像,并且必须是第一条指令,有一个特殊镜像 scratch ,这个镜像是虚拟的概念,表示空白。

通过 RUN 来执行命令,有 shell 格式 RUN <命令> 和 exec 格式 RUN ["可执行文件", "参数1", "参数2"] 这种更像是函数调用的格式。值得注意的是,执行命令每一条就代表构建一层镜像,构建命令时可可以用 && 来串联起多条语句,同时最后一定要进行清理无关文件等操作。

1
2
3
4
5
#FROM 指定基础镜像
FROM debian:stretch
#RUN 执行命令
RUN apt-get update \
    && apt-get purge -y --auto-remove $buildDeps
commit 与 build 构建命令

命令 docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] 用来生成黑箱镜像,也就是将容器的存储层保存下来成为镜像,但这种方法只适用于入侵后保存现场等特殊情况,因为他不像使用 Dockerfile 文件进行构建,容器内执行过什么命令进行过什么操作没有直观记录,而且容器内的修改调试,有大量重复臃肿的内容,通过 commit 构建之后,不仅大小会大很多,而且因为具体操作不清晰,对后期的维护十分不便。

命令 docker build [选项] <上下文路径/URL/-> 可以使用 Dockerfile 文件来构建镜像, 最后的上下文路径要注意,为相对路径,一般来说,把需要构建入镜像的文件放到 Dockerfile 所在目录,用 . 表示为当前目录。docker build 还支持从 URL 构建,比如通过 Git repo、压缩包等。

容器(Container)

在 Docker 中,镜像与容器的关系,镜像是静态的定义,容器是镜像运行时的实体。容器的实质是进程,这里有一个新的名词“命名空间”。在容器进程运行时属于自己的独立的命名空间。

命名空间是Linux内核的一项功能,可以对内核资源进行分区,以便一组进程看到一组资源,而另一组进程看到另一组资源。

同样的,容器也是分层存储的,在运行时,以镜像为基础层,在其上创建容器存储层。容器存储层的生存周期和容器一样,容器消亡时也随之消亡。最好来说,容器存储层要保持无状态化,也就是不写入任何数据。所有的文件操作,都应该使用数据卷或绑定宿主目录,在这些位置操作会跳过容器存储层。

数据卷 (Volume) 的生存周期独立于容器,容器消亡,数据卷不会消亡。

容器的启动-运行-终止

仓库(Repository)

Docker Registry 是一个集中存储、分发镜像的服务。一个 Docker Registry 中可以包含多个仓库 (Repository);每个仓库有多个标签 (Tag);每个标签对应一个镜像。通过格式 <仓库名>:<标签> 来指定具体这个软件的那个版本的镜像。latest 为默认标签。

有官方和第三方提供的免费或者收费相关服务,也可以通过 Docker 官方提供的镜像,在本地搭建私有 Docker Registry。

Docker 官方 Registry 公开服务 Docker hub

使用 Docker 镜像

0%