I have a model with a FileField. My application is running in a docker container created with a dockerfile. When I save a file it is saved on my local path instead of the containers base root. But when I try to retrieve the file and send it as attachment in an email I get a file not found error. The media root directory is based on the Dockerfile's base root. The email is built and sent in another container as an async task. The Dockerfile looks like this:
# 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/
I have a docker-compose file to build the image and run the container. It looks like that:
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:
An example model looks like this:
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)
with media root settings:
BASE_DIR = Path(__file__).resolve().parent.parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Anyone can help how to save the files in the Dockerfile's base root?