概述
这篇文章讲述一些 Dockerfile的 应用知识和建议。Dockerfile 中应该包含构建一个完整镜像需要的操作步骤。
Docker 会读取Dockerfile 的内容,然后自动构建镜像。如果你想了解更详细的内容,你可以阅读官网内容:
https://docs.docker.com/engine/reference/builder/。当然,你可以阅读我自己整理的内容,我将会分享相
关的链接。
注意:由于本人的词汇量有限,部分单词无法完成翻译,可能会直接保留英文。
第一个 Dockerfile
# syntax=docker/dockerfile:1
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
我们来解读一下 每一行的内容:
#syntax=docker/dockerfile:1
这一行定义一个 解析器语法, 这个定义 和 BuildKit 特性一起使用;
一般情况下,以 # 开始的行,Docker都会认为是注释行。
FROM ubuntu:18.04
Dockerfile第一个实际有效的操作,从 DockerHub 仓库寻找 ubuntu 版本为18.04的镜像,下载这个镜像,以这个镜像作为基础镜像进行构建。
官网给出说明,Dockerfile 第一个有效的构建指令必须是 FROM。
你可以指定下载镜像的远程仓库
- FROM nexus3.system.cn.alibb:8087/com/alibb/group/itid/es/dc/ubuntu/ubuntu:18.04
COPY ./app
从主机目录 ./app 拷贝所有内容 到 镜像 WORKDIR 中;
一般的使用方法是 COPY <src> <dest>;
- <src> : 本地机器的目录,它可以是一个绝对路径、具体文件名、WORKDIR相对路径;
<dest>: 是指容器内部的目录,它可以是一个绝对路径,具体的文件名、也可以相对于 WORKDIR 的相对路径;
例子:
COPY /home/etc/ /home/etc/
COPY /home/etc/passwd /home/etc/passed
COPY …/src/resource/ src/resource 从当前目录的上级目录的 src/resource 拷贝所有内容 到 WORKDIR 目录下的 src/resource 目录中
更多详细的内容,可以阅读一下我整理关于 COPY 操作指引的内容:
RUN make /app
在镜像中执行命令 make /app。RUN 可以执行命令,该命令的生成的结果会立刻在镜像中生效。
CMD python /app/app.py
为正在构建的容器程序设置 容器启动命令。当我们使用 docker run 启动容器的时候,容器就会执行 这个命令。
当你运行一个 image 和 生成一个 container 时,你增加了新的 container layer在最上层。所有改变制定一个运行的 container,例如:创建一个新文件,修改已经存在的文件,和 删除文件,都被写入这个容器层。
关于更多 image layer的内容,请看看:
https://docs.docker.com/storage/storagedriver/
一般使用指南和建议
创建一个 快速容器
我们建议创建一个能在一分钟完成 stop destroy then rebuild and replace 的容易。
理解构建环境
当你运行 docker build 命令时,当前工作目录被称作构建条件(build context)。默认情况下,Dockerfile 被认为存放在当前目录下,但是你可以指定一个不同的位置使用标识 -f 。不管Dockerfile实际在什么位置,所有在当前目录下的文件和子目录内容都被发送到 Docker daemon ,这些内容将作为构建条件(build context)。
Build context example
创建一个目录,使用 cd 命令进入该目录。在目录下创建一个名称为 hello 的 text 文件,并往文件中写入"Hello World"。创建一个 Dockerfile ,在Dockerfile 中定义容器执行cat 命令。构建环境为当前目录。参考下面的指令:mkdir myproject && cd myproject echo "hello" > hello echo -e "FROM busybox\nCOPY /hello /\nRUN cat /hello" > Dockerfile docker build -t helloapp:v1 .
移动 Dockerfile 和 hello ,让他们存放在不同的目录。构建一个第二版本的镜像。使用 -f 标识 指定构建Dockerfile 和 构建环境:
mkdir -p dockerfiles context mv Dockerfile dockerfiles && mv hello context docker build --no-cache -t helloapp:v2 -f dockerfiles/Dockerfile context
我们只希望包含一些必要的文件、库文件、配置文件在构建条件中(build context),其他不重要的内容尽量不放到构建条件中。这样可以提高构建镜像的效率,减小拉取、推送、初始化容器的时间。来看一看你的构建环境的大小,寻找一些跟下面类似的信息在构建的时候:
Sending build context to Docker daemon 187.8MB
Pipe Dockerfile through stdin (标准输入传输Dockerfile)
Docker 提供了一种方案,不需要写一个Dockerfile 文件,也能够使用Dockerfile 的特性来构建docker 镜像。这样的一种构建方式是通过标准输入(stdin) 传输 Dockerfile 的文件内容。在一些简单的一次性构建工作中,使用这种方式工作比较方便。
下面两个例子是等效的:
echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -
docker build -<<EOF FROM busybox RUN echo "hello world" EOF
构建一个镜像使用 来自标准输入的 Dockerfile 信息,不需要发送构建条件信息
使用这个方法来构建镜像,不需要发送当前目录下的文件作为构建条件。连接符(-)获取位置路径,和指引Docker从标准输入获取构建条件,而不是读取当前目录。
docker build [OPTIONS] -
接下来的例子构建一个镜像,使用标准输入传输的Dockerfile 信息。没有文件作为构建条件发送给 docker daemon。docker build -t myimage:latest -<<EOF FROM busybox RUN echo "hello world" EOF
忽略构建条件是非常有用的,如果你不需要拷贝任何文件到镜像中,提高了构建速度,因为没有文件需要发送到 docker daemon。
如果你想提高构建速度,部分不必要的文件不发送到 docker daemon,可以考虑使用 .dockerignore 功能。
注意:使用这个方法构建镜像,如果构建指令包含 COPY 或者 ADD,构建会失败。下面的例子说明这个问题:
# create a directory to work in mkdir example cd example # create an example file touch