1.尽量使用小型的基础镜像
Alpine Linux是一种基于musl libc和BusyBox的轻量级Linux发行版。它专注于安全、简单和高效,以最小化系统资源消耗和攻击面。Alpine Linux采用apk包管理器,使软件安装和更新变得简单和快速。它也可以作为容器镜像的基础操作系统,因为它的镜像非常小,这使得它适合于云原生应用和微服务架构

2.尽量移除不必要数据(文件 ,包<编译后将编译依赖包去除,保留运行时依赖>)

3.尽量减少镜像层数

4.可以采取 多阶段 构建镜像

5.如果可以实现为全静态项目,采用空(scratch)基础镜像构建

多阶段构建

# 第一阶段:构建nginx
FROM alpine:latest AS builder

# 更改apk源为阿里云源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

# 复制nginx源代码包
COPY nginx-1.22.0.tar.gz /tmp

# 安装构建依赖并编译nginx
RUN apk add --no-cache make gcc libgcc libc-dev zlib-dev pcre-dev openssl-dev && \
    cd /tmp && \
    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 -j2 && \
    make install && \
    # 清理构建依赖
    apk del make gcc libc-dev zlib-dev pcre-dev openssl-dev && \
    rm -rf /tmp/nginx-1.22.0 /tmp/nginx-1.22.0.tar.gz

# 第二阶段:运行nginx
FROM alpine:latest

# 复制编译好的nginx
COPY --from=builder /usr/local/nginx /usr/local/nginx

# 复制nginx配置文件和静态文件
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
COPY xxl /usr/local/nginx/html

# 设置工作目录
WORKDIR /usr/local/nginx/html

# 启动nginx
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

用此Dockerfile构建的镜像,构建容器,容器会立即退出,查看log:

[root@bolog sinatra]# docker logs cfa4c08f96c3
Error loading shared library libpcre.so.1: No such file or directory (needed by /usr/local/nginx/sbin/nginx)
Error relocating /usr/local/nginx/sbin/nginx: pcre_exec: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_config: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_fullinfo: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_compile: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_study: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_free_study: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_free: symbol not found
Error relocating /usr/local/nginx/sbin/nginx: pcre_malloc: symbol not found

错误信息表明在运行nginx时找不到所需的共享库 libpcre.so.1,这是因为在运行阶段的Alpine镜像中缺少 libpcre 库。虽然在构建阶段安装了相关的开发包,但在运行阶段没有安装这些库。

所以修改Dockersfile

# 第一阶段:构建nginx
FROM alpine:latest AS builder

# 更改apk源为阿里云源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

# 复制nginx源代码包
COPY nginx-1.22.0.tar.gz /tmp

# 安装构建依赖并编译nginx
RUN apk add --no-cache make gcc libgcc libc-dev zlib-dev pcre-dev openssl-dev && \
    cd /tmp && \
    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 -j2 && \
    make install && \
    # 清理构建依赖
    apk del make gcc libc-dev zlib-dev pcre-dev openssl-dev && \
    rm -rf /tmp/nginx-1.22.0 /tmp/nginx-1.22.0.tar.gz

# 第二阶段:运行nginx
FROM alpine:latest

# 更改apk源为阿里云源并安装运行时依赖
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add --no-cache pcre openssl zlib

# 复制编译好的nginx
COPY --from=builder /usr/local/nginx /usr/local/nginx

# 复制nginx配置文件和静态文件
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
COPY xxl /usr/local/nginx/html

# 设置工作目录
WORKDIR /usr/local/nginx/html

# 启动nginx
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@bolog sinatra]# docker build --no-cache -t xxl-apline-src:v3 .

[root@bolog sinatra]# docker run  -dt --name game3 -p82:80 xxl-apline-src:v3
997ba78618b9896dff28fda4b7b3ad71b4ef726b5596c1767d3f8a7bddc3e057
[root@bolog sinatra]# docker ps
CONTAINER ID   IMAGE               COMMAND                   CREATED         STATUS         PORTS                               NAMES
997ba78618b9   xxl-apline-src:v3   "/usr/local/nginx/sb…"   3 seconds ago   Up 2 seconds   0.0.0.0:82->80/tcp, :::82->80/tcp   game3
bea8055b95df   xxl-alpine-bin:v1   "/usr/local/nginx/sb…"   3 hours ago     Up 3 hours     0.0.0.0:80->80/tcp, :::80->80/tcp   game

结果对比

[root@bolog sinatra]# docker images
REPOSITORY       TAG       IMAGE ID       CREATED         SIZE
xxl-apline-src   v3        8168b45956e6   9 minutes ago   16.8MB
xxl-apline-src   v2        bf8194f9f50d   2 hours ago     15.6MB
xxl-alpine-src   v1        5d8f65081b64   3 hours ago     176MB

由此可见,使用多阶段构建可以极大的节约空间

为什么能减少这么多空间

  • 构建阶段和运行阶段分离

    • 在多阶段构建中,构建阶段使用了包含开发工具和库的基础镜像,这些工具和库只在编译和构建nginx时需要。

    • 运行阶段使用了一个干净的Alpine镜像,只包含运行nginx所需的最小文件和依赖。这意味着不需要在最终镜像中包含编译工具和中间文件。

  • 减少了不必要的依赖

    • 在构建阶段,安装了编译nginx所需的所有依赖(如 makegcclibc-devzlib-devpcre-devopenssl-dev),这些依赖在编译完成后被删除。

    • 运行阶段只安装了nginx运行时所需的最小依赖(如 pcreopensslzlib),大大减少了最终镜像中不必要的文件。

  • 清理构建文件

    • 在构建完成后,删除了构建过程中生成的临时文件和缓存(如 /tmp/nginx-1.22.0/tmp/nginx-1.22.0.tar.gz),确保最终镜像干净整洁,避免了冗余数据的增加。

  • 压缩的层次

    • 使用多阶段构建时,只有构建阶段生成的有效文件(如nginx的可执行文件和配置文件)被复制到最终镜像中。每个阶段的镜像层数被有效地压缩,减少了不必要的层次。