- 1. 使用多阶段构建">1. 使用多阶段构建
- 2. 选择正确的基础镜像">2. 选择正确的基础镜像
- 3. 最小化层数">3. 最小化层数
- 4. 利用 Docker 忽略文件">4. 利用 Docker 忽略文件
- 5. 优化软件安装">5. 优化软件安装
- 6. 尽可能使用静态二进制文件">6. 尽可能使用静态二进制文件
- 7. 使用 BuildKit 压缩镜像层">7. 使用 BuildKit 压缩镜像层
- 8. 挤压镜像层">8. 挤压镜像层
- 9. 使用镜像扫描工具提供优化建议">9. 使用镜像扫描工具提供优化建议
- 10.定期更新镜像">10.定期更新镜像
- 11. 最小化运行时可变性">11. 最小化运行时可变性
- 12. 优化应用程序代码和资产">12. 优化应用程序代码和资产
- 13. 在 CI/CD 管道中自动执行镜像优化">13. 在 CI/CD 管道中自动执行镜像优化
1. 使用多阶段构建
Docker 中的多阶段构建是一项强大的功能,可让您简化 Dockerfile,使其更高效、更易于维护。通过使用多阶段构建,您实际上在 Dockerfile 中使用了多个 FROM 语句。每个 FROM 指令可以使用不同的基础镜像,并且每个阶段都可以命名。您可以将介质从一个阶段复制到另一个阶段,在最终镜像中留下您想要的所有内容。为什么选择多阶段构建
减小镜像大小:通过将生成环境与运行时环境分离,可以确保最终镜像中仅包含必要的项目和依赖项。
安全性:通过排除运行时镜像中不需要的工具和文件来最大程度地减少攻击面。
简化 Dockerfile:允许您在单个 Dockerfile 中同时拥有构建和运行时环境,使其更易于管理和理解。
实现多阶段构建
下面是一个多阶段构建的基本示例,该构建在构建阶段编译 Go 应用程序,然后将编译后的二进制文件复制到轻量级 Alpine 运行时阶段:
# Build stage
FROM golang:1.16 AS build
WORKDIR /app
COPY . .
RUN go build -o myapp .
# Runtime stage
FROM alpine:latest
WORKDIR /root/
COPY --from=build /app/myapp .
CMD ["./myapp"]
优化Node.js应用程序
在此示例中,我们在第一阶段构建Node.js应用程序,安装依赖项并构建静态资产。在第二阶段,我们只复制运行应用程序所需的文件和资产:
# Build stage
FROM node:14 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Runtime stage
FROM node:14-alpine
WORKDIR /app
COPY --from=build /app/package*.json ./
RUN npm install --only=production
COPY --from=build /app/build ./build
CMD ["node", "build/server.js"]
高级用例:Java 应用程序
对于 Java 应用程序,您可以在构建阶段使用 Maven 或 Gradle 等构建工具,然后将应用程序打包到精简的运行时镜像中:了解更多信息:https://overcast.blog/kubernetes-multi-stage-builds-a-practical-guide-982e95c5072a?source=post_page-----5c5c7697e718--------------------------------
# Build stage
FROM maven:3.6.3-jdk-11 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -f pom.xml clean package
# Runtime stage
FROM openjdk:11-jre-slim
COPY --from=build /app/target/my-application.jar /usr/app/
WORKDIR /usr/app
EXPOSE 8080
CMD ["java", "-jar", "my-application.jar"]
2. 选择正确的基础镜像
选择正确的基础镜像是减小 Docker 镜像大小的最直接但最有效的方法之一。基础镜像是容器的基础,包括操作系统和基础文件。通过选择轻量级基础镜像,可以显著减小最终容器镜像的整体大小,从而缩短生成和部署时间,并减少资源消耗。选择基础镜像的条件
大小:选择较小的基础镜像,以最大程度地减少最终镜像的占用空间。
安全性:较小的镜像通常包含较少的组件,这可以减少攻击面。兼容性:确保基础镜像支持应用程序所需的所有依赖项和运行时环境。维护:首选由其维护者或社区定期更新和维护的镜像。
流行的轻量级基础镜像
Alpine Linux:Alpine 以其小尺寸和安全性而闻名,是许多 Docker 镜像的热门选择。
- 例: FROM alpine:latest
Distroless by GoogleContainerTools:这些镜像仅包含您的应用程序及其运行时依赖项。它们不包括包管理器、shell 或您希望在标准 Linux 发行版中找到的任何其他程序。
- 例: FROM gcr.io/distroless/java:11
Slim Variants:许多官方镜像提供超薄变体,这些变体是标准镜像的最小版本。
- 例: FROM python:3.8-slim
示例:优化 Python 应用程序
在优化之前,使用标准 Python 镜像:优化后,切换到超薄变体:
FROM python:3.8
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
通过使用 python:3.8-slim 镜像并添加 —no-cache-dir pip install ,可以大大减小镜像大小。
FROM python:3.8-slim
COPY . /app
WORKDIR /app
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "app.py"]
示例:将多阶段构建与 Alpine 一起用于 Node.js 应用程序
此 Dockerfile 用于 node:14-alpine 在构建期间和运行时最小化镜像大小,并利用多阶段构建来确保最终镜像中仅包含必要的文件。
# Build stage
FROM node:14-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# Runtime stage
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "build/index.js"]
了解更多信息
- Alpine Linux:https://www.alpinelinux.org/
- GoogleContainerTools 开发的无发行版镜像:https://github.com/GoogleContainerTools/distroless
- 编写 Dockerfile 的最佳实践:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
- Alpine 镜像:https://overcast.blog/leveraging-alpine-images-in-kubernetes-a-guide-6245e1380513?source=post_page-----5c5c7697e718--------------------------------
3. 最小化层数
在 Docker 中,Dockerfile 中的每个命令都会向镜像添加一个新层。这些层会增加镜像的大小,从而影响拉取时间和存储效率。通过最小化层数并优化其内容,可以显著减小 Docker 镜像的整体大小。最小化层的策略
合并 RUN 指令:不要对每个命令使用多个 RUN 指令,而是使用逻辑运算符将它们合并到单个 RUN 语句中。
删除不必要的文件:在创建或修改文件的同一层中,确保清理任何不必要的文件。
最小化层的好处
提高效率:层数越少,镜像提取速度越快,存储空间使用量越少。
简化的镜像结构:使镜像更易于理解和维护。
示例:优化 Node.js Dockerfile
优化前:优化后:
FROM node:14
RUN apt-get update
RUN apt-get install -y curl
RUN mkdir /app
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "app.js"]
在优化的 Dockerfile 中, apt-get update 、 apt-get install 和 cleanup 合并为一条 RUN 指令。此外, npm install 通过仅安装生产依赖项并清除 npm 缓存进行了优化。
FROM node:14
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package.json .
RUN npm install --production && \
npm cache clean --force
COPY . .
CMD ["node", "app.js"]
示例:减少 Python 应用程序中的层
优化前:优化后:
FROM python:3.8
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
通过一次复制所有必要的文件并将 pip install 和 清理步骤合并到一个 RUN 命令中,可以减少镜像层数,并从最终镜像中删除不必要的文件。
FROM python:3.8
COPY . .
RUN pip install --no-cache-dir -r requirements.txt && \
rm requirements.txt
了解更多信息
- Dockerfile 最佳实践:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers
- 了解 Docker 层:https://docs.docker.com/storage/storagedriver/
4. 利用 Docker 忽略文件
有效地使用 .dockerignore 文件可以显著减少在镜像构建期间发送到 Docker 守护程序的构建上下文。通过指定与要从生成上下文中排除的文件和目录匹配的模式,不仅可以加快生成过程,还可以确保不需要的文件和敏感信息不会无意中包含在 Docker 镜像中。为什么 .dockerignore 文件很重要
加快构建时间:通过从构建上下文中排除不必要的文件,Docker 可以处理和传输更少的数据,从而缩短构建时间。
提高安全性:帮助防止将敏感数据(如密钥和开发日志)添加到镜像中。
减小镜像大小:确保镜像中仅包含应用程序所需的文件,避免膨胀。
使用 .dockerignore 技巧
查看上下文:在编写 .dockerignore 文件之前,请查看生成上下文目录的内容。识别临时文件、本地配置文件和其他非必要项目。
使用通配符:利用通配符排除广泛的文件组,例如 .log 日志文件或 .tmp 临时文件。
更改后测试:更新 .dockerignore 文件后,重新生成 Docker 镜像,以确保应用程序在没有排除的文件的情况下仍能正常运行。
Node.js应用程序的示例 .dockerignore 文件
此 .dockerignore 文件不包括 Docker 镜像中不需要的公共目录和文件,例如源代码管理目录 ( git )、环境文件 ( .env ) 和本地开发文件 ( docker-compose.yml , npm-debug.log )。
node_modules
npm-debug.log
.DS_Store
.env
.git
.gitignore
README.md
LICENSE
docker-compose.yml
Dockerfile
tests/
示例: .dockerignore 集成到 Python 项目中
对于 Python 项目,这 .dockerignore 可确保编译的 Python 文件、Git 目录、环境文件和其他非必要项不包含在 Docker 构建上下文中,从而简化构建过程并保护最终镜像。
*.pyc
*.pyo
*.pyd
__pycache__
.env
.git
.gitignore
README.md
Dockerfile
tests/
了解更多信息
- Docker .dockerignore :https://docs.docker.com/engine/reference/builder/#dockerignore-file
- 写入 .dockerignore 文件的最佳实践:https://www.docker.com/blog/faster-builds-in-docker-compose-thanks-to-dockerignore-support/
5. 优化软件安装
优化软件和依赖项在 Docker 镜像中的安装方式可以大大减小其大小并提高安全性。这涉及诸如合并安装命令、安装后清理以及选择最有效的安装方法等策略。整合安装命令
通过将多个软件安装命令合并到一条 RUN 指令中,可以减少 Docker 镜像中的层数,从而显著减小其大小。示例:在单层中安装实用程序
此命令更新包列表,安装必要的包,并在一个层中进行清理,而不是为每个步骤创建单独的层,这样效率更高。
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y curl git vim && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
安装后清理
许多包管理器创建的缓存对于在容器中运行应用程序不是必需的。在同一 RUN 语句中移除这些缓存和其他临时文件可防止它们包含在镜像图层中。示例:删除缓存文件
此方法在不保留缓存的情况下安装 Python 包,并删除 pycache 生产映像中不需要的目录,从而减小镜像大小。
FROM python:3.8-slim
RUN pip install --no-cache-dir flask gunicorn && \
find / -type d -name __pycache__ -prune -exec rm -rf {} \;
选择高效的安装方法
在可能的情况下,选择将添加的组件的大小降至最低的软件安装方法。例如,使用静态编译的二进制文件而不是包管理器安装可以显著减小 Docker 镜像的大小。示例:使用静态编译的二进制文件
此 Dockerfile 示例演示如何使用静态编译的二进制文件, my-static-binary 该二进制文件包含其所有依赖项,从而消除了在镜像中安装其他软件包的需要。
FROM alpine:latest
COPY ./my-static-binary /usr/local/bin/my-app
CMD ["my-app"]
了解更多信息
- Dockerfile 最佳实践:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
- Alpine Linux 官方文档:https://wiki.alpinelinux.org/wiki/Main_Page
- 了解 Docker 缓存:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache
6. 尽可能使用静态二进制文件
将静态二进制文件合并到 Docker 镜像中可以显著降低其大小和复杂性。静态二进制文件是独立的可执行文件,其中包含二进制文件本身中所有必要的库和依赖项,无需在容器中安装这些依赖项。使用静态二进制文件的优点
减小镜像大小:由于静态二进制文件包含其所有依赖项,因此您可以将 Docker 镜像基于最小的基础镜像(如 scratch or alpine ),从而显着减小整体镜像大小。
提高安全性:镜像中包含的组件越少,潜在的攻击媒介就越少。
简化的依赖关系管理:静态二进制文件消除了在 Docker 镜像中管理单个库版本的需要,从而简化了构建过程。
创建静态二进制文件
创建静态二进制文件的过程因所使用的编程语言和生成工具而异。下面是 Go 的一个示例:此命令将 Go 应用程序编译为名为 myapp 的静态二进制文件。 CGO_ENABLED=0 环境变量禁用 CGO,确保不使用动态库,并 GOOS=linux 指定目标操作系统。
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
使用静态二进制文件的 Dockerfile 示例
使用 Go 应用程序:在这个多阶段构建中,第一阶段将 Go 应用程序编译为静态二进制文件。第二阶段从 scratch 空的 Docker 镜像开始,并在静态二进制文件中进行复制。结果是一个非常轻量级的 Docker 镜像,仅包含已编译的应用程序。
FROM golang:1.16 AS builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
FROM scratch
COPY --from=builder /build/myapp /myapp
CMD ["/myapp"]
了解更多信息
- Go 静态二进制文件:https://golang.org/pkg/cmd/link/
- 关于静态和动态库:https://www.learncpp.com/cpp-tutorial/static-and-dynamic-libraries/
- Docker 多阶段构建:https://docs.docker.com/develop/develop-images/multistage-build/
7. 使用 BuildKit 压缩镜像层
Docker BuildKit 是一个现代构建引擎,旨在解决以前构建实现的许多限制,从而在性能、缓存和安全性方面提供改进。它的突出功能之一是能够更有效地管理和压缩 Docker 镜像中的层,这可以显著减小镜像大小。使用 BuildKit 的优势
并行构建:BuildKit 可以并行执行多个构建阶段,从而加快整个构建过程。
高级缓存:它引入了改进的缓存机制,通过避免不必要的镜像层,可以减少构建时间并减小生成镜像的大小。
镜像层压缩:BuildKit 支持自动镜像层压缩,使镜像更小,存储和传输效率更高。
启用 BuildKit
BuildKit 包含在 Docker 18.09 及更高版本中,但默认情况下不启用。您可以通过设置 DOCKER_BUILDKIT 环境变量来启用它:或者将 Docker 守护程序配置为默认使用 BuildKit:
export DOCKER_BUILDKIT=1
docker build .
{ "features": { "buildkit": true } }
示例:使用 BuildKit 优化映像构建
优化前的 Dockerfile:使用 BuildKit 优化后的 Dockerfile: 使用 BuildKit,您可以通过组织 Dockerfile 来利用其缓存和并行化功能,以实现最佳层缓存并避免不必要的步骤:
FROM node:14
COPY . /app
WORKDIR /app
RUN npm install
此示例利用该 —mount=type=cache 选项来缓存 npm 模块,防止在每次生成中重新下载和重新安装它们,从而减少生成时间和生成镜像的大小。
# syntax=docker/dockerfile:1.2
FROM node:14
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
了解更多信息
- GitHub 上的 BuildKit:https://github.com/moby/buildkit
- Docker Buildx:https://docs.docker.com/buildx/working-with-buildx/
- BuildKit 的 Dockerfile 语法:https://docs.docker.com/engine/reference/builder/#syntax
8. 挤压镜像层
将镜像层压缩为单个层可以显著减小 Docker 镜像的大小。虽然 Docker 镜像由多个层组成,分别表示 Dockerfile 中的每条指令,但压缩会将这些层合并为一个,从而可能减少开销和镜像的总大小。但是,务必在挤压的好处和缺点之间取得平衡,例如丢失单个镜像层的构建缓存,这可能会影响后续的构建时间。挤压层的优点
减小镜像大小:合并镜像层可以消除因维护多个镜像层而引入的开销,尤其是在中间镜像层包含不必要的数据时。
简化的镜像结构:单层镜像更易于传输和管理,尤其是在存储效率至关重要的环境中。
如何压扁镜像层
Docker 本身不支持将压缩作为构建过程的一部分(从 Docker 19.03 开始),但您可以使用外部工具或 Docker export 和 import 命令来实现类似的效果。使用 docker export 和 docker import
构建镜像后,您可以将其导出到 tarball,然后将其重新导入为新镜像,该镜像将是一个单层:此序列从镜像创建一个容器,将其文件系统导出到 tarball,然后将该 tarball 作为新镜像导入。
docker build -t my-app .
docker container create --name temp-container my-app
docker export temp-container | docker import - my-app:squashed
docker container rm temp-container
使用 Docker Squash 工具
另一种方法是使用第三方工具,例如 docker-squash ,它可以更有选择性地压缩镜像层,从而保留某些镜像层的缓存的好处,同时减小镜像大小:此命令压缩 my-app:latest 镜像并将压缩的镜像标记为 my-app:squashed 。
pip install docker-squash
docker save my-app:latest | docker-squash -t my-app:squashed | docker load
考虑
虽然挤压可以减小镜像大小,但它也可能掩盖镜像的历史记录,并使识别镜像中的更改或更新变得更加困难。必须考虑压缩是否适合您的工作流和部署策略。了解更多信息
- Docker Squash 工具:https://github.com/goldmann/docker-squash
- 了解 Docker 层和镜像:https://docs.docker.com/storage/storagedriver/
9. 使用镜像扫描工具提供优化建议
镜像扫描工具不仅可以通过检测漏洞来增强安全性,还可以为优化 Docker 镜像提供有价值的见解。这些工具可以分析镜像中是否存在未使用的层、过多的文件或其他效率低下的问题,从而为减小镜像大小提供建议。使用镜像扫描工具的好处
识别不必要的组件:发现并删除未使用或不必要的文件、包或镜像层。
优化建议:接收有关如何在不影响功能的情况下减小镜像大小的可操作建议。
持续改进:集成到 CI/CD 管道中,以实现持续优化和安全状况改进。
流行的图像扫描工具
Dive:一种工具,用于探索 Docker 镜像、层内容以及发现缩小 Docker/OCI 镜像大小的方法。
Trivy:针对容器和其他工件的简单而全面的漏洞扫描程序,不仅提供安全性,还提供大小优化见解。
Snyk:提供功能丰富的平台,用于扫描和监控 Docker 镜像的漏洞,并深入了解如何优化和保护容器。
示例:使用 Dive 分析镜像
Dive 提供了一个用户友好的界面来探索镜像层并评估它们对整体镜像大小的影响。以下是如何使用 Dive 分析和识别优化 Docker 镜像的机会:Dive 将呈现镜像的详细细分,突出显示大文件和目录以及需要减小大小的潜在区域。
dive <your-image-name>
示例:使用 Trivy 扫描漏洞和大小
Trivy 不仅可以扫描您的镜像以查找漏洞,还可以扫描可能导致效率低下的错误配置:虽然 Trivy 专注于安全性,但通过识别可以删除的不必要的软件组件,获得的见解可以间接导致优化。
trivy image --ignore-unfixed <your-image-name>
了解更多信息
- Dive GitHub 存储库:https://github.com/wagoodman/dive
- Trivy GitHub 存储库:https://github.com/aquasecurity/trivy
- Snyk 官方文档: https://snyk.io/product/container-vulnerability-management/
10.定期更新镜像
使 Docker 镜像保持最新状态对于安全性和效率都至关重要。定期更新可确保您使用最新版本的基础镜像和依赖项,其中通常包括优化和安全补丁。这种做法可以减小镜像大小,因为较新版本的软件包可能更有效或消除以前所需的补丁和解决方法。定期更新的好处
增强的安全性:整合最新的安全补丁以防范漏洞。
缩小镜像大小:利用较新软件版本中的优化,这些优化可能会导致更小的包和依赖项。改进的性能:利用最新软件版本中的性能改进。
使镜像保持最新的策略
自动执行依赖项更新:使用 Dependabot 或 Renovate 等工具自动建议或应用更新到项目依赖项。
使用官方基础镜像:坚持使用官方基础镜像并标记您的 Dockerfile,以便在适当的情况下自动更新到最新的次要版本。
定期重建:计划定期重建镜像,以确保它们拉取最新版本的基础镜像和依赖项。
示例:自动执行基础镜像更新
考虑使用官方Node.js基础镜像的 Dockerfile:若要确保始终使用 Node.js 14 的最新修补程序版本,可以设置定期重新生成此镜像的 CI/CD 管道作业。如果 CI 工具支持 cron 作业,则可以将其配置为每周重新生成镜像:
FROM node:14
...
# CI/CD configuration pseudocode
jobs:
rebuild-image:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Build and push Docker image
run: |
docker build -t myapp:${{ github.sha }} .
docker push myapp:${{ github.sha }}
schedule:
- cron: '0 0 * * 0' # Every Sunday
示例:使用 Dependabot 进行依赖关系管理
如果项目包含 package.json for Node.js 依赖项,则可以使用 Dependabot 来保持这些依赖项的更新。Dependabot 将自动在存储库中打开拉取请求以更新到最新版本:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
了解更多信息
- Docker 官方文档中有关使镜像保持最新状态的最佳实践:https://docs.docker.com/develop/dev-best-practices/
- Dependabot 文档:https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically
- 翻新文档: https://docs.renovatebot.com/
11. 最小化运行时可变性
设计具有最小运行时可变性的 Docker 镜像意味着要努力实现构建后在不同环境中表现一致的镜像。这种方法提倡镜像包含所有必要的配置和依赖项,并通过容器编排工具(如 Kubernetes)而不是在镜像级别管理环境差异。这种做法不仅简化了部署过程,还有助于减少 Docker 镜像大小,避免包含可能用于修改运行时行为的不必要文件和工具。最小化运行时可变性的优点
可预测性:开发、测试和生产环境之间的差异较小,可减少遇到意外行为的机会。
安全性:更小、更简单的镜像和更少的移动部件意味着更小的攻击面。
效率:消除不必要的文件和配置可以减小镜像大小并缩短部署时间。
最小化运行时可变性的策略
环境变量:使用环境变量来调整应用程序在不同环境中的行为,而无需更改镜像本身。
配置文件:使用 Kubernetes ConfigMap 或 Secrets 在运行时挂载配置文件,而不是将不同的配置烘焙到镜像中。
动态内容交付:通过 API 或运行时发现提供动态内容,如功能标志或服务终结点,而不是将它们直接嵌入到镜像中。
示例:使用环境变量
可以将 Node.js 应用程序配置为使用环境变量连接到开发和生产中的不同数据库:在 Kubernetes 中,可以在部署配置中设置以下变量:
const dbConfig = {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
};
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
image: myapp:latest
env:
- name: DB_HOST
value: "prod.db.example.com"
- name: DB_USER
valueFrom:
secretKeyRef:
name: myapp-db-user
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: myapp-db-password
key: password
示例:挂载配置文件
您可以在运行时使用 Kubernetes ConfigMap 挂载配置文件,而不是在 Docker 镜像中嵌入配置文件:在您的部署中:
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
config.json: |
{
"loggingLevel": "verbose",
"featureToggle": "new-feature"
}
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
template:
spec:
containers:
- name: myapp
image: myapp:latest
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: myapp-config
了解更多信息
- Kubernetes 环境变量:https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/
- Kubernetes ConfigMaps:https://kubernetes.io/docs/concepts/configuration/configmap/
- Kubernetes Secret:https://kubernetes.io/docs/concepts/configuration/secret/
12. 优化应用程序代码和资产
优化 Docker 镜像中包含的应用程序代码和资产可以显著减小镜像大小。这涉及缩小代码、压缩资产和删除不必要的文件,这不仅可以减小 Docker 镜像的大小,还可以提高应用程序的运行时性能。优化代码和资产的好处
缩小镜像大小:较小的代码库和压缩的资产占用的空间更少,使您的 Docker 镜像更精简。
更快的构建和部署时间:较小的镜像可以更快地构建、推送和拉取,从而加快部署过程。
增强的性能:优化的资产加载速度更快,从而改善应用程序的整体用户体验。
代码和资产优化策略
缩小 JavaScript、CSS 和 HTML:使用工具从代码中删除不必要的字符,而无需更改其功能。
压缩镜像和其他资产:像这样的 imagemin 工具可以显著减小镜像文件的大小,而不会明显降低质量。
删除不必要的文件:确保 Docker 镜像中仅包含运行应用程序所需的文件。
示例:缩小 JavaScript 和 CSS
对于Node.js应用程序,您可以使用 JavaScript 和 clean-css CSS 等 uglify-js 工具来缩小您的资产。下面介绍如何设置脚本 package.json 来执行这些任务:运行 npm run build 将缩小您的 JavaScript 和 CSS 文件,准备好包含在您的 Docker 镜像中。
{
"scripts": {
"build": "uglifyjs -o dist/app.min.js src/app.js && cleancss -o dist/style.min.css src/style.css"
}
}
示例:压缩镜像
在 imagemin 将镜像资产添加到 Docker 镜像之前,在 Node.js 项目中使用:此脚本压缩 JPG 和 PNG 文件,在保持可接受质量的同时显著减小其大小。
const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const imageminPngquant = require('imagemin-pngquant');
(async () => {
await imagemin(['assets/images/*.{jpg,png}'], {
destination: 'dist/images',
plugins: [
imageminMozjpeg({quality: 75}),
imageminPngquant({
quality: [0.6, 0.8]
})
]
});
console.log('Images optimized');
})();
了解更多信息
- 缩小适用于 JavaScript 的工具:https://github.com/mishoo/UglifyJS
- 用于 CSS 缩小的 clean-CSS:https://github.com/jakubpawlowicz/clean-css
- 用于资产压缩的 Imagemin:https://github.com/imagemin/imagemin
13. 在 CI/CD 管道中自动执行镜像优化
将镜像优化集成到持续集成/持续部署 (CI/CD) 管道中,可在生成过程中自动执行减小 Docker 镜像大小的过程。这可确保部署的每个镜像都尽可能高效,而无需手动干预或单独的优化步骤。自动化镜像优化的好处
一致性:确保在部署之前优化每个镜像,使所有镜像的质量和大小保持一致。
效率:通过自动执行重复性优化任务来节省时间并降低人为错误的可能性。
改进的工作流程:让开发人员能够专注于功能开发,而不是手动优化流程。
自动化策略
集成镜像缩小工具:DockerSlim 等工具可以集成到 CI/CD 管道中,以自动减小镜像大小。
在 CI/CD 中使用多阶段构建:确保 CI/CD 管道利用 Docker 的多阶段构建将构建环境与生产环境分开,从而最大程度地减小最终镜像的大小。
自动执行代码和资产优化:在管道中合并步骤,以在将资产添加到 Docker 镜像之前自动缩小代码并压缩资产。
示例:在 CI 管道中集成 DockerSlim
DockerSlim ( docker-slim ) 可以自动分析和优化 Docker 镜像以用于生产。以下是将 DockerSlim 集成到 GitHub Actions 工作流程中的方法:此 GitHub Actions 工作流签出代码,生成 Docker 镜像,安装 DockerSlim,然后使用 DockerSlim 优化镜像。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t myapp .
- name: Install DockerSlim
run: curl -L https://downloads.dockerslim.com/releases/1.35.0/dist_linux.tar.gz | tar xz -C /tmp
- name: Optimize Docker image with DockerSlim
run: /tmp/dist_linux/docker-slim build --http-probe myapp
示例:CI/CD 中的代码和资产优化
若要自动缩小 JavaScript 和 CSS 以及压缩镜像,可以在生成 Docker 镜像之前在 CI/CD 管道中添加步骤:在此示例中, npm run build 和 npm run compress-images 是在 ur package.json 中定义的脚本,用于分别缩小应用程序的 JavaScript 和 CSS 文件并压缩镜像资产。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm install
- name: Minify JavaScript and CSS
run: npm run build
- name: Compress images
run: npm run compress-images
- name: Build Docker image
run: docker build -t myapp .