Best practices for writing Dockerfiles(来自Docker官方文档)

Best practices for writing Dockerfiles(来自Docker官方文档)

蹩脚的英语看官方文档真累,更新中

这一篇是编写Dockerfile最佳实践的整理,篇幅很长,会逐步不定期更新。如果有什么理解不到位的欢迎指正,喷子请绕道。原文链接

开始就提到Dockerfile遵循特定的格式和指令,这些可以在Dockerfile reference中找到。

原文:
A Docker image consists of read-only layers each of which represents a Dockerfile instruction. The layers are stacked and each one is a delta of the changes from the previous layer.
经过我蹩脚的英语和翻译器理解为:
Docker镜像由只读层组成,每个层代表一个Dockerfile指令。这些层是堆叠的,每一层都是前一层变化的增量。

下面引出了第一个例子:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

每一行的解释:

  • FROM 指明构建的新镜像是来源于哪
  • COPY 拷贝文件或目录到镜像中,示例中是从当前目录拷贝到镜像中
  • RUN 构建镜像时运行的shell命令
  • CMD 启动容器时执行的shell命令

General guidelines and recommendations

Create ephemeral containers

官方给ephemeral做了解释,By “ephemeral”, we mean that the container can be stopped and destroyed, then rebuilt and replaced with an absolute minimum set up and configuration.
意思是,ephemeral(可以理解为短暂的或瞬时性)是指容器可以停止和销毁,然后重建和更换,只需要绝对低的设置和配置就可以了。

Understand build context

理解构建环境

当你发出docker build指令时,当前工作目录被称为build context(构建环境)。默认情况下,Dockerfile被假定位于此,但你可以用-f指定不同的位置。无论Dockerfile实际位于何处,当前目录中的所有文件和目录的所有子内容都将作为构建环境发送到Docker daemon。

示例:

创建myproject并cd进去,向hello文件中写入hello,在当前构建环境创建Dockerfile。

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

构建中包含不必须的文件会使镜像更大。这会增加构建镜像的时间,拉取和推送的时间,以及容器运行时的大小。要查看生成的有多大,在生成Dockerfile时查找一下信息:

Sending build context to Docker daemon  187.8MB

Pipe Dockerfile through stdin

我的理解是通过管道来连接标准输入和Dockerfile

给出了两个例子并说明是等价的。

echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -
docker build -<<EOF
FROM busybox
RUN echo "hello world"
EOF

BUILD AN IMAGE USING A DOCKERFILE FROM STDIN, WITHOUT SENDING BUILD CONTEXT

给出了从标准输入(stdin)创建的语法

docker build [OPTIONS] -

示例:

docker build -t myimage:latest -<<EOF
FROM busybox
RUN echo "hello world"
EOF

官方做出了说明,Omitting the build context can be useful in situations where your Dockerfile does not require files to be copied into the image, and improves the build-speed, as no files are sent to the daemon.
意思是,在Dockerfile不需要将文件复制到镜像中的情况下,省略构建环境是非常有用的,而且可以提高构建速度,因为没有文件被发送到守护进程中。

如果你想通过排除一些文件来提高构建速度,可以参考exclude with .dockerignore

官方接着一个注意事项,COPYADD在这个语法中将会失败。示例:

# create a directory to work in
mkdir example
cd example

# create an example file
touch somefile.txt

docker build -t myimage:latest -<<EOF
FROM busybox
COPY somefile.txt .
RUN cat /somefile.txt
EOF

# observe that the build fails
...
Step 2/3 : COPY somefile.txt .
COPY failed: stat /var/lib/docker/tmp/docker-builder249218248/somefile.txt: no such file or directory

使用以上语法是不能用COPYADD的,下面给出了解决方案。

BUILD FROM A LOCAL BUILD CONTEXT, USING A DOCKERFILE FROM STDIN

语法:

docker build [OPTIONS] -f- PATH

示例:

# create a directory to work in
mkdir example
cd example

# create an example file
touch somefile.txt

# build an image using the current directory as context, and a Dockerfile passed through stdin
docker build -t myimage:latest -f- . <<EOF
FROM busybox
COPY somefile.txt .
RUN cat /somefile.txt
EOF

BUILD FROM A REMOTE BUILD CONTEXT, USING A DOCKERFILE FROM STDIN

这里的关键字是remote

语法跟上面一样:

docker build [OPTIONS] -f- PATH

原文:
This syntax can be useful in situations where you want to build an image from a repository that does not contain a Dockerfile, or if you want to build with a custom Dockerfile, without maintaining your own fork of the repository.
我的理解:
如果从不包含Dockerfile的仓库生成镜像,或者如果要使用自定义Dockerfile生成镜像,而不维护自己的仓库分支,则此语法非常有用。

docker build -t myimage:latest -f- https://github.com/docker-library/hello-world.git <<EOF
FROM busybox
COPY hello.c .
EOF

Exclude with .dockerignore

若要排除与构建无关的文件(不重新构造源仓库),可以使用.dockerignore文件。此文件支持类似于.gitignore文件的排除模式。有关信息可参见.dockerignore

猜你喜欢

转载自blog.csdn.net/sker12424/article/details/105911936