当前位置: 首页 > news >正文

如何使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)

相关文章:

如何使Python Docker镜像安全、快速、小巧

一、说明 在微服务领域,拥有安全、高效和紧凑的 Docker 映像对于成功部署至关重要。本博客将探讨有助于构建此类映像的关键因素,包括不以 root 用户身份运行映像的重要性、在构建映像时更新和升级包、在编写 Dockerfile 指令时考虑 Docker 的层架构&…...

AWS——03篇(AWS之Amazon S3(云中可扩展存储)-01入门)

AWS——03篇(AWS之Amazon S3(云中可扩展存储)-01入门) 1. 前言2. 关于 Amazon S32.1 介绍2.1.1 简述2.1.2 详细介绍 2.2 Amazon S3 好处和功能2.3 3. 创建S3存储桶3.1 创建存储桶3.2 修改访问权限 4. 简单实用4.1 上传图片文件4.2…...

没有synchronized,rust怎么防并发?

学过Java的同学对synchronized肯定不陌生,那么rust里怎么办呢? 在Rust中,可以使用标准库提供的 std::sync::Mutex 来实现加锁功能。Mutex是互斥锁的一种实现,用于保护共享数据在并发访问时的安全性。 下面是一个简单的示例代码&a…...

1.Python简介及安装(3.11.4)

简介 Python 是一种解释型、面向对象、动态数据类型、高级、通用、解释型的高级程序设计语言。 Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。 像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。 官方宣布,…...

face_recognition人脸识别与人脸检测

1、安装face_recognition库 pip install face_recognition face_recognition库的人脸识别是基于业内领先的C开源库dlib中的深度学习模型,安装face_recognition库的同时会一并安装dlib深度学习框架。 2、face_recognition库的使用 1)load_image_file加…...

vue3获得url上的参数值

1、引入 import { useRoute } from vue-router2、获得const route useRoute() console.log(route.query.number)...

chapter15:springboot与监控管理

Spring Boot与监控管理视频 1. 简介 通过引入spring-boot-starter-actuator, 可以使用SpringBoot为我们提供的准生产环境下的应用监控和管理功能。我们可以通过http, jmx, ssh协议来进行操作,自动得到审计、健康及指标信息等。 步骤: 引入spring-boo…...

http历史版本

1,HTTP0.9 最早的http版本,后来才被定义为0.9版本。 这时候通信采用的是纯文本格式; 只支持get请求,且在服务器响应之后就关闭连接; 没有请求头的概念,功能比较简单。 2,HTTP1.0 这个版本增…...

【Go语言】Golang保姆级入门教程 Go初学者chapter2

【Go语言】变量 VSCode插件 setting的首选项 一个程序就是一个世界 变量是程序的基本组成单位 变量的使用步骤 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuxG8imp-1691479164956)(https://cdn.staticaly.com/gh/hudiework/imgmain/image-20…...

关于ETL的两种架构(ETL架构和ELT架构) qt

ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库&#xf…...

【Linux】进程间通信——管道

目录 写在前面的话 什么是进程间通信 为什么要进行进程间通信 进程间通信的本质理解 进程间通信的方式 管道 System V IPC POSIX IPC 管道 什么是管道 匿名管道 什么是匿名管道 匿名管道通信的原理 pipe()的使用 匿名管道通信的特点 拓展代码 命名管道 什么是命…...

Element-plus中tooltip 提示框修改宽度——解决方案

tooltip 提示框修改宽度方法&#xff1a; 在element中&#xff0c;想要设置表格的内容&#xff0c;超出部分隐藏&#xff0c;鼠标悬浮提示 可以在el-table 上添加show-overflow-tooltip属性 同时可以通过tooltip-options配置提示信息 如下图代码 <el-tableshow-overflo…...

java实现当前系统时间格式化

import java.text.SimpleDateFormat; import java.util.Date;public class DateTest {public static void main(String[] args) {Date date new Date();System.out.println("当前系统时间&#xff1a;" date);SimpleDateFormat simpleDateFormat new SimpleDateFo…...

篇十一:享元模式:共享细粒度对象

篇十一&#xff1a;“享元模式&#xff1a;共享细粒度对象” 设计模式是软件开发中的重要工具&#xff0c;享元模式&#xff08;Flyweight Pattern&#xff09;是结构型设计模式的一种。享元模式旨在通过共享细粒度的对象&#xff0c;减少内存消耗和提高性能。在设计模式学习中…...

Dev控件 Gridcontrol,gridview 实现多选功能

在网上看了好多实现dev控件GridControl多选功能的方法&#xff0c;都很麻烦&#xff0c;其实GridControl有一个自带的实现多选功能的控件&#xff0c;很简单。 实现效果如下 无需代码代码&#xff0c;使用GridControl中自带的多选功能&#xff0c;在界面直接设置即可 1.找到要…...

内网穿透:如何通过公网访问本地Web服务器?

文章目录 前言1. 首先安装PHPStudy2.下载一个开源的网页文件3. 选择“创建网站”并将网页内容指向下载好的开源网页文件4. 打开本地网页5. 打开本地cpolar客户端6. 保存隧道设置 生成数据隧道 前言 随着科技进步和时代发展&#xff0c;计算机及互联网已经深深融入我们的生活和…...

在qemu中挂载镜像文件

将镜像文件作为交换分区 创建镜像文件&#xff1a; dd if/dev/zero ofswap.img bs512 count131072 qemu-system-arm -nographic -M vexpress-a9 -m 64M -kernel arch/arm/boot/zImage -append "rdinit/linuxrc consolettyAMA0 loglevel8" -dtb arch/arm/boot/dts/…...

报错注入(主键重复)攻击原理

基本原理 利用数据表中主键不能重复的特点&#xff0c;通过构造重复的主键&#xff0c;使得数据库报错&#xff0c;并将报错结果返回到前端。 SQL说明函数 以pet数据表为例进行说明 rond(): 返回[0,1)区间内的任意浮点数。 count(): 返回每个组的列行数。 如&#xff0…...

Golang基础教程

Golang基础教程 golang简介安装golanggolang开发工具go常用命令golang开发 vscode快捷键如何编写golang代码golang标识符、关键字、命名规则golang变量go语言常量go语言数据类型go语言布尔类型go语言数字类型golang字符串golang格式化输出golang运算符go语言中的流程控制golan…...

ppt压缩文件怎么压缩最小?文件压缩技巧分享

在日常的工作和学习中&#xff0c;难免会遇到PPT太大&#xff0c;需要将其压缩变小的情况&#xff0c;但很多朋友还不知道怎么压缩PPT文件&#xff0c;下面就给大家分享几个简单的方法&#xff0c;分分钟缩小过大的PPT文件。 一、PowerPoint PowerPoint就是微软公司的演示文稿…...

实例033 制作闪烁的窗体

实例说明 Windows系统中&#xff0c;当程序在后台运行时&#xff0c;如果某个窗口的提示信息需要用户浏览&#xff0c;该窗口就会不停的闪烁&#xff0c;这样就会吸引用户的注意。同样&#xff0c;如果在自己的程序中使某个窗口不停的闪烁就会吸引用户的注意。本例设计了一个闪…...

【JavaEE进阶】Spring创建与使用

文章目录 一. 创建 Spring 项目1.1 创建一个Maven项目1.2 添加Spring依赖1.4. 创建一个启动类 二. 将 Bean 对象存放至 Spring 容器中三. 从 Spring 容器中读取到 Bean1. 得到Spring对象2. 通过Spring 对象getBean方法获取到 Bean对象【DI操作】 一. 创建 Spring 项目 接下来使…...

PHP8的循环控制语句-PHP8知识详解

我们在上一节讲的是条件控制语句&#xff0c;本节课程我们讲解循环控制语句。循环控制语句中&#xff0c;主要有for循环、while循环、do...while循环和foreach循环。 在编写代码时&#xff0c;经常需要反复运行同一代码块。我们可以使用循环来执行这样的任务&#xff0c;而不是…...

第八次作业

一&#xff0c;.什么是数据认证&#xff0c;有什么作用&#xff0c;有哪些实现的技术手段? 数据认证是指保证数据的真实性、完整性和可信度&#xff0c;以确保数据不被篡改或伪造。其作用包括但不限于&#xff1a; 保护关键数据不被恶意篡改或损坏 提供数据来源的可靠性和安全…...

LeetCode //C - 290. Word Pattern

290. Word Pattern Given a pattern and a string s, find if s follows the same pattern. Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in s. Example 1: Input: pattern “abba”, s “dog c…...

[保研/考研机试] 括号匹配问题 C++实现

题目描述&#xff1a; 在某个字符串(长度不超过100)中有左括号、右括号和大小写字母&#xff1b;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序&#xff0c;找到无法匹配的左括号和右括号&#xff0c;输出原来的字符串&am…...

springBoot集成caffeine,自定义缓存配置 CacheManager

目录 springboot集成caffeine Maven依赖 配置信息&#xff1a;properties文件 config配置 使用案例 Caffeine定制化配置多个cachemanager springboot集成redis并且定制化配置cachemanager springboot集成caffeine Caffeine是一种基于服务器内存的缓存库。它将数据存储在…...

【瑞吉外卖】Git部分学习

Git简介 Git是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。通过Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库 远程仓库&#xff1a;远程服务器上的Git仓库…...

如何阐述自己做了一个什么样的东西

线上qps2000&#xff0c;主要的性能瓶颈在于出现在数据库I/O上。另外&#xff0c;如果是一个正常部署的容器&#xff0c;qps能达到几百就不错了。资讯服务现在做了静态的底层页&#xff0c;所以热点新闻多数会命中底层页&#xff0c;即便没有命中底层页&#xff0c;也会走多层的…...

TC3XX - MCAL知识点(二十二):QSPI 同步与异步 Mcal配置及代码实战

目录 1、MCAL配置 1.1、配置目标 1.2、同步QSPI配置 1.2.1、SpiGeneral 1.2.2、SpiMaxChannel 1.2.3、SpiMaxJob...

做网站刷东西/营销网店推广的软文

如果存在自增列那就比较麻烦&#xff0c;需要写明需要插入列的具体名称&#xff0c;比较麻烦&#xff0c;可以用下面的语句实现。 --删除主键 ALTER TABLE 表名 DROP constraint 主键约束; --删除ID alter table 表名 drop column ID; --新增ID alter table 表名 add ID in…...

菜鸟教程网站怎么做/简述在线推广网站的方法

这套题还是比较基础的。 首先b题是队友a的&#xff0c;我只是刚读懂题&#xff0c;如果没读错的话&#xff0c;应该就是匹配字符串&#xff0c;如果有一个happiness就输出yes&#xff0c;且输出匹配的位置和下一个位置就行&#xff0c;如果没有happiness就随便输出两个位置就行…...

wordpress 有赞云/打开百度网址

最近想升级mesos0.23.0,结果编译mesos0.23.0需要gcc4.8&#xff0c;可是centOS6.6最高版本的gcc也只到4.4.7版本,只好手动升级一下了。 下载4.8.2源码 wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.bz2 下载依赖(gmp-4.3.2、mpfr-2.4.2、mpc-0.8.1) /us…...

建设网站简单教程/最新新闻事件摘抄

企业需要什么 企业有三个最基本的诉求&#xff1a;降低成本、提高生产效率、提升业务质量&#xff0c;而信息化的系统/软件可以帮助企业有效解决以上三个问题。但企业软件价格昂贵、技术复杂、维护成本太高也是另不少中小型企业望而却步&#xff0c;这时SaaS模式的软件就随着市…...

a0000网站建设/汕头百度推广公司

版本3.2.3 1、数据库操作中的连贯操作table()&#xff0c;在查询的时候可以切换表&#xff0c;但是在插入&#xff0c;更新的时候请不要使用。例如 D(user)->table(auth)->add($data); 操作会出问题&#xff0c;因为插入的时候会把非user表的字段删除 2.数据库操作的crea…...

手机网站和电脑网站/脑白金网络营销

Spire.XLS是一款专业的Excel控件&#xff0c;无需安装微软Excel&#xff0c;也能拥有Excel的全套功能&#xff0c;能够为工厂智能化提供完善的Excel需求。【下载Spire.XLS最新试用版】组合图表是指在同一张图表中包含两种或以上样式的图表&#xff0c;我们在使用Excel分析数据时…...