在Docker容器中保存Django FileField中的文件

3

我有一个带FileField的模型。我的应用程序在使用dockerfile创建的docker容器中运行。当我保存文件时,它保存在本地路径而不是容器基础根目录中。但是当我尝试检索文件并将其作为附件发送电子邮件时,会出现文件未找到错误。媒体根目录基于Dockerfile的基本根目录。该电子邮件是在另一个容器中构建和发送的异步任务。

Dockerfile如下:

# pull official base image
FROM python:3.9.1-alpine

# set work directory
#ENV APP_HOME=/code
#RUN mkdir $APP_HOME
#RUN mkdir $APP_HOME/static
#RUN mkdir $APP_HOME/media
#WORKDIR $APP_HOME
WORKDIR /code

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY requirements.txt /code/

RUN apk --update --upgrade --no-cache add \
    postgresql-libs make gdal-dev geos-dev g++ python3-dev cairo-dev pango-dev gdk-pixbuf-dev ttf-ubuntu-font-family

RUN \
    apk add --virtual .build-deps gcc musl-dev postgresql-dev jpeg-dev zlib-dev libffi-dev && \
    pip3 install --no-cache-dir -r /code/requirements.txt && \
    apk --purge del .build-deps

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# copy project
COPY . /code/

我有一个Docker Compose文件,用于构建镜像和运行容器。它看起来是这样的:

version: "3.9"

services:
  db:
    image: postgis/postgis:13-3.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    # TODO remove ports for production
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=DB
      - POSTGRES_USER=USER
      - POSTGRES_PASSWORD=PW
  api:
    build: .
    image: app/api
    command: python manage.py runserver 0.0.0.0:8000 --settings=api.settings.production
    volumes:
      - .:/code
      - static:/code/static
      - media:/code/media
    ports:
      - "8000:8000"
    env_file:
      - ./.env.dev
    depends_on:
      - db
    entrypoint: /entrypoint.sh
  mail:
    image: app/api
    command: python manage.py qcluster --settings=api.settings.production
    depends_on:
      - api

volumes:
  postgres_data:
  static:
  media:

一个示例模型如下所示:
def order_nested_item_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/orders/user_<id>/<filename>
    user_id = instance.order.user.id if instance.order.user else 'anonymous'
    return f'orders/user_{user_id}/order_{instance.order.id}/{filename}'

class Invoice(TimeStampedModel):
    order = models.ForeignKey(Order, related_name='invoices', on_delete=models.CASCADE)
    number = models.CharField(max_length=100)
    pdf = models.FileField(upload_to=order_nested_item_directory_path)

使用媒体根目录配置:

BASE_DIR = Path(__file__).resolve().parent.parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

有没有人能帮忙解决如何在Dockerfile的根目录下保存文件的问题?


请包括您的设置,特别是媒体、模型、表单和视图的设置。 - markwalker_
我已经包含了设置和模型,这是一个REST API,所以没有表单。 - lando
1个回答

2

我不确定这个方法能否解决你的问题,但如果你想在使用docker-compose时在容器之间共享命名卷中的数据,你需要将这些卷添加到所有这些容器中或使用扩展字段。

由于第一种方法更简单,只需添加:

    volumes:
      - media:/code/media

将您的邮件服务添加到docker-compose中。

之后重新构建您的容器。

然后,当它正在运行时,运行docker exec -it <image id> sh并检查是否存在/code/media


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接