Django cannot serve files after moving to compose - django

Context
Hi, we have a big project in Django. Up until now, we have used Vagrant to run it. Now, we have decided to move to a container and use docker compose. Everything has worked out fine except for the serving of static files. We have a directory called web where we have all our static assets. Inside there, there are more subdirectories with more static assets.
Problem
Right now static files are not being served. Is curious because only some files are being served. I think the ones from the web directory are not working for some reason.
Current django config
This config has worked well before moving to docker.
# this is necessary because our settings file are stored inside a directoy
PROJECT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
PUBLIC_DIR = os.path.join(PROJECT_DIR, 'public')
STATIC_ROOT = os.path.join(PUBLIC_DIR, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, 'web'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
Additional information
We are using django-1.11 and python 3.6.9. I know, it's not the latest.
Compose configuration
version: '3'
services:
web:
image: "dev"
container_name: web
ports:
- "8000:8000"
volumes:
- ./:/app
depends_on:
- db
networks:
- djangonetwork
db:
image: "postgres"
container_name: db
ports:
- "5432:5432"
networks:
- djangonetwork
networks:
djangonetwork:
driver: bridge
Any idea about what could be the problem?

Related

django-environ and Postgres environment for docker

I am using django-environ package for my Django project.
I provided the DB url in the .env file, which looks like this:
DATABASE_URL=psql://dbuser:dbpassword#dbhost:dbport/dbname
My DB settings in settings.py:
DATABASES = {
"default": env.db(),
}
So far, I have no issues.
Then, I created a docker-compose.yml where I specified that my project uses Postgres database, i.e.:
version: '3.8'
services:
...
db
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=???
- POSTGRES_PASSWORD=???
- POSTGRES_DB=???
- "POSTGRES_HOST_AUTH_METHOD=trust"
Now I am confused a little.
How do I provide these POSTGRES_* env. variables there? Do I need to provide them as separate variables alongside with the DATABASE_URL in my .env file? If yes, what's the best way do accomplish this? I aim to avoid duplication in my settings.
You can use variable expansion in your .env file. Something like
DB_NAME=dbname
DB_USER=dbuser
DB_PASSWORD=dbpassword
DATABASE_URL=psql://$DB_USER:$DB_PASSWORD#dbhost:dbport/$DB_NAME
and then something like this in your compose file
services:
postgresdb:
container_name: projectname_db
image: postgres:15
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- "127.0.0.1:5432:5432"
...
I am not exactly familiar with django-environ but this should work

How to deploy django based website running on a docker compose to my local home network?

I have the following setup:
docker-compose.yml
# Mentioning which format of dockerfile
version: "3.9"
# services or nicknamed the container
services:
# web service for the web
web:
# you should use the --build flag for every node package added
build: .
# Add additional commands for webpack to 'watch for changes and bundle it to production'
command: python manage.py runserver 0.0.0.0:8000
volumes:
- type: bind
source: .
target: /code
ports:
- "8000:8000"
depends_on:
- db
environment:
- "DJANGO_SECRET_KEY=django-insecure-m#x2vcrd_2un!9b4la%^)ou&hcib&nc9fvqn0s23z%i1e5))6&"
- "DJANGO_DEBUG=True"
expose:
- 8000
db:
image: postgres:13
#
volumes:
- postgres_data:/var/lib/postgresql/data/
# unsure of what this environment means.
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
# - "POSTGRES_USER=postgres"
# Volumes set up
volumes:
postgres_data:
and a settings file as
ALLOWED_HOSTS = ['0.0.0.0', 'localhost', '127.0.0.1']
#127.0.0.1 is my localhost address.
With my host's IP as 192.168.0.214
Can you please help me deploy the django site on my host's local network?
Do I have to set up something on my router?
Or could you direct me towards resources(understanding networking) which will help me understand the same.

Docker - Media volume not storing data [duplicate]

App Description
I have an app with django-gunicorn for back-end and reactjs-nginx with front-end all containerized as well as hosted on aws ec2 instance.
Problem
On development environment, media files are being saved in the 'media' directory permanently. Tho, those files are only saved on the current running docker container on production time. As a result, the files will be removed when I rebuild/stopped the container for a new code push.
Expectation
I wanted to store the file on the 'media' folder for permanent use.
Important code
settings.py
ENV_PATH = Path(__file__).resolve().parent.parent
STATIC_ROOT = BASE_DIR / 'django_static'
STATIC_URL = '/django_static/'
MEDIA_ROOT = BASE_DIR / 'media/'
MEDIA_URL = '/media/'
docker-compose-production.yml
version: "3.3"
services:
db:
image: postgres
restart: always #Prevent postgres from stopping the container
volumes:
- ./data/db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- 5432:5432
nginx:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
ports:
- 80:80
- 443:443
volumes:
- static_volume:/code/backend/server/django_static
- ./docker/nginx/production:/etc/nginx/conf.d
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot
depends_on:
- backend
# Volume for certificate renewal
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
backend:
restart: unless-stopped
build:
context: .
dockerfile: ./docker/backend/Dockerfile
entrypoint: /code/docker/backend/wsgi-entrypoint.sh
volumes:
- .:/code
- static_volume:/code/backend/server/django_static
expose:
- 8000
depends_on:
- db
volumes:
static_volume: { }
pgdata: { }
I finally figured out the issue. I forgot to add .:/code to my nginx volumes config in my docker-compose file. Thank to this answer
Updated nginx volumes confi
volumes:
- .:/code
- static_volume:/code/backend/server/django_static
- ./docker/nginx/production:/etc/nginx/conf.d
- ./docker/nginx/certbot/conf:/etc/letsencrypt
- ./docker/nginx/certbot/www:/var/www/certbot

Permission denied, cannot open static files, Docker, Django

I am new in docker, I want dockerize my django application to production.
My OS: Ubuntu 20.04.1 LTS,
Docker version 20.10.5, build 55c4c88,
My docker-compose.yml file as below:
version: '3.1'
services:
nginx-proxy:
image: jwilder/nginx-proxy
restart: "always"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/vhost/:/etc/nginx/vhost.d:ro
- ./nginx/conf.d/client_max_body_size.conf:/etc/nginx/conf.d/client_max_body_size.conf:ro
- ./static/:/amd/static
- ./media/:/amd/media
postgres:
image: postgres:9.6.6
restart: always
volumes:
- ./pgdb/:/var/lib/postgresql/
ports:
- "5432:5432"
env_file: ./.env
redis:
image: redis
ports:
- 6379:6379
restart: always
web:
container_name: amd
build: .
restart: "always"
ports:
- "8000:8000"
volumes:
- .:/code/
# - ./static/:/code/static
# - ./media/:/code/media
depends_on:
- "postgres"
env_file: .env
celery:
build:
context: .
dockerfile: celery.dockerfile
volumes:
- .:/code
command: celery -A amdtelecom worker -l info
links:
- redis
- postgres
depends_on:
- "redis"
- "postgres"
env_file: ./.env
networks:
default:
external:
name: nginx-proxy
My Dockerfile as below:
FROM python:3.7
ENV PYTHONUNBUFFERED 1
ENV DEBUG False
COPY requirements.txt /code/requirements.txt
WORKDIR /code
RUN pip install -r requirements.txt
ADD . .
CMD [ "gunicorn", "--bind", "0.0.0.0", "-p", "8000", "amdtelecom.wsgi" ]
in my project setting file:
CORS_ALLOWED_ORIGINS = [
"http://localhost:8000",
"http://127.0.0.1:8000",
"http://localhost"
]
STATIC_URL = '/static/'
if PROD:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
else:
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
BASE_DIR / "static",
]
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"
SITE_URL = 'http://localhost:80'
I use the below steps in my terminal:
docker-compose up -d --build
docker ps -a
docker exec -it 'my gunicorn id' bash
./manage.py migrate
./manage.py collectstatic
./manage.py loaddata data.json
and open try open project in chrome browser in url localhost
and project opens without static files (no js, no css).
And in my docker logs:
> (docker-compose logs -f):
2021/03/25 10:51:32 [error] 51#51: *18 open() "/amd/static/images/fashion/product/13.jpg" failed (13: Permission denied), client: 172.23.0.1, server: localhost, request:
"GET /static/images/fashion/product/13.jpg HTTP/1.1", host: "localhost", referrer: "http://localhost/"
and I want one note about my code - this application already work fine in Mac OS, static files open fine. I think my problem is related with my Linux OS.
How can I solve this problem?
Thanks in advance. For additional information about my code it is github repo:
The problem probably dwells in permissions, more exactly in file owners - you can solve it easily (but not much securely) with chmod 777 on all files in the static (or media) volume.
The second option is to chown to the container user as decribed here https://stackoverflow.com/a/66910717/7113416 or propably even better here https://stackoverflow.com/a/56904335/7113416

Style of django admin is not shown

This is how my Django admin page looks like:
Though in my network section this is the result:
And the url path of these requests are correctly set by the static url, these are the Django settings:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
I collect statics before serving my app:
RUN python3 manage.py collectstatic --noinput (This is part of my Dockerfile)
some parts of my docker-compose:
web:
restart: always
image: <some private image>
ports:
- "127.0.0.1:8000:8000"
volumes:
- static_volume:/<path>/static
nginx:
container_name: nginx
image: nginx:1.19.3
restart: always
ports:
- 80:80
- 443:443
volumes:
- static_volume:/home/status/statics
volumes:
static_volume:
This is inside my nginx container:
Also this is in my https config for my nginx:
Well to me it seems like everything is working and I can't understand what's wrong with it.
I checked the console of the browser and I found some warnings. The styles were fetched as text and the problem was the wrong Content-Type header. I add mime.types file to my container and include that in my nginx config.
include /etc/nginx/mime.types;