一、Dockerfile常用指令详解
来自菜鸟教程
指令 | 详解 |
---|---|
FROM | 后续的操作都是基于 FROM 的镜像,相当于指定基础镜像 |
MAINTAINER | 设置镜像作者,例如邮箱等 |
ADD | ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。 |
COPY | 复制指令,从上下文目录中复制文件或者目录到容器里指定路径 |
WORKDIR | 指定工作目录(用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。WORKDIR 指定的工作目录,如果不存在会自动创建。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。) |
ENV | 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量 |
RUN | 执行后面跟着的命令行命令(docker build时执行) |
EXPOSE | 仅仅只是声明端口 |
VOLUME | 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。 |
CMD | 类似于 RUN 指令,用于运行程序(docker run时运行) |
ENTRYPOINT | 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。 |
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
指令使用格式示例:
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make && yum clean all
FROM rhel7 ##多阶段构建,优化镜像
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
- build命令,需要在Dockerfile所在的文件夹中build,-t 命名
docker build -t webserver .
Dockerfile 构建的镜像便于审计。
二、docker 镜像构建( 容器化)
将 Nginx 以 rhel7(无法从网络下载) 为基础镜像容器化。
rhel7 基础镜像大小为140MB
Dockerfile文件所在的文件夹下需要有以下三个文件:
Dockerfile dvd.repo nginx-1.18.0.tar.gz
然后执行下面的Dockerfile构建镜像
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/ #在Dockerfile所在的文件夹中编写rhel7.6yum源
ADD nginx-1.18.0.tar.gz /mnt #将从GitHub上下载的nginx压缩包移动并自动解压到/mnt/下
WORKDIR /mnt/nginx-1.18.0 #切换到nginx目录下
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make && yum clean all #编译安装nginx
FROM rhel7 #多阶段构建,优化镜像
COPY --from=build /usr/local/nginx /usr/local/nginx #将上阶段编译产生的build中的nginx文件夹拷贝到当前使用
EXPOSE 80 #声明80端口
VOLUME ["/usr/local/nginx/html"] #挂载到该目录
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"] #关闭Debug模块
构建镜像大小为144MB
三、镜像的优化
镜像的大小与基础镜像的大小、镜像的层数、构建时的中间产物有关,镜像构建的快慢与网络请求、是否使用构建缓存,是否多阶段构建镜像有关。所以对镜像的优化主要从这六大方面来进行,其中最关键的是基础镜像大小,使用尽量小的基础镜像可以大大提升优化效果。
我们找到了一个更为精简的基础镜像gcr.io/distroless/base-debian10(直接search拉取或GitHub下载),仅仅只有19.2MB,然后将nginx编译之后的二进制程序和库函数拷贝其中。
FROM nginx:1.18.0 as base #拉取官方 nginx:1.18.0
#https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE
#找到需要的库函数,拿到其中用
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /usr/sbin/nginx-debug /opt && \
cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base-debian10
COPY --from=base /opt / #将上一阶段拷贝出来的 /opt 拷贝到此处
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
最后构建出来的nginx镜像只有31.7MB。