做网站平台,wordpress文章省略,做私人彩票网站,wordpress+pdo+mysql扩展一、说明 在微服务领域#xff0c;拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素#xff0c;包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构… 一、说明 在微服务领域拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构以及利用多阶段构建来减小映像大小。本博客的部分内容受到我最近来自Matthijs Brouns的精彩演讲的启发您可以在此处查看。 我将使用 CLI 工具潜水来分析图像及其图层。Docker镜像的目的是充当机器学习应用程序的FASTAPI服务器的主机而Poetry是其依赖项管理器。有关使用诗歌而不是pip/pipenv/pip-tools/conda的动机的更多信息请阅读此博客和此博客。请注意对 Docker 和 Docker 文件的基本了解是本文的先决条件。
FROM python:3.11-slim as build 我正在使用 Python 3.11 的精简版本来最小化容器的大小并使其尽可能轻量级。它的大小为 121 MB。 完整的Python映像python3.11包括运行应用程序不需要的额外开发工具和文档使其更大大小为875 MB比苗条版本大约7倍。 另一种选择是Alpinepython3.11-alpine它更小大小为56.5 MB。但是它缺少软件包安装程序 pip 和对安装轮子包的支持这两者都是安装 Pandas 和 Numpy 等应用程序所必需的。若要安装这些应用程序需要使用 G 等编译器包从源文件编译它们默认情况下也不会在 Alpine 映像上安装这些包。这导致图像尺寸比苗条版本更大和麻烦得多所以让我们继续那个。
ENV PIP_DEFAULT_TIMEOUT100 \# Allow statements and log messages to immediately appearPYTHONUNBUFFERED1 \# disable a pip version check to reduce run-time log-spamPIP_DISABLE_PIP_VERSION_CHECK1 \# cache is useless in docker image, so disable to reduce image sizePIP_NO_CACHE_DIR1ARG POETRY_VERSION1.3.2 Dockerfile 中的 ENV 变量被设置为在 Docker 容器中安装软件包期间优化 pip 和诗歌的行为。此外我明确定义了要安装的诗歌版本。
二、Docker安全 让我们继续讨论安全性因为有几个方面很重要。不建议以 root 用户身份运行 Docker 容器因为 root 用户可以完全控制主机系统包括修改或删除文件、启动和停止服务以及访问敏感信息的能力。若要遵循最小特权原则最好仅使用所需的最低特权运行容器。因此为了增强安全性我们为 Docker 容器创建了一个名为 的非 root 用户。appuser
RUN set -ex \# Create a non-root user addgroup --system --gid 1001 appgroup \ adduser --system --uid 1001 --gid 1001 --no-create-home appuser \ 通过分配特定的用户和组 ID例如 1001可以更轻松地管理不同系统之间的用户权限和访问控制尤其是在 Kubernetes 等平台上运行容器时。 那么 的权限与根用户的权限有何不同呢分配给的权限可能包括对某些文件和目录的读取、写入或执行访问的限制具体取决于为这些资源设置的默认权限。例如默认情况下可能没有对容器中特定子目录的写入访问权限。如果运行 作为的应用程序需要对该目录的写入访问权限则需要使用以下命令更改该目录的所有权以授予所需的权限appuserappuserappuserappuserchownappuser
RUN chown -R appuser:appuser /your-subdirectory 否则将引发以下错误
[Errno 13] Permission denied: your-subdirectory/filename 另一个安全最佳实践是更新和升级 Docker 容器中的包。原因是在 Docker 环境中用于创建容器的基础映像通常是特定版本的操作系统的快照。随着时间的推移可能会发现安全漏洞或其他问题并发布修补程序以使用 和 解决这些问题。该命令更新包索引有点像可用软件包及其元数据的数据库并从包存储库中检索最新的包信息。apt-get updateapt-get upgradeapt-get update
RUN set -ex \ apt-get update \ apt-get upgrade -y 现在我们有了有关可用软件包的信息我们可以使用该命令将容器中当前安装的软件包升级到其最新的可用版本。该标志用于在升级过程中自动对任何提示回答“是”。apt-get upgrade-y ⬆ 更新过程导致一些自动安装的包、包缓存文件和包索引文件。在运行应用程序时不再需要这些文件因为它们达到了帮助升级包的目的。我们可以使用以下命令安全地删除这些文件这应该会减小 Docker 映像的大小。
# Clean up
RUN set -ex apt-get autoremove -y \\ apt-get clean -y \\ rm -rf /var/lib/apt/lists/* 最后的安全最佳做法是确保 docker 映像中不包含任何机密。为了帮助防止这种情况您可以将常用机密文件和文件夹添加到 .dockerignore 文件中
**/.env
**/.aws
**/.ssh 您还可以使用 Trivy例如当您使用“root”作为图像用户时它会警告您。以下是VSCode扩展的屏幕截图 Trivy 的 VSCode 扩展 三、应用程序文件 好了现在我们已经设置了一些环境变量并提高了 docker 容器的安全性让我们继续复制实际的应用程序文件并安装依赖项。我们希望将工作目录设置为“/app”。此目录在基本映像中尚不存在但如果不存在则会为我们创建它。所有后续指令都将在此位置执行这使我们的 docker 镜像更有条理和可移植性。WORKDIR
WORKDIR /app
COPY pyproject.toml poetry.lock ./ 该命令用于将文件从主机系统复制到容器文件系统。在本例中我们正在复制 和 这是 Poetry 包管理器的配置文件。COPYpyproject.tomlpoetry.lock
四、潜水 现在我们已经完成了一些步骤让我们构建 docker 镜像并深入研究它以检查️ ♀️不同的层
docker build -t app:latest .
dive app:latest 我们可以在每一层中看到与前一层相比进行了哪些更改。首先我们使用命令创建了一个应用程序目录然后复制两个文件。WORKDIR 当前映像的大小为 139 MB。它看起来相当不错但可以进行一些改进以减小其大小。首先要记住的是系统中后续层删除的文件实际上仍然存在于图像中;它们只是在最后一层无法访问。 因此分别安装安全更新和删除现在不必要的文件和包的步骤不会节省任何空间。起作用的是将这两个步骤合二为一。
RUN set -ex \# Create a non-root user addgroup --system --gid 1001 appgroup \ adduser --system --uid 1001 --gid 1001 --no-create-home appuser \# Upgrade the package index and install security upgrades apt-get update \ apt-get upgrade -y \ apt-get autoremove -y \ apt-get clean -y \ rm -rf /var/lib/apt/lists/* 这将图像的大小从 18 mb 减小到 总大小 121 mb 这与我们之前的图层完全相同。apt-get update update-get upgrade -y
五、缓存
好的让我们继续安装依赖项后我们会将我的应用程序需要的一些子目录复制到容器中。接下来是使用 Poetry 安装 python 包
COPY ./artifacts artifacts
COPY ./api apiRUN pip install poetry$POETRY_VERSION \ poetry install --no-root --no-ansi --no-interaction 但是这些命令的顺序有意义吗请记住每个层都是与其下方层独立的增量。每次更改图层时它都会更改其后的每个图层。如果上一层与之前完全相同我们可以只使用缓存的值而不是重建该步骤。
Step 12/18 : COPY ./api api--- Using cache--- ea3ba41d1a13 因此您希望将图层从最不可能更改到最有可能更改进行排序以缩短构建时间。在复制程序的其余部分之前先安装依赖项是有意义的。与应用程序代码相比更新和更改依赖项的可能性通常要小得多。 因此这是一个更好的指令顺序
RUN pip install poetry$POETRY_VERSION \ poetry install --no-root --no-ansi --no-interactionCOPY ./artifacts artifacts
COPY ./api api 下一步是公开一个端口供我们的应用程序侦听。 在 Dockerfile 中更多地用于文档目的指示应用程序在容器中侦听哪些端口。EXPOSE
为了实际公开我们的 FASTAPI 服务器我们运行以下命令
CMD [uvicorn, api.main:app, --host, 0.0.0.0, --port, 8000] 最后我们使用命令设置应用程序将运行的用户。这设置为我们之前创建的用户 .USERappuser
让我们再次构建 docker 镜像并检查大小 映像现在的总大小为 731 MB。531 mb 来自 Poetry 安装的依赖项但 Poetry 本身也占用了一些空间。 尽管 Poetry 在开发阶段对于创建虚拟环境和管理依赖项很有用但在运行 Docker 映像时不需要这些功能因为映像提供了自己的隔离环境并且我们的依赖项已经安装。因此减小 Docker 映像的大小也可以通过确保 Poetry 包不包含在最终映像中来实现。
六、多阶段构建 多阶段构建可用于从最终的 Docker 映像中排除 Poetry因为它可以从单个 Dockerfile 创建多个映像。与直接使用 Poetry 安装依赖项不同Poetry 还可以在构建阶段将必要的依赖项导出到 needs.txt 文件中。此文件可以复制到最后阶段并由 pip 用于安装依赖项。
FROM python:3.11-slim as build. . . RUN pip install poetry$POETRY_VERSION \ poetry install --no-root --no-ansi --no-interaction \ poetry export -f requirements.txt -o requirements.txt### Final stage
FROM python:3.11-slim as finalWORKDIR /appCOPY --frombuild /app/requirements.txt .RUN pip install -r requirements.txt 通过在最后阶段排除诗歌Docker图像的大小减小如从732 MB减少到538 MB 所示。
七、 我们最终得到以下文件
FROM python:3.11-slim as buildENV PIP_DEFAULT_TIMEOUT100 \# Allow statements and log messages to immediately appearPYTHONUNBUFFERED1 \# disable a pip version check to reduce run-time log-spamPIP_DISABLE_PIP_VERSION_CHECK1 \# cache is useless in docker image, so disable to reduce image sizePIP_NO_CACHE_DIR1 \POETRY_VERSION1.3.2WORKDIR /app
COPY pyproject.toml poetry.lock ./RUN pip install poetry$POETRY_VERSION \ poetry install --no-root --no-ansi --no-interaction \ poetry export -f requirements.txt -o requirements.txt### Final stage
FROM python:3.11-slim as finalWORKDIR /appCOPY --frombuild /app/requirements.txt .RUN set -ex \# Create a non-root user addgroup --system --gid 1001 appgroup \ adduser --system --uid 1001 --gid 1001 --no-create-home appuser \# Upgrade the package index and install security upgrades apt-get update \ apt-get upgrade -y \# Install dependencies pip install -r requirements.txt \# Clean up apt-get autoremove -y \ apt-get clean -y \ rm -rf /var/lib/apt/lists/*COPY ./artifacts artifacts
COPY ./api apiEXPOSE 8000CMD [uvicorn, api.main:app, --host, 0.0.0.0, --port, 8000]# Set the user to run the application
USER appuser
八、总结 总之通过在创建 Dockerfile 时遵循这些提示和最佳实践您可以确保最终映像针对安全性、大小和性能进行了优化。 确保选择正确的基础映像了解 Docker 层的不变性按正确的顺序放置说明并遵循安全最佳实践。 如何使您的 Python Docker 镜像安全、快速和小巧 |作者比约恩·范·迪克曼 |华帝人工智能 |中等 (medium.com)