如何使Python 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映像(python:3.11)包括运行应用程序不需要的额外开发工具和文档,使其更大,大小为875 MB,比苗条版本😱大约7倍

        另一种选择是Alpine(python:3.11-alpine),它更小,大小为56.5 MB。但是,它缺少软件包安装程序 pip 和对安装轮子包的支持,这两者都是安装 Pandas 和 Numpy 等应用程序所必需的。若要安装这些应用程序,需要使用 G++ 等编译器包从源文件编译它们,默认情况下也不会在 Alpine 映像上安装这些包。这导致图像尺寸比苗条版本更大(和麻烦得多),所以让我们继续那个。

ENV PIP_DEFAULT_TIMEOUT=100 \# Allow statements and log messages to immediately appearPYTHONUNBUFFERED=1 \# disable a pip version check to reduce run-time & log-spamPIP_DISABLE_PIP_VERSION_CHECK=1 \# cache is useless in docker image, so disable to reduce image sizePIP_NO_CACHE_DIR=1ARG POETRY_VERSION=1.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 --from=build /app/requirements.txt .RUN pip install -r requirements.txt

        通过在最后阶段排除诗歌,Docker图像的大小减小,如从732 MB减少到538 MB 🎉🍾所示。

七、👇 我们最终得到以下文件:

FROM python:3.11-slim as buildENV PIP_DEFAULT_TIMEOUT=100 \# Allow statements and log messages to immediately appearPYTHONUNBUFFERED=1 \# disable a pip version check to reduce run-time & log-spamPIP_DISABLE_PIP_VERSION_CHECK=1 \# cache is useless in docker image, so disable to reduce image sizePIP_NO_CACHE_DIR=1 \POETRY_VERSION=1.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 --from=build /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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/82887.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测 桥梁作为交通运输的重要节点,其安全性一直备受关注。不同于其他建筑物,桥梁所处的环境复杂多变,同时,其所需承受的负荷也相对较大,这就需要对桥梁的安全进…

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases,下载最新版安装文件,例如,3.1.6.1 版&#…

常见分布式ID解决方案总结:数据库、算法、开源组件

常见分布式ID解决方案总结 分布式ID分布式ID方案之数据库数据库主键自增数据库号段模式Redis自增MongoDB 分布式ID方案之算法UUIDSnowflake(雪花算法) 雪花算法的使用IdWorker工具类配置分布式ID生成器 分布式ID方案之开源组件uid- generator(百度)Tinyid(滴滴&…

基于Java的体育网站的设计与实现(论文+源码)_kaic

基于Java的体育网站的设计与实现 摘 要:在网络应用的迅速发展与科技的不断进步的现代环境下,人们生活节奏越来越快,娱乐方式也多种多样,各种软件应用,各种娱乐,购物网站已经成为必不可少的伴随品&#xff…

《24海南大学835软件工程考研经验贴》

1.经验之谈 首先,我是一个二战的考生,一战给我带来的经验有几点。第一,数学、专业课这两门越早复习越好,越拖到后面你就会发现来不及了,这学不完,那学不完的。第二、我认为是比较关键的一点,一定…

Idea创建maven管理的web项目

如果你想在项目中添加一个传统的 src 目录来存放源代码,可以按照以下步骤操作: 1. 在项目视图中,右键单击项目名称,选择 “New” -> “Directory”。 2. 在弹出的对话框中,输入目录名称为 “src”,然后…

使用ffmpeg将m4a及wav等文件转换为MP3格式

要使用ffmpeg将m4a及wav等文件转换为MP3格式,您可以按照以下步骤进行操作: 安装 ffmpeg 确保您已经安装了ffmpeg软件。如果没有安装,请访问ffmpeg的官方网站https://ffmpeg.org/ 并按照说明进行安装。 Win10 / Win11 可以通过 winget 命令…

Vue自定义指令使用

本篇文章讲述使用Vue自定义指令,并在项目中完成相应功能。 在平常Vue脚手架项目中,使用到 自定义指令较少,一般都是使用的自带指令,比如 v-show 、v-if 、 v-for 、 v-bind 之类的。这些已经能够满足大多数项目使用。更多的可能也…

蚁剑antSword-maste下载-安装-使用-一句话木马

下载 https://github.com/AntSwordProject/antSword 一句话木马 hack.php脚本 <?php eval($_POST[attack]);?> 安装 1、安装完成后启动 2、初始化&#xff0c;选择有源码的目录 3、连接

SpringMVC的架构有什么优势?——视图与模型(二)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

c语言每日一练(2)

前言&#xff1a; 每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;暑假时三天之内必有一更&#xff0c;到了开学之后&#xff0c;将看学业情…

leetcode 63. 不同路径 II

2023.8.9 这题是不同路径I的升级版&#xff0c;在路径上增加了障碍物&#xff0c;有障碍物的地方无法通过。 我的思路依然还是使用动态规划&#xff0c;dp[i][j]的含义依然是到&#xff08;i&#xff0c;j&#xff09;这个位置的路径个数。只需要在dp数组中将有障碍物的地方赋为…

js案例:1.简单计算器

目录 一.效果图 二.实现思路 整体思路 ​ 1.关键是dom操作 ​ 2.设置点击事件 3.数据类型的隐式转换和赋值 三.完整代码 一.效果图 二.实现思路 整体思路 1.关键是dom操作 通过 document.getElementById(id) 获取html中的dom元素 每一个html标签都是一个对象&…

CANoe通过Frame Histogram窗口统计报文周期(方便快捷)

文章目录 效果展示1.插入Frame Histogram窗口2.Activate3.运行CANoe&#xff0c;停止后查看write窗口 效果展示 统计报文周期信息输出在write窗口。 1.插入Frame Histogram窗口 2.Activate 3.运行CANoe&#xff0c;停止后查看write窗口 统计报文周期信息输出在write窗口。

Pytorch深度学习-----神经网络模型的保存与加载(VGG16模型)

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…

数据结构刷题训练——链表篇(一)

目录 前言 题目一&#xff1a;链表的中间节点 思路 分析 题解 题目二&#xff1a;链表中倒数第k个结点 思路 分析 题解 题目三&#xff1a;合并两个有序链表 思路 分析 题解 方法二 题解 题目四&#xff1a;链表的回文结构 思路 分析 题解 总结 前言 今天我将开…

2023华数杯C题总结

前言 对这次比赛中遇到的问题和卡住的思路进行复盘&#xff0c;整理相关心得&#xff0c;供以后比赛参考 &#x1f9e1;1.认识数据类型&#x1f9e1; 连续变量&#xff1a;母亲年龄、妊娠时间、CBTS、EPDS、HADS、整晚睡醒时间、婴儿年龄 无序分类变量&#xff1a;婚姻状态、…

Gpt微信小程序搭建的前后端流程 - 前端小程序部分-2.确定交互所需的后端API(二)

Gpt微信小程序搭建的前后端流程 - 前端小程序部分-2.确定交互所需的后端API(二) 参考微信小程序-小柠AI智能聊天&#xff0c;可自行先体验。 根据上一节的小程序静态页面设计&#xff0c;需要从后端获取数据的主要4个点&#xff1a; 登录流程&#xff1b;获取今日已提问次数&a…

Unity制作护盾——2、力场冲击波护盾

Unity制作力场护盾 大家好&#xff0c;我是阿赵。   继续做护盾&#xff0c;这一期做一个力场冲击波护盾。 一、效果展示 主要的效果并不是这个球&#xff0c;而是护盾在被攻击的时候&#xff0c;会出现一个扩散的冲击波。比如上图在右边出现了冲击波 如果在左边被攻击&am…

MongoDB 6.0.8 安装配置

一、前言 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 将数据存储为一个文档&#xff0c;数据结构由键值(key>value…