Docker笔记(十一):Dockerfile详解与最佳实践
Dockerfile是一个文本文件,包含了一条条指令,每条指令对应构建一层镜像,Docker基于它来构建一个完整镜像。本文介绍Dockerfile的常用指令及相应的最佳实践建议。
1. 理解构建上下文(build context)
Docker镜像通过docker build
指令构建,该指令执行时当前的工作目录就是docker构建的上下文,即build context,上下文中的文件及目录都会作为构建上下文内容发送给Docker Daemon。
docker build --no-cache -t helloapp:v2 -f dockerfiles/Dockerfile context |
如上 –no-cache 表示镜像构建时不使用缓存,-f 指定Dockerfile文件位置, context 指定build context目录。
将一些非必要的文件包含到build context中,会导致build context过大,从而导致镜像过大,会增加镜像构建、推送及拉取的时间,以及容器运行时的大小。
执行docker build时会显示build context的大小,
Sending build context to Docker daemon 187.8MB |
最佳实践建议
-
使用.dockerignore来排除不需要加入到build context中的文件,类似于.gitignore
-
不要安装不必要的包,所有包含的东西都是镜像必须的,非必须的不要包含。
-
解耦应用,如果应用有分层,解耦应用到多个容器,便于横向扩展,如web应用程序栈包含web服务应用,数据库,缓存等。
-
最少化镜像层数:只有RUN、COPY、ADD指令会创建镜像层,其它指令创建临时的中间镜像,不会增大镜像构建的大小
-
如果可能,尽可能使用多阶段构建,只复制你需要的组件到最终镜像,这使得你可以在中间构建阶段包含工具与debug信息,同时又不会增大最终镜像的大小。
-
排序多行参数:将参数按字母排序,有利于避免包重复,及后续的维护与提高易读性
2. FROM
作用
FROM指定基础镜像,每一个定制镜像,必须以一个现有镜像为基础。因此一个Dockerfile中FROM是必须的指令,并且必须是第一条。使用格式,
FROM <image>:<tag> |
最佳实践建议
-
如果不想以任何镜像为基础,则可以使用
FROM scratch
-
尽量使用官方镜像作为基础镜像
-
推荐使用Alpine镜像,因为它足够轻量级(小于5MB),但麻雀虽小五脏俱全,基本具有Linux的基础功能
3. RUN
作用
用来执行命令行命令,是最常用的指令之一。使用格式,
# shell格式,跟直接在命令行输入命令一行 |
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建指令中指定–no-cache参数,如:docker build --no-cache
最佳实践建议
-
将比较长的复杂的指令通过 \ 分为多行,让Dockerfile文件可读性、可理解性、可维护性更高,将多个指令通过 && 连接,减少镜像的层数
-
确保每一层只添加必需的东西,任何无关的东西都应该清理掉,如所有下载、展开的文件,apt 缓存文件等,以尽可能减少镜像各层的大小
-
将
RUN apt-get update
与RUN apt-get install
组合成一条RUN指令(将apt-get update单独作为一条指令会因为缓存问题导致后续的apt-get install 指令失败)
比如先按如下Dockerfile创建了一个镜像
FROM ubuntu:18.04 |
一段时间后,再按以下Dockerfile创建另一个镜像
|