我有2个停靠文件的例子,一个是工作的,另一个是不工作的.两者之间的主要区别是基本图像.

简单的基于python的图像docker文件:

# syntax = docker/dockerfile:experimental
FROM python:3.9-slim-bullseye

RUN apt-get update -qy && apt-get install -qy \
    build-essential tini libsasl2-dev libssl-dev default-libmysqlclient-dev gnutls-bin

RUN pip install poetry==1.1.15
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry config virtualenvs.create false
RUN --mount=type=cache,mode=0777,target=/root/.cache/pypoetry poetry install

Airflow基础图像扩展底座文件:

# syntax = docker/dockerfile:experimental
FROM apache/airflow:2.3.3-python3.9
USER root
RUN apt-get update -qy && apt-get install -qy \
    build-essential tini libsasl2-dev libssl-dev default-libmysqlclient-dev gnutls-bin

USER airflow
RUN pip install poetry==1.1.15
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry config virtualenvs.create false
RUN poetry config cache-dir /opt/airflow/.cache/pypoetry
RUN --mount=type=cache,uid=50000,mode=0777,target=/opt/airflow/.cache/pypoetry poetry install

在构建docker文件之前,在与pyproject.toml文件相同的文件夹中运行poetry lock

pyproject.toml个文件:pyproject.toml个文件:

[tool.poetry]
name = "Airflow-test"
version = "0.1.0"
description = ""
authors = ["Lorem ipsum"]

[tool.poetry.dependencies]
python = "~3.9"
apache-airflow = { version = "2.3.3", extras = ["amazon", "crypto", "celery", "postgres", "hive", "jdbc", "mysql", "ssh", "slack", "statsd"] }
prometheus_client = "^0.8.0"
isodate = "0.6.1"
dacite = "1.6.0"
sqlparse = "^0.3.1"
python3-openid = "^3.1.0"
flask-appbuilder = ">=3.4.3"
alembic = ">=1.7.7"
apache-airflow-providers-google = "^8.1.0"
apache-airflow-providers-databricks = "^3.0.0"
apache-airflow-providers-amazon = "^4.0.0"
pendulum = "^2.1.2"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

为了构建映像,这是我使用的命令:

DOCKER_BUILDKIT=1 docker build --progress=plain -t airflow-test -f Dockerfile . 

对于这两个映像,它们第一次构建时,poetry install将需要下载所有依赖项.有趣的是,在我第二次构建该映像时,由于依赖项已被缓存,因此基于Python的映像速度要快得多,但基于Airflow的映像将再次try 下载所有200个依赖项. 根据O通过指定--mount=type=cache了解到的情况,该目录将存储在映像存储库中,以便下次构建映像时可以重用.通过此操作可以修剪最终图像的大小.

在运行映像时,依赖关系是如何显示的?如果我运行docker run -it --user 50000 --entrypoint /bin/bash image,一个简单的Python导入将在气流图像上工作,但不会在Python图像上工作.何时以及如何将依赖项重新附加到映像?

如果你想试一试,这里有一个虚拟项目,可以在本地克隆并玩耍: https://github.com/ioangrozea/Docker-dummy

推荐答案

也许它没有直接回答这个问题,但我认为你试图做的事情从一开始就没有什么意义,所以我建议你彻底改变方法,特别是你试图实现的目标在Airflow官方图像文件中描述得很好,包括许多可供参考的例子.如果你按照官方文档go 做,你想要达到的效果(无论你多么努力)最终都会比你所能达到的效果大200 MB以上(至少20%).

使用诗歌来构建这种形象没有什么意义,也不推荐使用诗歌(在这种情况下,绝对没有必要使用诗歌).

参见 comments here.

虽然使用其他工具也取得了一些成功,如诗歌或 Pip-工具,它们不共享与pip相同的工作流程--尤其是 当涉及到约束与需求管理时.正在安装 当前不支持通过诗歌或pip工具.如果你愿意的话 使用这些工具安装气流您应该使用约束和 将它们转换为您的工具所需的适当格式和工作流 需要.

POLITE和pip有完全不同的依赖关系解决方法,虽然POLITE是一个很酷的工具来管理小项目的依赖关系,我真的很喜欢POLITE,但他们坚持不同地对待库和应用程序的 Select ,使得它不适合管理Airflow的依赖关系,因为Airflow既是要安装的应用程序,也是开发人员要在其上构建的库,并且Pory的限制根本不适用于Airflow.

我在go 年发表的talk篇文章中详细解释了这一点,如果你对"为什么"感兴趣,你可以看到它.

那么,如何解决你的问题呢?在这种情况下,不要使用--mount-type缓存和诗歌.使用多段图像的apache 气流和"定制"选项,而不是"扩展"图像.这将给您带来更多的节省--因为您不会将"构建要素"添加到最终的映像中(它们本身会增加大约200 MB的映像大小,消除它们的唯一方法是将您的映像分成两个部分--一个是具有"构建要素"并允许您构建Python包的部分,另一个是您用作"运行时"的部分,其中您只复制"构建"的python库.

这正是Airfow官方Python镜像所采用的方法-它针对重建的大小和速度进行了高度优化,虽然其内部相当复杂,但实际构建高度优化的、完全定制的镜像就像下载Airflow Dockerfile并运行正确的docker buildx build . --build-arg ... --build-arg ... 命令一样简单-Airflow Dockerfile将为您做所有的优化-导致图像尽可能小,而且它还允许您重复使用构建缓存-特别是如果您使用构建套件-这是一种现代的、灵活的和非常优化的构建镜像的方式(Airflow Dockerfile需要构建套件从Airflow 2.3开始).

你可以看到关于如何构建定制映像here的所有细节-在那里你有大量的例子和解释为什么它工作,它的工作方式,以及你可以得到什么样的优化.有一些关于如何添加依赖项、Python包等的例子.虽然这很复杂,但您似乎在处理您的图像时做了一些复杂的事情,这就是为什么我建议您遵循这条路由.

此外,如果你对其他部分的推理感兴趣,为什么它是有意义的,你可以观看我的talk从气流峰会2020-虽然演讲是在两年前进行的,一些小细节发生了变化,但关于如何以及为什么我们在气流中建立形象的解释仍然非常有效.自从演讲结束后,事情变得更简单了(即你唯一不需要的东西是Dockerfile,不需要完整的气流源),你需要使用Buildkit-然而所有其他的东西都保持不变.

Python相关问答推荐

Tkinter滑动条标签.我不确定如何删除滑动块标签或更改其文本

实现的差异取决于计算出的表达是直接返回还是首先存储在变量中然后返回

如何使用stride_tricks.as_strided逆转NumPy数组

列表上值总和最多为K(以O(log n))的最大元素数

提取两行之间的标题的常规表达

如何在BeautifulSoup中链接Find()方法并处理无?

使用FASTCGI在IIS上运行Django频道

如何删除索引过go 的lexsort深度可能会影响性能?' &>

运行Python脚本时,用作命令行参数的SON文本

无法通过python-jira访问jira工作日志(log)中的 comments

如何记录脚本输出

如何使用Python以编程方式判断和检索Angular网站的动态内容?

从Windows Python脚本在WSL上运行Linux应用程序

在极中解析带有数字和SI前缀的字符串

(Python/Pandas)基于列中非缺失值的子集DataFrame

如何按row_id/row_number过滤数据帧

你能把函数的返回类型用作其他地方的类型吗?'

ModuleNotFoundError:Python中没有名为google的模块''

Django.core.exceptions.SynchronousOnlyOperation您不能从异步上下文中调用它-请使用线程或SYNC_TO_ASYNC

如何在Python中从html页面中提取html链接?