简体   繁体   中英

Dockerizing django, postgres, gunicorn, ngnix - only admin static works, other 404

As in topic. I have tried to apply solutions I found in internet, but no success:( I am pretty new to programming and as making an app is one thing, deploying it just overwhelmed me. I have managed to put it on server, run it on docker with SSL, but main problem is that only admin static files load, other give 404 error. Weird thing is that static subdirectories structure is kept, but there are no files inside. Please help me, I am really stuck:( If you require any other data, please write

Note that neither STATIC_ROOT or STATIC_DIRS work (in some cases changing it helped, not here).

Thank you very much in advance

EDIT: I have no idea why, but files exist in /home/app/web/staticfiles Before I used this directory for static. Could sb explain what is going on?

Directory structure:

├── app
│   ├── Dockerfile.prod
│   ├── entrypoint.prod.sh
│   ├── manage.py
│   ├── requirements.txt
│   ├── sancor
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   ├── settings.py
│   │   ├── urls.py
│   │   ├── views.py
│   │   └── wsgi.py
│   ├── static
│   │   ├── css
│   │   ├── favicon.ico
│   │   ├── fonts
│   │   ├── js
│   │   ├── less
│   │   ├── sancor
│   │   │   ├── css
│   │   │   └── js
│   │   └── scss
├── docker-compose.staging.yml
├── env
└── nginx
    ├── custom.conf
    ├── Dockerfile
    ├── nginx.conf.old
    └── vhost.d
        └── default

app/Dockerfile:

###########
# BUILDER #
###########

# pull official base image
FROM python:3.8.3-alpine as builder

# set work directory
WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev

# lint
RUN pip install --upgrade pip
#RUN pip install flake8
COPY . .
#RUN flake8 --ignore=E501,F401 .

# install dependencies
COPY ./requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt


#########
# FINAL #
#########

# pull official base image
FROM python:3.8.3-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/static
WORKDIR $APP_HOME

# install dependencies
RUN apk update && apk add libpq
COPY --from=builder /usr/src/app/wheels /wheels
COPY --from=builder /usr/src/app/requirements.txt .
RUN pip install --no-cache /wheels/*

# copy entrypoint-prod.sh
COPY ./entrypoint.prod.sh $APP_HOME

# 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"]

app/entrypoint.sh:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started succesfully"
fi

exec "$@"

app/sancor/settings.py:

from pathlib import Path
import os

BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')

SECRET_KEY = os.environ.get("SECRET_KEY")

DEBUG = False

ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")

# template context processor
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
)

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bootstrap4',
    'tempus_dominus',
    'crispy_forms',
    'django_filters',
    'accounts',
    'pacjenci',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'sancor.urls'

# Static files (CSS, JavaScript, Images)
STATIC_URL = '/static/'
STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [STATIC_DIR,]
#STATIC_ROOT = os.path.join(BASE_DIR, "static") 

LOGIN_REDIRECT_URL = 'test'
LOGOUT_REDIRECT_URL = 'thanks'

TEMPUS_DOMINUS_LOCALIZE = 'True'

CRISPY_TEMPLATE_PACK = 'bootstrap'

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

docker-compose.staging.yml:

version: '3.7'

services:
  web:
    build:
      context: ./app
      dockerfile: Dockerfile.prod
    command: gunicorn sancor.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/home/app/web/static
      - media_volume:/home/app/web/mediafiles
    expose:
      - 8000
    env_file:
      - ./.env.staging
    depends_on:
      - db

  db:
    image: postgres:12.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.staging.db
  
  nginx-proxy:
    container_name: nginx-proxy
    build: ./nginx
    restart: always
    ports:
      - 443:443
      - 80:80
    volumes:
      - static_volume:/home/app/web/static
      - media_volume:/home/app/web/mediafiles
      - certs:/etc/nginx/certs
      - html:/usr/share/nginx/html
      - vhost:/etc/nginx/vhost.d
      - /var/run/docker.sock:/tmp/docker.sock:ro
    depends_on:
      - web

  nginx-proxy-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    env_file:
      - ./.env.staging.proxy-companion
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - certs:/etc/nginx/certs
      - html:/usr/share/nginx/html
      - vhost:/etc/nginx/vhost.d
      - acme:/etc/acme.sh
    depends_on:
      - nginx-proxy

volumes:
  postgres_data:
  static_volume:
  media_volume:
  certs:
  html:
  vhost:
  acme:

Please have a look at these answers: dockerizing django , configuring static files

There is no STATIC_DIR option, it's STATIC_ROOT

STATICFILES_DIRS = [STATIC_DIR,] - pointless setting. STATICFILES_DIRS are folders where from files would be collected to STATIC_ROOT during collectstatic . Listing destination folder in the list of source folders to be delivered to the destination folder makes not much sense.

DEBUG = False is of no use (in case if you're trying to fix static files with it) since nginx would handle static urls.

Consider storing all the files inside images/containers out of any user home folder - it may lead to security issues. Put them somewhere /var/opt whatever you choose and give appropriate permissions to the user. And restrict permissions to others.

static_volume:/home/app/web/static - does nginx image know anything about user "app"? is it running under "app"?

Also please check/share nginx.conf

static subdirectories structure is kept, but there are no files inside check.dockerignore.

If I'm not mistaken you're trying to collectstatic files first, them build docker image containting those files and share them via virtual volume. It is a common scenario to avoid including static files into a django app docker image. Currently to update any of them you would have to rebuild and redeploy the whole image, restart container. Consider building image without static files, collecting them separately, delivering to the folder as "just files" and mapping containers to a real shared folder (actually only nginx would need them).

Even if you choose to stay with current concept, note that when you map files to nginx there is absolutely no need to stick to the home/app . Nginx has it's own config, it does not have to respect "whatever settings.py" configs. Nginx maps whatever location to whatever alias/root folder. So when attaching a volume to nginx container you are free to choose any target folder name (place) you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM