I need to launch my site in production, so I decided to do it with Docker container(at first time, newbie there) with Postgres, nginx and Django, everything is working inside a container, but on launched site I have in console 404 error with static and media. I did a research, but still haven't found the answer for my case. Could somebody advise what I need to fix there?
There is my Dockerfile
###########
# BUILDER #
###########
# pull official base image
FROM python:3.9.6-alpine as builder
# set work directory
WORKDIR /usr/src/my_shop
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install psycopg2 and Pillow dependencies
RUN apk update \
&& apk add postgresql-dev gcc python3-dev musl-dev jpeg-dev zlib-dev
# && pip install Pillow
# lint
RUN pip install --upgrade pip
RUN apk add build-base python3-dev py-pip jpeg-dev zlib-dev
ENV LIBRARY_PATH=/lib:/usr/lib
# install dependencies
COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/my_shop/wheels -r requirements.txt
#########
# FINAL #
#########
# pull official base image
FROM python:3.9.6-alpine
# create directory for the app user
RUN mkdir -p /home/app
# create the app user
RUN addgroup -S app && adduser -S app -G app
# create the appropriate directories
ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
WORKDIR $APP_HOME
# install dependencies
RUN apk update && apk add libpq gcc python3-dev musl-dev jpeg-dev zlib-dev \
&& pip install --no-cache-dir Pillow
COPY --from=builder /usr/src/my_shop/wheels /wheels
COPY --from=builder /usr/src/my_shop/requirements.txt .
RUN pip install --no-cache /wheels/*
# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
RUN chmod +x $APP_HOME/entrypoint.prod.sh
# copy project
COPY . $APP_HOME
# chown all the files to the app user
RUN chown -R app:app $APP_HOME
# change to the app user
USER app
# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
There is docker-compose.yml
version: '3.8'
services:
web:
build:
context: ./
dockerfile: Dockerfile.prod
command: gunicorn shop.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
ports:
- 8000:8000
env_file:
- ./.env.prod
depends_on:
- db
db:
image: postgres:13.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env.prod.db
nginx:
build: ./nginx
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
ports:
- "80:80"
depends_on:
- web
volumes:
postgres_data:
static_volume:
media_volume:
and there is nginx settings:
upstream shop {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://shop;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /home/app/web/staticfiles/;
}
location /media/ {
alias /home/app/web/mediafiles/;
}
}
What I have in settings.py
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / "mediafiles"
Dockerfile for nginx
FROM nginx:1.21-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
And of course after container launching I did:
docker-compose -f docker-compose.prod.yml exec web python manage.py migrate --noinput
and then
docker-compose -f docker-compose.prod.yml exec web python manage.py collectstatic --no-input --clear
I did it according to this instruction with some fixes https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/