我想提前道歉,我没有具体的代码示例可以分享(尽管我在下面包含了我的 docker-compose 文件,它可能有帮助,也可能没有帮助)。我遇到了一个奇怪的问题,我似乎无法追踪,并且我不能 100% 确定要分享什么。
我有一个在 Docker 中运行的 django + celery 设置(基于 cookiecutter-django)。一开始一切似乎都很顺利。我在 Docker 之外进行了广泛的测试和使用此设置,并且 Docker 化的 Celery 任务通常按照我的预期运行(即,与未 Docker 化时的行为一样)。
但这就是事情变得奇怪的地方。由于各种原因,我需要加载一些数据文件并在运行时创建临时文件,而我不能将其放入 docker 文件中。一个例子是使用 NamedTemporaryFile。另一个是安装 Spacy 中的数据文件。 。在这两种情况下,我的脚本都将数据存储到/tmp (我知道这里简单的答案是将它们放入我的 docker 文件中,但遗憾的是我无法提前预测我需要哪些文件)。当我的 celery 任务工作人员尝试访问它应该创建、下载和/或存储到/tmp 的数据文件时,我不断收到文件未找到错误。奇怪的是我的日志中没有收到任何文件创建或下载失败的错误...
但是,当我/bin/bash 进入我的 celeryworker 容器并 cd 到/tmp 目录时,果然,那里没有文件...如果在我的容器中使用 python 控制台,我运行相同的命令 代码,我没有任何问题,文件确实显示在/tmp 中。我没有收到一致的错误消息,并且该行为在不同的脚本中表现不同,因此很难为您提供特定的错误消息/堆栈跟踪。公共(public)元素似乎源于当我的 celery 任务尝试在/tmp 中动态存储数据然后立即访问它时出现的一些问题。我是 Docker 新手,不知道下一步该做什么。我怀疑这可能是一个权限问题,但我尝试将/tmp 更改为 777,但没有解决任何问题。我还认为这可能是一个体积问题,但是,如果是这样的话,我不确定为什么如果我在容器内使用 bash 就可以让一切正常工作。
有人有什么建议吗?花了几天时间试图追踪问题的根源,但现在陷入了死胡同。我的 docker 文件和配置几乎是 Django Cookiecutter 默认值的普通副本。
version: '3'
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
services:
django: &django
build:
context: .
dockerfile: ./compose/local/django/Dockerfile
image: gremlin_gplv3_local_django
container_name: django
depends_on:
- postgres
- tika
- redis
volumes:
- .:/app
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
ports:
- "8000:8000"
command: /start
postgres:
build:
context: .
dockerfile: ./compose/production/postgres/Dockerfile
image: gremlin_gplv3_production_postgres
container_name: postgres
volumes:
- local_postgres_data:/var/lib/postgresql/data
- local_postgres_data_backups:/backups
env_file:
- ./.envs/.local/.postgres
redis:
image: redis:5.0
container_name: redis
celeryworker:
<<: *django
image: gremlin_gplv3_local_celeryworker
container_name: celeryworker
depends_on:
- redis
- postgres
ports: []
command: /start-celeryworker
celerybeat:
<<: *django
image: gremlin_gplv3_local_celerybeat
container_name: celerybeat
depends_on:
- redis
- postgres
ports: []
command: /start-celerybeat
flower:
<<: *django
image: gremlin_gplv3_local_flower
container_name: flower
ports:
- "5555:5555"
command: /start-flower
tika:
image: lexpredict/tika-server
command: /start-tika
最佳答案
我想通了……嗯,主要是。问题是 Spacy(以及其他类似的下载数据文件的库和工具)将它们放入文件系统上的本地目录中,并可能创建指向它们的符号链接(symbolic link))。然而,在 Docker 容器中,这些文件和符号链接(symbolic link)不是持久的,除非父目录位于 Docker 卷中。
我最终做的是为 Spacy(或任何库)用来存储数据文件/库的文件夹创建 docker 卷。就我而言,Spacy 总是通过 Celery 调用,Celery 在我的 docker-compose 堆栈中拥有自己的 docker 镜像,因此我需要将每个 Spacy 数据目录的卷附加到我的 celeryworker,如下所示:
version: '3'
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
worker_usr: {}
worker_root: {}
worker_tmp: {}
services:
[...]
celeryworker:
<<: *django
image: local_django:latest
container_name: celeryworker
depends_on:
- redis
- postgres
volumes:
- worker_usr:/usr
- worker_tmp:/tmp
- worker_root:/root
- .:/app
ports: []
command: /start-celeryworker
综上所述,我注意到在某些情况下,第一次在我的工作容器中安装数据文件(如 Spacy 模型)会引发错误,表明数据文件仍然无法访问,但,当发生这种情况时(并非总是如此),我可以再次运行安装,99% 的情况下,这似乎可以解决问题。我没有时间尝试解决这个问题。也许其他人可以解决这个问题。
关于python - Docker 化的 Python 脚本在访问存储到/tmp 的文件时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62057053/