带你了解docker是什么----基础原理篇(一)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

docker

容器是如何工作的?

docker的架构

docker的核心组件如下

  • docker的客户端client。我们最常用的客户端就是docker命令。
  • docker服务器docker daemon 一Linux后台服务的方式运行。运行在docker host 上负责创建、运行、监控容器构建、存储镜像。默认下智能响应本地host的客户端的请求。
  • docker镜像image
  • registry
  • docker容器container

组件之间的联系如下图
在这里插入图片描述

docker采用的是client/server的架构。客户端向服务器发送请求服务器负责构建、运行和分发容器。
客户端和服务器可以运行在同一个host上。我们电脑中一般使用的就是这种情况当然客户端也可以通过socket与远程的服务器通信。

docker 镜像

常用命令

  • docker images 查看镜像的信息
  • docker run -it dockerID 运行指定ID的docker 镜像
  • build 从 dockerfile 构建镜像
  • tag给镜像打tag
  • pull 从registry下载镜像
  • push将镜像上传到registry
  • rmi删除docker host 中的镜像
  • search 搜索docker hub 中的镜像
  • images显示镜像列表
  • history显示镜像构建历史
  • commit 从容器创建新镜像

base 镜像

base镜像含义为1不依赖其他镜像从scratch构建2其他镜像可以在该镜像基础上进行扩展。
通常情况下能称为base镜像的是各种Linux发行版的docker镜像如Ubuntu、centOS等

一般基础镜像会与我们实际的大小有所出入。比如一个centOS才200MB左右当时平时我们按照一个centOS至少都有几个G。原因如下

  1. Linux操作系统大致是由内核空间和用户空间组成。如下图在这里插入图片描述
  2. 内核指的是一个提供设备驱动、文件系统、进程管理、网络通信等功能的系统软件但一个内核并不是一套完整的操作系统它只是操作系统的核心。一些组织或厂商将Linux内核与各种软件和文档包装起来并提供系统安装界面和系统配置、设定与管理工具就构成了Linux的发行版本
  3. 内核空间是kernelLinux刚启动时会加载bootfs文件系统之后bootfs会被卸载掉。用户空间的文件系统是rootfs包含我们熟悉的 /dev 、 /proc、/bin等目录。如下图在这里插入图片描述
  4. 对于base镜像来说底层直接使用host的kernel自己只需要提供rootfs就可以了。所以这也就解释了按照docker的时候对于Windows操作系统需要安装一下一个Linux的一个发行版。而对于一个精简的OSrootfs可以很小只需要包括最基本的命令、工具和程序就可以了。
  5. 不同Linux发行版的区别主要就是rootfs因此docker可以同时支持多种Linux镜像。同时这也从侧面反映了主流的Linux发行版的内核是兼容的。什么说呢比如我们在docker中有多个不同发行版的Linux但是host中只有Ubuntu 的一个内核那么其实这些在docker中的Linux镜像使用的都是这个host中的内核。

镜像的分层结构

docker支持通过扩展现有镜像创建新的镜像。
下图为一个具体的例子
在这里插入图片描述

  1. 首先这么做的一个好处就是共享资源。 比如有多个镜像都从相同的base镜像构建而来的那么docker host 只需要在磁盘上保存一份base镜像同时内存中也需要加载一份base镜像就可以为所有容器服务了。而且镜像的每一层都可以被共享。
  2. 多个容器共享一份基础镜像那么在修改的时候就需要进行一些技巧在docker中使用的就是创建一个容器层。 所有对容器的改动无论添加、删除还是修改文件都只会发生在容器层中。只有容器层是可写的容器层下面的所有镜像都是只读的。

构建镜像

对于Docker用户来说最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等都有现成的Docker官方镜像或其他人和组织创建的镜像我们只需要稍作配置就可以直接使用。
当然有的情况下我们还是需要自己来创建镜像的。docker提供了两种创建镜像的方法①docker commit 命令命令行方式②使用dockerfile 构建文件。一般使用的是后者因此这篇介绍的是后者。

dockerfile

dockerfile 是一个文本文件记录了镜像创建的所有步骤。

下面列举例子来说明使用dockerfile来创建镜像的一些细节
一个dockerfile文件中的内容如下
在这里插入图片描述
运行docker build 命令构建镜像

root@ubuntu:~# pwd ①
​​​​/root
​​​​root@ubuntu:~# ls ②
​​​​Dockerfile
​​​​root@ubuntu:~# docker build -t ubuntu-with-vi-dockerfile . ③
​​​​Sending build context to Docker daemon 32.26 kB ④
​​​​Step 1 : FROM ubuntu ⑤
​​​​---> f753707788c5
​​​​Step 2 : RUN apt-get update && apt-get install -y vim ⑥
​​​​---> Running in 9f4d4166f7e3 ⑦
​​​​......
​​​​Setting up vim (2:7.4.1689-3ubuntu1.1) ...
​​​​---> 35ca89798937 ⑧
​​​​Removing intermediate container 9f4d4166f7e3 ⑨
​​​​Successfully built 35ca89798937 ⑩
​​​​root@ubuntu:~#​​
  1. 当前目录为 /root。
  2. Dockerfile准备就绪。
  3. 运行docker build命令-t将新镜像命名为ubuntu-with-vi-dockerfile命令末尾的.指明build context为当前目录。Docker默认会从build context中查找Dockerfile文件我们也可以通过-f参数指定Dockerfile的位置。
  4. 从这步开始就是镜像真正的构建过程。首先Docker将build context中的所有文件发送给Docker daemon。build context为镜像构建提供所需要的文件或目录。
    Dockerfile中的ADD、COPY等命令可以将build context中的文件添加到镜像。此例中build context为当前目录 /root该目录下的所有文件和子目录都会被发送给Docker daemon。
    所以使用build context就得小心了不要将多余文件放到build context特别不要把 /、/usr作为build context否则构建过程会相当缓慢甚至失败。也即是说我们创建指定镜像的时候指定的目录有正确
  5. Step 1执行FROM将Ubuntu作为base镜像。
    Ubuntu镜像ID为f753707788c5。
  6. Step 2执行RUN安装vim具体步骤为 ⑦ ⑧ ⑨。
  7. 启动ID为9f4d4166f7e3的临时容器在容器中通过apt-get安装vim。
  8. 安装成功后将容器保存为镜像。底层类似docker commit 命令
  9. 删除临时容器。
    10.镜像构建成功。

镜像的缓存特性

docker 会缓存已有镜像的镜像层构建新镜像时候如果某镜像层已经存在就直接使用无需重新创建。

dockerfile 中每一个指令都会依赖一个镜像层上层是依赖于下层的。无论什么时候只要某一层发生变化其上面所有层的缓存都会失效。 简单来说看下面的两个文件内容都是一眼的就是指令的顺序有所不同。
在这里插入图片描述

在这里插入图片描述
对于第一个dockerfile文件在创建的时候由于前面两行命令得到的镜像与之前创建的相同因此就会使用缓存中的镜像。而对于第二个就需要重新下载了。因此有时候指令的顺序也是我们考虑的一个要点

dockerfile 构建镜像过程

  1. 从base镜像运行一个容器。
  2. 执行一条指令对容器做修改。
  3. 执行类似docker commit的操作生成一个新的镜像层。
  4. Docker再基于刚刚提交的镜像运行一个新容器。
  5. 重复2~4步直到Dockerfile中的所有指令执行完毕。

从这个过程可以看出如果Dockerfile由于某种原因执行到某个指令失败了我们也将能够得到前一个指令成功执行构建出的镜像这对调试Dockerfile非常有帮助。我们可以运行最新的这个镜像定位指令失败的原因。

如下边的一个调试例子
dockerfile中的内容如下
在这里插入图片描述
执行docker build 后结果如下

在这里插入图片描述
Dockerfile在执行第三步RUN指令时失败。我们可以利用第二步创建的镜像22d31cc52b3e进行调试方法是通过docker run -it启动镜像的一个容器如图3-31所示。
在这里插入图片描述
手工执行RUN指令很容易定位失败的原因是busybox镜像中没有bash。虽然这是个极其简单的例子但它很好地展示了调试Dockerfile的方法。

dockerfile 常用指令

  1. form : 指定base镜像
  2. copy 将文件 从build context 复制到镜像。支持两种格式copy src dest 与copy [“srt”,“dest”] .src 只能指定build context 中的文件或目录
  3. add 与copy 类似从build context 复制文件到镜像。不同的是如果src是归档文件tar、zip文件会自动解压到dest
  4. env 设置环境变量
  5. volume : 将文件或目录声明为volume。
  6. workdir 为后面的run 、 cmp 、add或copy 指令设置镜像中的当前工作目录
  7. run 在容器中运行指定的命令
  8. cmd 容器启动时运行指定的命令 可以有多个cmd指令但是只要最后一个生效。
  9. maintainer : 设置镜像的作者

下面以一个较为详细地使用 dockerfile 文件来创建镜像来详细说明各个命令的作用
在这里插入图片描述
构建镜像细节如下图

在这里插入图片描述

  1. 构建前确保build context中存在需要的文件。
  2. 依次执行Dockerfile指令完成构建。其中下一行显示将相关的文件传输到服务器

运行容器验证镜像内容如图所示。
在这里插入图片描述

① 进入容器当前目录即为WORKDIR。
如果WORKDIR不存在Docker会自动为我们创建。
② WORKDIR中保存了我们希望的文件和目录
目录bunch由ADD指令从build context复制的归档文件bunch.tar.gz已经自动解压。这就像我们智能解压压缩包一样得到的是一个压缩包名字的文件夹
文件tmpfile1由RUN指令创建。
文件tmpfile2由COPY指令从build context复制。
③ ENV指令定义的环境变量已经生效。

dockerfile 支持以“#”开头的注释

RUN 、CMD和ENTRYPOINT

RUN、CMD和ENTRYPOINT这三个Dockerfile指令看上去很类似很容易混淆。这里就详细讨论它们的区别。
简单地说
1RUN执行命令并创建新的镜像层RUN经常用于安装软件包。
2CMD设置容器启动后默认执行的命令及其参数但CMD能够被docker run后面跟的命令行参数替换。
3ENTRYPOINT配置容器启动时运行的命令。

一、 RUN

RUN指令通常用于安装应用和软件包。

RUN在当前镜像的顶部执行命令并创建新的镜像层。dockerfile 中常常包含多个RUN指令

下面为使用RUN安装多个包的例子

RUN apt-get update && apt-get install-y\bzr\cvs\git\mercurial\
​​​​subversion​​

apt-get update 和apt-get install 被放在一个RUN指令中执行这样能够保证每次安装的是最新的包。如果apt-get install 在单独的RUN中执行则会使用apt-get update 创建镜像层而这一层可能是很久之前缓存的了。

二、 CMD

CMD 指令允许用户指定容器的默认执行命令。

此命令会在容器启动且docker run 没有指定其他命令时运行。

  • 如果docker run 指定了其他命令cmd 指定的默认命令将被忽略。
  • 如果有多个CMD指令则只有最后一个有效。

shell 和Excel 格式

我们可以用两种方式指定RUN、CMD和ENTRYPOINT要运行的命令。

一、Shell 格式<instruction><command>
例如

RUN apt-get install python3
​​​​CMD echo "Hello world"
​​​​ENTRYPOINT echo "Hello world"​​

当指令执行时shell格式底层会调用 /bin/sh -c [command]

二、Excel 格式<instruction> ["executable", "param1", "param2", ...]​​
例如

​​​​RUN ["apt-get", "install", "python3"]
​​​​CMD ["/bin/echo", "Hello world"]
​​​​ENTRYPOINT ["/bin/echo", "Hello world"]​​

当指令执行时会直接调用 [command]不会被shell解析。

CMD和ENTRYPOINT推荐使用Excel格式因为这样指令可读性更强。RUN则两种方式都可以。

分发镜像

分发镜像指的是如何在多个docker host 上使用镜像。

有以下几种可用的方法

  1. 用相同的dockerfile 在其他host 构建镜像。
  2. 将镜像上传到公共registryhost 直接下载使用。
  3. 搭建私有的registry供本地host 使用。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Docker

“带你了解docker是什么----基础原理篇(一)” 的相关文章