Docker 多阶段构建的原理及构建过程展示

Docker多阶段构建是一个优秀的技术,可以显著减少 Docker 镜像的大小,从而加快镜像的构建速度,并减少镜像的传输时间和存储空间。本文将详细介绍 Docker 多阶段构建的原理、用途以及示例。

Docker 多阶段构建的原理

在传统的 Docker 镜像构建中,我们通常需要在 Dockerfile 中指定多个步骤,每个步骤都需要添加一些新的层到镜像中。这样做的问题是,每个层都会添加额外的文件和元数据到镜像中,因此镜像的大小会变得非常大。当需要传输这些镜像到其他地方时,这会消耗大量的时间和网络带宽。

为了解决这个问题,Docker 多阶段构建提供了一种方法来构建一个 Docker 镜像,该镜像只包含必要的文件和元数据,而不包含多余的信息。具体来说,Docker 多阶段构建允许您在同一个 Dockerfile 中定义多个阶段,每个阶段可以独立地构建、测试和优化。在每个阶段结束时,只需将必要的文件和元数据复制到下一个阶段,并舍弃上一个阶段中的多余信息。这样,您就可以在不增加镜像大小的情况下构建出一个可靠的 Docker 镜像。

Docker 多阶段构建的用途

Docker 多阶段构建的主要用途是减少 Docker 镜像的大小。由于每个阶段只包含必要的文件和元数据,所以您可以显著减少 Docker 镜像的大小,并加快构建速度。此外,Docker 多阶段构建还提供了一种简单的方法来构建、测试和优化多个应用程序,因为每个阶段都可以使用不同的环境和工具。

Docker 多阶段构建的示例

下面是一个使用 Docker 多阶段构建构建 Nginx应用程序的示例。该示例分为两个阶段:第一个阶段使用 Alpine 官方镜像来构建应用程序,第二个阶段使用 Alpine镜像 +Nginx运行时文件来运行应用程序。

首先拉取一个alpline镜像,并查看镜像的大小,可以看到只有7M

bash 复制代码
[root@server159 ~]# docker pull alpine
[root@server159 ~]# docker images
REPOSITORY       TAG       IMAGE ID       CREATED        SIZE
centos7-python   v1        e6a497c56c1c   16 hours ago   526MB
php-fpm          v1        0474bd7488fa   39 hours ago   698MB
debian           latest    676aedd4776f   3 weeks ago    117MB
alpine           latest    8ca4688f4f35   4 weeks ago    7.34MB
centos           7         eeb6ee3f44bd   2 years ago    204MB
nginx            1.18.0    c2c45d506085   2 years ago    133MB

随便创建一个空目录,最好是空的不要有其它文件

然后编写一个Dockerfile文件

复制代码
[root@server159 alpine]# ls
Dockerfile 
bash 复制代码
[root@server159 alpine]# cat Dockerfile 
FROM     alpine:latest as relay_nginx
RUN      sed  -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'  /etc/apk/repositories  && \
         apk add --no-cache  gcc libgcc libc-dev zlib-dev pcre-dev wget make openssl-dev && \

         wget -c http://nginx.org/download/nginx-1.22.0.tar.gz && \
         tar xf nginx-1.22.0.tar.gz && \
         cd nginx-1.22.0 && \
         ./configure --prefix=/usr/local/nginx  --with-http_ssl_module --with-http_auth_request_module --with-http_random_index_module && \
        make && make install && \
        rm -rf  /usr/local/nginx/conf/*.default && \
        cd ../ && \
        rm -rf nginx-1.22.0* /var/cache/apk/*
 
ADD     ./index.html  /usr/share/nginx/html/index.html
EXPOSE 80
EXPOSE 443

ENTRYPOINT ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

然后构建镜像

bash 复制代码
[root@server159 alpine]# docker build --no-cache -t nginx:alpine-1.0 .

构建完以后查看我们的镜像,可以看到大小为172M

bash 复制代码
[root@server159 alpine]# docker images
REPOSITORY       TAG          IMAGE ID       CREATED          SIZE
nginx            alpine-1.0   e096be22d040   34 seconds ago   172MB
centos7-python   v1           e6a497c56c1c   16 hours ago     526MB
php-fpm          v1           0474bd7488fa   39 hours ago     698MB
debian           latest       676aedd4776f   3 weeks ago      117MB
alpine           latest       8ca4688f4f35   4 weeks ago      7.34MB
centos           7            eeb6ee3f44bd   2 years ago      204MB
nginx            1.18.0       c2c45d506085   2 years ago      133MB

构建一个容器查看效果

bash 复制代码
[root@server159 alpine]# docker run --name nginx-alpine-1.0 -d  -p8080:80 nginx:alpine-1.0 
21fa466986ab11cfac2c8c23b4772e8c2213d83e2ffc414c289420756106d1ed

去浏览器访问

可以看到容器是正常运行的

然后我们再编写Dockerfile文件,多加一层镜像的构建

bash 复制代码
[root@server159 alpine]# cat Dockerfile 
FROM     alpine:latest as relay_nginx
RUN      sed  -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'  /etc/apk/repositories  && \
         apk add --no-cache  gcc libgcc libc-dev zlib-dev pcre-dev wget make openssl-dev && \

         wget -c http://nginx.org/download/nginx-1.22.0.tar.gz && \
         tar xf nginx-1.22.0.tar.gz && \
         cd nginx-1.22.0 && \
         ./configure --prefix=/usr/local/nginx  --with-http_ssl_module --with-http_auth_request_module --with-http_random_index_module && \
        make && make install && \
        rm -rf  /usr/local/nginx/conf/*.default && \
        cd ../ && \
        rm -rf nginx-1.22.0* /var/cache/apk/*
 
FROM    alpine:latest as alpine_nginx
RUN     sed  -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g'  /etc/apk/repositories && \
        apk add --no-cache  zlib-dev pcre-dev openssl-dev && \
        rm -rf /var/cache/apk/*

COPY --from=relay_nginx /usr/local/nginx /usr/local/nginx
EXPOSE 80
EXPOSE 443

ENTRYPOINT ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

编写完毕以后我们构建一个2.0版本的镜像

bash 复制代码
[root@server159 alpine]# docker build --no-cache -t nginx:alpine-2.0 .

产看镜像

bash 复制代码
[root@server159 alpine]# docker images
REPOSITORY       TAG          IMAGE ID       CREATED          SIZE
nginx            alpine-2.0   11c2c53e9585   10 seconds ago   24.1MB
nginx            alpine-1.0   603a2f2545fe   6 minutes ago    172MB
centos7-python   v1           e6a497c56c1c   16 hours ago     526MB
php-fpm          v1           0474bd7488fa   39 hours ago     698MB
debian           latest       676aedd4776f   3 weeks ago      117MB
alpine           latest       8ca4688f4f35   4 weeks ago      7.34MB
centos           7            eeb6ee3f44bd   2 years ago      204MB
nginx            1.18.0       c2c45d506085   2 years ago      133MB

可以惊奇的发现我们2.0的镜像仅仅只有24M,小了好几倍

然后也用2.0的镜像生成一个容器测试一下可用性

bash 复制代码
[root@server159 alpine]# docker run --name nginx-alpine-2.0 -d  -p8081:80 nginx:alpine-2.0 
73e2a462573e3c5298ad6e255a95d214aad58ce498becfcac2fde8799c796d1e

然后去网页访问


说明我们的2.0版本镜像也是可以正常运行的

但是却小了好多,那是因为我们构建了两层的镜像,而底层的镜像会被压缩

所以这就是多层镜像构建的好处,在发布的时候可以大大缩减镜像的大小

在这个基础上再定制我们自己想要的镜像,就是一项很好的优化

相关推荐
少妇的美梦7 小时前
logstash教程
运维
容器魔方7 小时前
Bloomberg 正式加入 Karmada 用户组!
云原生·容器·云计算
chen9457 小时前
k8s集群部署vector日志采集器
运维
chen9458 小时前
aws ec2部署harbor,使用s3存储
运维
muyun280012 小时前
Docker 下部署 Elasticsearch 8 并集成 Kibana 和 IK 分词器
elasticsearch·docker·容器
東雪蓮☆13 小时前
深入理解 LVS-DR 模式与 Keepalived 高可用集群
linux·运维·服务器·lvs
qq_2642208913 小时前
LVS负载均衡群集和LVS+Keepalived群集
运维·负载均衡·lvs
乌萨奇也要立志学C++13 小时前
【Linux】进程概念(二):进程查看与 fork 初探
linux·运维·服务器
雨落Liy13 小时前
Nginx 从入门到进阶:反向代理、负载均衡与高性能实战指南
运维·nginx·负载均衡
Nazi613 小时前
k8s的dashboard
云原生·容器·kubernetes