python - Docker 化的 Python 脚本在访问存储到/tmp 的文件时出现问题

标签 python django docker celery spacy

我想提前道歉,我没有具体的代码示例可以分享(尽管我在下面包含了我的 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/

相关文章:

python - 如何为每个月做子图?

Python:在新终端中打开程序 [Linux]

python - 根据 file.txt pandas 中的模式匹配对数据框进行子集化

python - Flask 应用程序搜索栏

MySQL 转义一切(所有特殊字符)

javascript - 在 js 文件中找不到 Django、Ajax url

docker - GCP Cloud 构建密码到 docker arg

python - Django:如何使用 @property 在模型中设置属性

Docker 命令返回 "invalid reference format"

node.js - 如何在两个docker服务之间实现负载均衡?