学习Docker(2017-10-1)

本节学习目录

  1. 使用 Dockerfile 定制镜像
  2. Dockerfile 的使用
  3. 构建镜像
    1. 直接用 Git repo 进行构建
    2. 用给定的 tar 压缩包构建
    3. 从标准输入中读取 Dockerfile 进行构建
    4. 从标准输入中读取上下文压缩包进行构建

继续学习 Docker 相关知识,上节学习了如何列出镜像,以及镜像的理解,关于 commit 生成定制的镜像,最后对 commit 生成镜像的缺点分析。 今天从 Dockerfile 定制镜像开始学习,并完成笔记。

使用 Dockerfile 定制镜像

Dockerfile
Dockerfile 是一个文本文件,其中包含一条条指令(Instrution),每一条指令构建一层,因此每条指令的内容,就是描述该层的应当如何构建。

Dockerfile 的使用

在一个文件夹中创建一个 Dockerfile 的文本,其中写入两条命令

1
2
FROM ngix
RUN echo '<h1>Hello,Docker!</h1>' > /usr/share/ngix/html/index.html

FROM 指定基础镜像

回顾我们上节课的 nginx 镜像,就是一个基础镜像,在此基础做出定制。基础镜像是必须指定的。而 FROM 就是指定基础镜像,每个 Dockerfile 中 FROM 是必备的,而且必须是第一条指令。

知识:在 Docker Hub 上有非常多的高质量的官方镜像

  1. 可以直接拿来使用的 服务器镜像:
    nginx、redis、mongo、mysql、httpd、php、tomcat 等
  2. 方便开发、构建、运行各种 语言应用的镜像:
    node、openjdk、python、ruby、galang 等
  3. 基础的 操作系统镜像:
    ubuntu、debian、centos、fedora、alpine 等
  4. 特殊镜像 scratch ,表示虚拟的概念,并不存在,是一个空白的镜像
    FROM scratch … 表示不以任何镜像为基础,接下来的命令作为镜像第一层开始存在。

    知识:不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如 swarm、coreos/etcd 对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经让镜像体积更加小巧了。因此 FROM scratch 会让镜像体积更加小巧。
    实用 Go 语言开发的应用用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言之一。—来自《Docker 从入门到实践》

RUN 执行命令
RUN 指令是执行命令行的命令。
RUN 指令在定制镜像时是最常见的指令之一。其格式有两种:

  1. shell格式:RUN <命令> ,就像直接在命令行中输入的命令一样。
  2. exec 格式:RUN [“可执行文件”,”参数1”,”参数2”],这更像是函数调用中的格式

问题:既然 RUN 就像 shell 脚本一样可以执行命令,那么我们是否就可以像 shell脚本一样把每个命令对应一个 RUN 呢?

之前说过, Dockerfile 中每一个指令都会建立一层, RUN 也不例外。 每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建一层,然后执行这些命令,commit 这层的修改,构成新的镜像。如果每条指令都是用 RUN 就创建了很多 镜像,所以又出现了上一节的问题,增加了镜像的臃肿程度。

Union FS 是有最大层数限制,比如 AUFS,曾经42层,现在127层

关于 Union FS

解决:仅仅使用一个 RUN 指令,并使用 && 将各个所需要的命令串联起来。

Dockerfile 支持 Shell 类的行尾添加 \ 命令换行,以及行首 # 进行注释格式

理解:阅读上图可能发现最后删除了编译构建所需要的软件,清理了所以下载、展开的文件,并清理了 apt 缓存文件,现在我们可能理解了 commit 和 Dockerfile 的区别,commit 直接生成了我们没有处理干净的镜像,其中包括很多自动生成的东西。利用 Dockerfile 相当一个”一键生成”的功能,把我们所要执行的工作,包括最后清理的工作,全部合成到一起,避免了 commit 忘记每一层构建的时候产生的文件。

构建镜像

回到我们刚才的 nginx 镜像,让我们构建这个镜像

1
2
docker build -t nginx:v3 .
<!-- 格式:docker build [选项] <上下文路径/URL/->-->

遇到的问题

问题1: 输入命名显示格式错误提示!

解决: 后来发现后面需要添加 . 点:表示当前目录

问题2: 未找到 Dockerfile 文件在你的目录

解决:知道了找不到文件,思考了一下可能文件格式不对,书上没说什么格式,我的是txt格式,后来改成 无后缀的ok了

问题3: build 成功后 windows 提示 权限问题

解决:
解决方法

验证:

  1. 启动
  2. 进入验证

镜像构建上下文 (Context)

构建镜像命令后面有个.,表示当前目录,对应命令格式,是上下文路径
,什么是上下文?

Docker build 工作原理
Docker 运行:

  1. Docker 引擎(服务端守护进程)
  2. 客户端工具

Docker 的引擎提供了一组 REST API (Docker Remote API),使用 docker 命令的客户端工具是通过这个 API 与引擎进行交互的。因此,虽然从表面上看我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端完成。这种 C/S设计,让我们轻松的操作远程服务器的 Docker 引擎。

当我们进行构建镜像的时候,并非是在本地构建,而是在服务端,也就是 Docker 引擎中进行。其中使用了上下文概念。

上下文路径的作用:当用户执行 docker build 命令,获取上下文路径,会将这个路径的内容打包上传到 Docker 引擎,引擎展开这个包获得构建镜像所需的一切文件

需要注意的是:我们上传的内容不要在硬盘的根目录,也就是 C,D 盘,这会在执行 docker build 命令后 发送一个 几十 GB 的文件,这是一种错误的做法。正确的做法是创建一个空目录,或者项目目录,把需要的文件复制一份,如果目录下有不想构建的内容,可以用 .gitignore一样的语法创建一个dockerignore

直接用 Git repo 进行构建

docker build 还支持从 URL 构建,比如可以直接从 Git repo 中构建:

用给定的 tar 压缩包构建

1
docker build http://server/context.tar.gz

所给的 URL 不是git repo,而是 tar 压缩包,那么 Docker 引擎会下载这个包,自动解压,以其作为上下文,开始构建。

从标准输入中读取 Dockerfile 进行构建

1
dockerfile -< Dockerfile

如果标准输入传入的是文本文件,则将其视为 Dockerfile ,并开始构建。

这种形式读取内容,没有上下文,因此不可以将本地文件 COPY 进镜像之类的事情

从标准输入中读取上下文压缩包进行构建

1
docker build -< context.tar.gz

如果发现标准输入的文件格式是 gzip、bzip2 以及 xz 的话,将会使其上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。

(*^▽^*)