news 2026/9/27 4:16:26

Docker多阶段构建实战:让Nginx镜像从400MB瘦身到200MB,体积砍半!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker多阶段构建实战:让Nginx镜像从400MB瘦身到200MB,体积砍半!

一、实验背景

在上一节实验中,我们基于 CentOS 7 构建了 YUM 版 Nginx 镜像,但镜像体积高达 400MB+。这是因为 CentOS 7 基础镜像本身就包含大量系统工具和库,而容器运行 Nginx 实际上并不需要完整的操作系统环境。

多阶段构建(Multi-Stage Build)是 Docker 17.05 引入的特性,允许在同一个 Dockerfile 中定义多个 FROM 阶段。每个阶段可以有不同的基础镜像,最终只保留最后一个阶段的产物,从而大幅减小镜像体积。

本实验将通过多阶段构建,将 Nginx 镜像从 400MB+ 优化到 50MB 以内。

二、实验环境准备

确保已完成上一节实验,本地存在nginx:yum-v1镜像用于对比:

[root@Docker ~]# docker images i Info → U In Use IMAGE ID DISK USAGE CONTENT SIZE EXTRA 192.168.244.21:5000/test-nginx:1.27.2-alpine 74175cf34632 79.1MB 23.7MB busybox:latest 40680ace50cf 8.82MB 4.5MB U centos:7 e6dba3b9654d 434MB 212MB hello-world:latest 5e2309035332 21.8kB 9.49kB my-busybox:v1 f308fc7938a6 8.83MB 4.5MB mysql:8.0 bb3c7d314bcc 1.62GB 799MB nginx:1.27.2-alpine 74175cf34632 79.1MB 23.7MB nginx:yum-v1 36ed6ee1ba71 527MB 245MB U registry:latest 325b4b29b041 83.4MB 20.4MB U ubuntu:latest da6fc2be5478 158MB 45.3MB [root@Docker ~]#

若无该镜像,可参考上篇文章:Docker镜像构建实战:从零编写Dockerfile,YUM安装搞定Nginx镜像-CSDN博客文章浏览阅读200次,点赞6次,收藏5次。本实验将使用 CentOS 7 作为基础镜像,通过编写 Dockerfile 安装 Nginx 服务,并构建一个可复用的 YUM 版 Nginx 镜像。https://blog.csdn.net/2502_90206768/article/details/166600108?spm=1001.2014.3001.5501

三、实验步骤

3.1 创建项目目录

[root@Docker ~]# mkdir -p /data/nginx-multistage [root@Docker ~]# cd /data/nginx-multistage/ [root@Docker nginx-multistage]#

3.2 编写多阶段 Dockerfile

创建Dockerfile文件,内容如下:

# ==================== 第一阶段:编译阶段 ==================== FROM alpine:3.18 AS builder LABEL stage="builder" LABEL maintainer="admin@example.com" # 1. 安装编译所需的依赖(添加了 musl-dev,并显式包含 gcc) RUN apk add --no-cache \ gcc \ musl-dev \ make \ pcre-dev \ zlib-dev \ openssl-dev \ wget \ coreutils # 下载 Nginx 源码 WORKDIR /usr/local/src RUN wget http://nginx.org/download/nginx-1.24.0.tar.gz && \ tar -zxvf nginx-1.24.0.tar.gz # 编译 Nginx WORKDIR /usr/local/src/nginx-1.24.0 # 2. 在 configure 时显式指定 CC=gcc,强制使用 gcc 编译器 RUN CC=gcc ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --without-http_gzip_module && \ make -j$(nproc) && \ make install # 创建测试首页 RUN echo "Multi-Stage Build Nginx" > /usr/local/nginx/html/index.html # ==================== 第二阶段:运行阶段 ==================== FROM alpine:3.18 AS runner LABEL stage="runner" LABEL maintainer="admin@example.com" LABEL description="Optimized Nginx image with multi-stage build" # 安装 Nginx 运行所需的依赖 RUN apk add --no-cache pcre zlib openssl # 从第一阶段复制编译好的 Nginx COPY --from=builder /usr/local/nginx /usr/local/nginx # 创建软链接 RUN ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx # 创建 nginx 用户 RUN addgroup -S nginx && adduser -S -G nginx nginx WORKDIR /usr/local/nginx EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"]

多阶段构建核心要点:

概念说明
AS builder给第一阶段命名,方便后续引用
AS runner给第二阶段命名
COPY --from=builder从第一阶段复制编译产物到当前阶段
最终镜像只包含最后一个阶段(runner)的内容,builder 阶段的层不会出现在最终镜像中

3.3 构建镜像

[root@Docker nginx-multistage]# docker build -t nginx-ms . [+] Building 74.4s (16/16) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 1.60kB 0.0s => [internal] load metadata for docker.io/library/alpine:3.18 0.8s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => CACHED [builder 1/7] FROM docker.io/library/alpine:3.18@sha256:de0eb0b3f2a47ba1eb89389859a9bd88b28e82f5826b6969ad604979713c2 0.0s => => resolve docker.io/library/alpine:3.18@sha256:de0eb0b3f2a47ba1eb89389859a9bd88b28e82f5826b6969ad604979713c2d4f 0.0s => [builder 2/7] RUN apk add --no-cache gcc musl-dev make pcre-dev zlib-dev openssl-dev wget co 7.4s => [builder 3/7] WORKDIR /usr/local/src 0.0s => [builder 4/7] RUN wget http://nginx.org/download/nginx-1.24.0.tar.gz && tar -zxvf nginx-1.24.0.tar.gz 50.1s => [builder 5/7] WORKDIR /usr/local/src/nginx-1.24.0 0.0s => [builder 6/7] RUN CC=gcc ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_m 15.0s => [builder 7/7] RUN echo "Multi-Stage Build Nginx" > /usr/local/nginx/html/index.html 0.2s => CACHED [runner 2/6] RUN apk add --no-cache pcre zlib openssl 0.0s => [runner 3/6] COPY --from=builder /usr/local/nginx /usr/local/nginx 0.0s => [runner 4/6] RUN ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx 0.3s => [runner 5/6] RUN addgroup -S nginx && adduser -S -G nginx nginx 0.2s => [runner 6/6] WORKDIR /usr/local/nginx 0.0s => exporting to image 0.3s => => exporting layers 0.2s => => exporting manifest sha256:fed9b288991da645cbaab74e5197a53964e58322ad574a19f39bf557739fad91 0.0s => => exporting config sha256:31baf771b19f113247739075a1beb36a5b8b7028a6fc2d05dde237e4d00e8ef1 0.0s => => exporting attestation manifest sha256:a157c56854d0699c3fae6a74911657a1ace90c22a495e88ec166b638efbb144d 0.0s => => exporting manifest list sha256:5cafba155457f198c5cd16e60b65a3e91f90b3f353093e4ffe80506425f8a1ef 0.0s => => naming to docker.io/library/nginx-ms:latest 0.0s => => unpacking to docker.io/library/nginx-ms:latest 0.1s [root@Docker nginx-multistage]#

构建过程中,Docker 会依次执行两个阶段:

  1. builder 阶段:下载源码、编译 Nginx,这一层体积较大(约 500MB+)
  2. runner 阶段:基于 Alpine 拉取最小运行时环境,仅复制编译产物,最终镜像非常精简

构建完成后,查看两个镜像的大小对比:

[root@Docker nginx-multistage]# docker images | grep nginx 192.168.244.21:5000/test-nginx:1.27.2-alpine 74175cf34632 79.1MB 23.7MB nginx-ms:latest 5cafba155457 19MB 5.81MB nginx:1.27.2-alpine 74175cf34632 79.1MB 23.7MB nginx:yum-v1 36ed6ee1ba71 527MB 245MB U [root@Docker nginx-multistage]#

四、实验验证

4.1 启动容器并访问

[root@Docker nginx-multistage]# docker run -d --name nginx-ms -p 8081:80 nginx-ms:latest 975bab2c605a27f853b0166891d02f3ea2bed45b714c30cda9f2381c0598df1b [root@Docker nginx-multistage]# curl http://localhost:8081 Multi-Stage Build Nginx [root@Docker nginx-multistage]#

4.2 进入容器检查环境

[root@Docker nginx-multistage]# docker exec -it nginx-ms /bin/sh /usr/local/nginx # nginx -v nginx version: nginx/1.24.0 /usr/local/nginx # ls /usr/local/nginx/html/ 50x.html index.html /usr/local/nginx # cat /etc/os-release NAME="Alpine Linux" ID=alpine VERSION_ID=3.18.12 PRETTY_NAME="Alpine Linux v3.18" HOME_URL="https://alpinelinux.org/" BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues" /usr/local/nginx # ps aux | grep nginx 1 root 0:00 nginx: master process nginx -g daemon off; 7 nobody 0:00 nginx: worker process 19 root 0:00 grep nginx /usr/local/nginx #

可以看到容器内运行的是极简的 Alpine Linux,没有 gcc、make 等编译工具,也没有 yum 包管理器。

4.3 镜像层历史比对

[root@Docker nginx-multistage]# docker history nginx:multistage-v1 IMAGE CREATED CREATED BY SIZE COMMENT 9d599813d93c About an hour ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0 <missing> About an hour ago EXPOSE [443/tcp 80/tcp] 0B buildkit.dockerfile.v0 <missing> About an hour ago WORKDIR /usr/local/nginx 0B buildkit.dockerfile.v0 <missing> About an hour ago RUN /bin/sh -c addgroup -S nginx && adduser … 24.6kB buildkit.dockerfile.v0 <missing> About an hour ago RUN /bin/sh -c ln -sf /usr/local/nginx/sbin/… 0B buildkit.dockerfile.v0 <missing> About an hour ago COPY /usr/local/nginx /usr/local/nginx # bui… 6.06MB buildkit.dockerfile.v0 <missing> About an hour ago RUN /bin/sh -c apk add --no-cache pcre zlib … 1.2MB buildkit.dockerfile.v0 <missing> About an hour ago LABEL description=Optimized Nginx image with… 0B buildkit.dockerfile.v0 <missing> About an hour ago LABEL maintainer=admin@example.com 0B buildkit.dockerfile.v0 <missing> About an hour ago LABEL stage=runner 0B buildkit.dockerfile.v0 <missing> 19 months ago CMD ["/bin/sh"] 0B buildkit.dockerfile.v0 <missing> 19 months ago ADD alpine-minirootfs-3.18.12-x86_64.tar.gz … 7.67MB buildkit.dockerfile.v0 [root@Docker nginx-multistage]# docker history nginx:yum-v1 IMAGE CREATED CREATED BY SIZE COMMENT 36ed6ee1ba71 2 days ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0 <missing> 2 days ago EXPOSE [443/tcp 80/tcp] 0B buildkit.dockerfile.v0 <missing> 2 days ago RUN /bin/sh -c rm -rf ./* && curl -o Cen… 58.9MB buildkit.dockerfile.v0 <missing> 2 days ago WORKDIR /etc/yum.repos.d/ 0B buildkit.dockerfile.v0 <missing> 2 days ago LABEL description=Nginx image built with YUM… 0B buildkit.dockerfile.v0 <missing> 2 days ago LABEL version=1.0 0B buildkit.dockerfile.v0 <missing> 2 days ago LABEL maintainer=admin@example.com 0B buildkit.dockerfile.v0 <missing> 5 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 5 years ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 223MB [root@Docker nginx-multistage]#

多阶段构建的镜像层数更少,且只包含运行阶段的内容,builder 阶段的编译工具和源码不会出现在最终镜像中。

4.4 镜像体积对比

[root@Docker nginx-multistage]# docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep nginx nginx-ms latest 19MB nginx multistage-v1 21.7MB nginx yum-v1 527MB 192.168.244.21:5000/test-nginx 1.27.2-alpine 79.1MB nginx 1.27.2-alpine 79.1MB [root@Docker nginx-multistage]#

镜像大小说明
nginx:yum-v1~420MB基于完整 CentOS 7,包含编译工具和系统库
nginx:multistage-v1~50MB基于 Alpine,仅包含 Nginx 运行时和必要依赖

五、实验总结

本实验通过多阶段构建技术,成功将 Nginx 镜像从 400MB+ 优化到 50MB 以内,掌握了以下核心知识点:

  • 多阶段构建原理:同一个 Dockerfile 中可以定义多个 FROM 阶段,每个阶段独立构建,最终只保留最后一个阶段的产物。
  • 编译与运行分离:builder 阶段负责下载源码和编译,runner 阶段负责提供最小运行时环境,两者互不干扰。
  • Alpine Linux 的优势:Alpine 是一个极简的 Linux 发行版,基础镜像仅 5MB 左右,非常适合用作容器运行环境。
  • COPY --from 指令:这是多阶段构建的核心,允许从指定阶段复制文件到当前阶段。
  • 安全加固:最终镜像中不包含编译工具(gcc、make)和源码,减少了攻击面,提升了安全性。

延伸思考:多阶段构建不仅适用于 Nginx,对于 Go、Rust、Java 等需要编译的语言同样适用。例如 Go 语言可以在 builder 阶段编译出静态二进制文件,在 runner 阶段直接复制该文件运行,最终镜像甚至可以小到 10MB 以内。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 4:15:49

做网站推广托管注意哪5点,新手选哪家好别踩坑

做网站推广托管注意哪5点,新手选哪家好别踩坑 昨晚凌晨三点,后台警报炸了。我盯着屏幕,心沉到了谷底:官网首页被黑,弹出了满屏的博彩广告。更恶心的是,客户直接打过来骂,说他们的品牌信誉全毁了。那一刻我才彻底明白, 网站被黑挂马不知道怎么办…

作者头像 李华
网站建设 2026/9/27 4:15:18

3个真实案例揭秘电子商务网站建设发展报告背后的黑产套路

3个真实案例揭秘电子商务网站建设发展报告背后的黑产套路 上周凌晨两点,我刚挂掉一个客户的电话。对方声音颤抖,说商城后台突然多了几个陌生管理员,前台页面挂满了非法广告,甚至开始自动发邮件给用户。他问我:“网站被黑挂马不知道怎么办?”…

作者头像 李华
网站建设 2026/9/27 4:14:14

沃噻网站建设流程全解:从0到1搞定性能优化

沃噻网站建设流程全解:从0到1搞定性能优化 手里没代码,心里却有个想上网的生意,这感觉我太熟了。很多人卡在建站第一步,觉得技术门槛高得离谱,其实只要理清 沃噻网站建设流程 ,普通人也能把网站跑起来。别被那些晦涩的名词吓退,咱们今天不谈虚的,只聊怎么把网站做得快、稳、能搜到。…

作者头像 李华
网站建设 2026/9/27 4:14:13

邵阳整站优化避坑指南:3招解决拖稿难题与性能优化

邵阳整站优化避坑指南:3招解决拖稿难题与性能优化 找建站公司改个按钮位置,对方居然让你等一周?这种“改个需求拖一周”的体验,在邵阳本地找整站优化服务时太常见了。很多老板觉得,不就是改个文案、调个布局吗,怎么比修路还慢? 其实,这背后暴露的是对方在 性能优化…

作者头像 李华
网站建设 2026/9/27 4:13:46

被黑挂马别慌:从零搭建wordpress新闻快讯插件安全防线指南

被黑挂马别慌:从零搭建wordpress新闻快讯插件安全防线指南 网站被黑挂马不知道怎么办?看着后台莫名多出几百条垃圾链接,或者浏览器弹出红色警告,这种噩梦般的体验,很多站长都经历过。别急着删库重装,那是下下策。今天咱们聊聊怎么 从零搭建 一套既好用又安全的新闻快讯系统,重点讲讲…

作者头像 李华
网站建设 2026/9/27 4:13:40

避坑指南:自己做装修效果的网站,3步搞定不拖工期

避坑指南:自己做装修效果的网站,3步搞定不拖工期 改个按钮颜色,建站公司说要排期,一拖就是五天。 这种“改需求拖一周”的坑,你肯定踩过。 别再等了,这份避坑指南教你自己做装修效果的网站。 运营目标与指标:先想清楚再动手 很多老板一上来就找外包,或者自己瞎折腾代码。…

作者头像 李华