Docker 镜像大小和安全性优化:综合指南
Docker是一个强大的工具,它使开发人员能够容器化他们的应用程序并确保跨各种环境的一致性。
然而,如果不仔细考虑,Docker 镜像可能会变得臃肿、缓慢,并且容易受到安全风险的影响。在本指南中,我将引导您了解优化 Docker 镜像大小和安全性的策略,以确保高效、安全的部署。
优化 Docker 镜像大小
Docker 镜像的大小直接影响其拉取和部署的速度,这将显著减少管道运行时间和工件存储成本,因此减小镜像大小对于性能和资源效率至关重要。
在本节结束时,我将向您展示我的作品集网站的图像尺寸减少了近 96%!
最小化图像尺寸的方法如下:
1)使用官方最小基础镜像
构建 Docker 镜像时,请务必从官方基础镜像开始。不要使用像ubuntu这样的全尺寸操作系统镜像,而应选择alpine或debian-slim这样的轻量级版本。这些精简镜像仅包含基本功能,可显著减小镜像大小。
以节点图像为例,以下是node:latest与node:alpine 的图像大小:
这几乎大了 7 倍!
通过使用最小基础图像,您可以避免不必要的包,从而实现更快的构建和更小的图像。
2)尽量减少层数
Dockerfile 中的每条指令(RUN、COPY等)都会在最终镜像中创建一个新层。将相关命令合并到单个层中可以减少层数,从而减小镜像大小。
- 不要这样做
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
- 执行此操作
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
3)使用“.dockerignore”排除不必要的文件
构建 Docker 镜像时,除非您另有指定,否则 Docker 会将整个上下文(项目目录中的所有内容)复制到镜像中。为防止包含不必要的文件,请创建 .dockerignore 文件。
- 示例.dockerignore
node_modules
.git
logs
tmp
该文件的作用类似于 .gitignore
4)使用静态二进制文件和“临时”基础映像
如果您的应用程序可以编译成静态二进制文件,则可以使用临时基础镜像,它本质上是一个空镜像。这会导致最终镜像非常小。
- 例子
FROM scratch
COPY myapp /
CMD ["/myapp"]
适用于不需要操作系统级依赖的应用程序。
5)多阶段构建(最有效)
多阶段构建允许您将构建过程与运行时环境分离。当您的应用程序需要编译工具,但最终镜像中不需要它们时,此功能尤其有用。
- 例子
# Stage 1: Build
FROM golang:1.16-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .
# Stage 2: Runtime
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
定量比较
我使用 React 构建的 Portfolio 网站之前是使用node:14-alpine图像构建的,它仍然比node:latest图像小。
- Dockerfile 如下:
# Use an official Node runtime as a parent image
FROM node:14-alpine
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json to the working directory
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code to the working directory
COPY . .
# Build the React app
RUN npm run build
# Install a lightweight HTTP server to serve the app
RUN npm install -g serve
# Set the default command to serve the build folder
CMD ["serve", "-s", "build"]
# Expose the port the app will run on
EXPOSE 3000
- 构建的图像尺寸为:
此后很久,我了解了多阶段构建并重新设计了我的 Dockerfile。
- 新的 Dockerfile 如下所示:
# Build environment (Stage - I)
FROM node:14-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production environment (Stage - II)
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
令人惊讶的是,新的图像尺寸是……
该应用程序的运行方式与以前完全一样,并且此版本的启动速度要快得多!
产生的差异约为1079 MB,减少了近96%!
这是多阶段构建效果的说明
优化 Docker 镜像的安全性
1)使用受信任的官方基础镜像
始终使用来自可信来源(例如 Docker Hub 或您组织的可信镜像仓库)的官方基础镜像。这些镜像会定期更新,并且比自定义或非官方镜像更安全。请保持基础镜像为最新版本,以缓解任何漏洞。
2)以非root用户身份运行容器
以 root 身份运行容器可能会使您的主机系统面临安全风险。请在 Dockerfile 中创建一个非 root 用户,并将容器配置为以该用户身份运行。
- 例子:
RUN adduser --disabled-password myuser
USER myuser
这种简单的改变通过限制对系统资源的访问减少了攻击面并提高了安全性。
3)扫描图像中的漏洞
使用以下工具定期扫描 Docker 镜像中是否存在已知漏洞:
- Trivy:一个开源漏洞扫描器。
- Docker 扫描:内置于 Docker CLI。
- Clair:一种用于发现漏洞的静态分析工具。
这些工具会扫描您的图像中是否存在过时或不安全的包,并提醒您注意潜在的威胁。
4)限制网络曝光
通过限制容器监听的端口和 IP 地址来限制其网络暴露。默认情况下,Docker 会将端口暴露给所有接口。如果不需要外部访问,请将它们绑定到 localhost。
- 例子:
docker run -p 127.0.0.1:8080:8080 myimage
这会将对容器服务的访问限制在本地机器上,从而阻止外部访问。
4)秘密管理
避免将 API 密钥或密码等敏感信息直接硬编码到 Dockerfile 或环境变量中。请使用 Docker Secrets 或外部 Secrets 管理工具,例如 AWS Secrets Manager 或 HashiCorp Vault。
- 使用 Docker Secrets 的示例:
docker secret create my_secret secret.txt
Docker 机密确保敏感数据仅对需要它的服务可用,而不会在容器文件系统中留下痕迹。
结论
通过遵循这些策略,您可以构建轻量级且安全的 Docker 镜像。优化大小有助于缩短部署时间、节省资源、降低成本并提高性能,而安全最佳实践则可以保护您的应用程序和基础架构免受漏洞侵害。
请记住,容器化带来了诸多优势,但也带来了新的挑战。通过周到的镜像优化,您可以充分利用 Docker 的潜力,同时保持强大的安全态势。
如果觉得这篇文章有帮助,请点赞。
关注我,获取更多类似内容。
学习愉快!
独家作者,
👨💻 阿克沙特·高塔姆
Google 认证助理云工程师 | 全栈开发人员
欢迎随时通过LinkedIn与我联系。
文章来源:https://dev.to/akshat_gautam/optimizing-docker-images-for-size-and-security-a-compressive-guide-4df0