Django and Docker Compose access media folder between containers - django

I'm working on a docker-compose app using Django and a container to check images validity, here's the project structure:
|-- backend
| |-- backend
| | |-- asgi.py
| | |-- celery.py
| | |-- __init__.py
| | |-- settings.py
| | `-- urls.py
| |-- manage.py
| |-- media
| | `-- temp
| | `-- image.png
| |-- profiles
|-- docker-compose.yml
|-- Dockerfile
|-- README.md
|-- requirements.txt
**|-- config/nginx/nginx.conf**
Here's the docker-compose configuration of django and nsfw:
app:
build: .
volumes:
- .:/app
ports:
- "8000:8000"
env_file:
- .env/.env.dev
depends_on:
- database
nsfw:
image: eugencepoi/nsfw_api
logging:
driver: none
ports:
- "5000:5000"
depends_on:
- app
environment:
- PORT=5000
nginx:
image: nginx:latest
ports:
- "8001:8001"
volumes:
- .:/app
- ./config/nginx:/etc/nginx/conf.d
Nginx configuration:
client_max_body_size 10M;
upstream web {
ip_hash;
server app:8000;
}
server {
location /media/ {
autoindex on;
alias /app/media/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
And here's when I try to access the source:
"{"error_code":404,"error_reason":"Not Found","url":"http://nginx/media/image.png"}\n"

As I can see from the EugenCepoi/nsfw_api repository, the service only supports http request. Also in production server, Django can't serve media contents, hence you can use VOLUME to share contents between many containers. I recommend using a new NGINX service for serving the media files, so I am adding the nginx service to the docker-compose file:
services:
app:
build: .
volumes:
- .:/app
env_file:
- ./.env/prod.env
depends_on:
- database
nsfw:
image: eugencepoi/nsfw_api
logging:
driver: none
ports:
- "5000:5000"
depends_on:
- app
environment:
- PORT=5000
nginx:
image: nginx:latest
ports:
- "8000:8000"
volumes:
- .:/app
- ./config/nginx:/etc/nginx/conf.d
volumes:
media:
And create a nginx configuration file in in your project directory/config/nginx/somename.conf:
client_max_body_size 10M;
upstream web {
ip_hash;
server app:8000;
}
server {
location /static/ {
autoindex on;
alias /app/path/to/static/;
}
location /media/ {
autoindex on;
alias /app/backend/media/;
}
location / {
proxy_pass http://web/;
}
listen 8000;
server_name localhost;
}
Now whatever content you add in app container's media folder, it will be available in /app directory of nginx container. Then nginx can serve these contents at nginx url.
url = "http://nginx:8000/media/temp/image.png"

Related

Nginx not serving media files. Dockerizing django/nginx/gunicorn/postgresql

I have a project running in 3 docker containers. One is for django project itself, another one for postgres and the third one for nginx. My static files are served just fine while all media files are not found. However every file which was uploaded is properly saved in web container in media folder.
Here is the docker-compose file:
version: '3.8'
volumes:
postgres_data:
static:
services:
db:
image: postgres:latest
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env
web:
build: .
restart: always
command: gunicorn foodgram.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./static:/static
- ./media:/media
ports:
- "8000:8000"
depends_on:
- db
env_file:
- ./.env
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "8080:80"
volumes:
- ./static:/etc/nginx/html/static
- ./media:/etc/nginx/html/media
depends_on:
- web
Here is the dockerfile:
FROM python:3.8.5
WORKDIR /code
COPY . /code
RUN pip install -r /code/requirements.txt
Here is the nginx.conf:
events {}
http {
include mime.types;
server {
location / {
proxy_pass http://web:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
location /static/ {
autoindex on;
root /etc/nginx/html/;
}
location /media/ {
autoindex on;
root /etc/nginx/html/;
}
}
}
and finally nginx dockerfile:
FROM nginx:latest
COPY nginx/nginx.conf /etc/nginx/nginx.conf
Error returned:
19#19: *1 open() "/etc/nginx/html/media/4.jpg" failed (2: No such file or directory)
There are no nested folders in media/static folders.

NGINX and TRAEFIK staticfiles are not working with HTTPS in production

I'm developing a website for my association Here. It uses Django 3.0.7 and PostgreSQL. I follow this tutorial to make it works in good condition in development and in production.
In development mode all is good, site is working perfectly, static files and media files are served by the Django built-in web server.
I test the "vanilla" (coming from the tutorial) production on my local machine it works too. But the tutorial is not complete for me so after completing it, I decided to adapt the code to fit my needs. As I follow the tutorial I created a new docker-compose and a new dockerfile for production. But there are 2 differences between the tutorial and the site I want to set in production:
I want to Use TREAFIK to route the traffic on different URL (appli.amis-simserhof.fr) because I will have other projects in the future on the same server with others subdomains..
I want to secure the website using HTTPS. So I use CERTBOT (let's encrypt) to generate certificates. I add this certificates to TREAFFIK in order to use HTTPS and it works.
So I adapted the docker-compose file with my new stuff :
version: '3.7'
services:
**traefik:
image: traefik:v1.7.12
command: [
"--loglevel=INFO",
"--api",
"--docker",
"--docker.domain=amis-simserhof.fr",
"--entrypoints=name:https address::443 tls:/etc/certs/fullchain.pem,/etc/certs/privkey.pem",
"--entrypoints=name:http address::80 redirect.entrypoint:https",
]
ports:
- 80:80 # http
- 443:443 # https
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/letsencrypt/live/amis-simserhof.fr/fullchain.pem:/etc/certs/fullchain.pem
- /etc/letsencrypt/live/amis-simserhof.fr/privkey.pem:/etc/certs/privkey.pem**
web:
image: registry.gitlab.com/guillaumekoenigtncy/aas-web:latest
command: gunicorn aas.wsgi:application --bind 0.0.0.0:8000
expose:
- 8000
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
environment:
- DEBUG=0
- SECRET_KEY=change_me
- DJANGO_ALLOWED_HOSTS=localhost appli.amis-simserhof.fr
- SQL_ENGINE=django.db.backends.postgresql
- SQL_DATABASE=postgres
- SQL_USER=postgres
- SQL_PASSWORD=postgres
- SQL_HOST=db
- SQL_PORT=5432
- DATABASE=postgres
labels:
- traefik.frontend.rule=HostRegexp:appli.amis-simserhof.fr
- traefik.frontend.entryPoints=https
depends_on:
- db
db:
image: postgres:12.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
**nginx:
image: registry.gitlab.com/guillaumekoenigtncy/aas-nginx:latest
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
expose:
- 80
- 443
depends_on:
- web**
volumes:
postgres_data:
static_volume:
media_volume:
I also created a dockerfile and a config file for nginx :
FROM nginx:1.19.0
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
upstream website {
server web:8000;
}
server {
listen 80;
listen [::]:80;
access_log off;
server_name appli.amis-simserhof.fr;
location / {
proxy_pass http://website;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /home/app/web/staticfiles/;
}
location /mediafiles/ {
alias /home/app/web/mediafiles/;
}
}
The problem is that now static files are not served in production (I got a 404). When I set the DEBUG to True in the setting.py of the project files are served sot that means static files are present in the correct folder that I have set in the settings.
STATIC_URL = "/staticfiles/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
MEDIA_URL = "/mediafiles/"
MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles")
In production, I have correctly run the python manage.py collectstatic command. I look inside both containers, ngnix and web, and in both the files are present in the correct directory.
So I conclude my configuration is not working but when I made changes in it, I saw this changes in the nginx logs of the containers. There are no errors...
I try everything during the last 2 days: set the ssl in the nginx config and remove it from traefik (site is not accessible), expose or not ports 80 and 443 in nginx or traefik (conflicts on open ports or too many redirect error), add or remove / at the end or at the beginning of blocks or alias in nginx configuration (change nothing), etc.
If you have any hint or tips I would be really grateful...
Have a nice day :)
I'am was able do define static path with following nginx service configuration:
version: '3.7'
services:
server:
container_name: dj
build:
context: ./server/project/
restart: unless-stopped
expose:
- 8000
volumes:
- static_volume:/app/staticfiles
- media_volume:/app/media
command: gunicorn project.wsgi:application --bind 0.0.0.0:8000
networks:
- web
nginx:
container_name: nginx
build:
context: ./
dockerfile: Dockerfile
restart: unless-stopped
volumes:
- static_volume:/app/staticfiles
- media_volume:/app/media
labels:
- "traefik.enable=true"
- "traefik.http.routers.${SERVICE}.rule=(Host(`${DOMAIN_NAME}`) && PathPrefix(`/static`)) || (Host(`${DOMAIN_NAME}`) && PathPrefix(`/media`))"
- "traefik.http.routers.${SERVICE}.tls.certresolver=letsEncrypt"
- "traefik.http.routers.${SERVICE}.entrypoints=web-secure"
- "traefik.http.services.${SERVICE}.loadbalancer.server.port=80"
depends_on:
- server
networks:
- web
volumes:
static_volume:
media_volume:
networks:
web:
external: true
Note this line:
- "traefik.http.routers.static-http.rule=Host(`ex.example.com`) && PathPrefix(`/static`)"
change the ex.example.com to you domain
Here is part of my configuration, The "server" part is not completed yet
UPDATE
To use the same static files between django and nginx use following nxing configuration:
#default.conf
server {
listen 80;
server_name _;
ignore_invalid_headers on;
location / {
root /usr/share/nginx/html;
index index.html;
default_type application/javascript;
try_files $uri $uri/ /index.html =404;
}
location /static {
autoindex on;
alias /app/staticfiles/;
}
location /media {
autoindex on;
alias /app/media/;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
Also note that I've updated docker-compose file and added Dockerfile below:
#Dockerfile
FROM nginx:1.19.1-alpine
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
So your Project-Structure should look like:
Project-root/
|-server/
|-nginx/
| |-default.conf
|-Dockerfile
|-docker-compose.yml

Serve Django Media Files via Nginx (Django/React/Nginx/Docker-Compose)

Context
I have a single page web app using the following stack:
React for the frontend
Django for the backend
Nginx for the webserver
The web application is dockerized using docker-compose. My React app, fetches data from the Django server (django is built as an api endpoint using Django Rest Framework).
Question/Problem
I am having an issue on deployment where I am unable to serve my media files via Nginx.
What have I tried so far
My initial thought was to serve the media files as shown on this stackoverflow post - which is pretty straight forward. Though, since Nginx runs in its own docker (and so does my django server), I unable to point to my django media files since they are in different containers.
Ideally, I would not want to use webpack, and have Nginx take care of serving media files.
If you look at the nginx Dockerfile below, you will see that I am copying my static files into /usr/share/nginx/html/static/staticfiles to then serve them using nginx (see location ^~ /static/ in nginx.conf). I have tried to do the same thing for my media file (as a test) and it works - though, all the files I am uploding once the site is up are not accessible since the copy happens when I build my container.
File Structure
Root Dirc
|__ docker-compose.yml
|__ backend
|__ root
|__ Project
|__ api
|__ models.py
|__ ...
|__ media
|__ teddycrepineau
|__ settings.py
|__ ...
|__ production
|__ Dockerfile
|__ nginx
|__ Dockerfile
|__ nginx.conf
|__ frontend
|__ ...
Relevant Code
docker-compose.yml
version: '3'
volumes:
postgres_data: {}
postgres_backup: {}
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env
nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"
django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'
env_file: .env
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
upstream app {
server django:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 0.0.0.0;
charset utf-80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ #proxy_to_app;
}
location #proxy_to_app {
rewrite ^(.+)$ /index.html last;
}
location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}
location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}
nginx Dockerfile
FROM nginx:latest
ADD ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./frontend/build /usr/share/nginx/html
COPY ./backend/root/staticfiles /usr/share/nginx/html/static/staticfiles
Django Dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1
RUN export DEBIAN_FRONTEND=noninteractive
RUN mkdir /app
RUN pip install --upgrade pip
ADD /root/requirements.txt /app/
WORKDIR /app/
ADD . /app/
RUN pip install -r requirements.txt
EXPOSE 8000
Django settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
APPS_DIR = os.path.join(BASE_DIR, 'project')
....
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(APPS_DIR, 'media/')
Django urls.py
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^api/', include('project.api.urls')),
path('summernote/', include('django_summernote.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Update
When I mount a shared volum and reference it in my nginx.conf I get a 404 page not found when trying to access the image uploaded in the django backend.
docker-compose.yml
version: '3'
volumes:
postgres_data: {}
postgres_backup: {}
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env
nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"
volumes:
- ./static:/app/backend/root/staticfiles
- ./media:/app/backend/root/project/media
django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
- ./static:/app/backend/root/staticfiles
- ./media:/app/backend/root/project/media
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py collectstatic --no-input &&
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'
env_file: .env
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
upstream app {
server django:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
charset utf-80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ #proxy_to_app;
}
location #proxy_to_app {
rewrite ^(.+)$ /index.html last;
}
location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}
location ^~ /media/ {
autoindex on;
alias /app/backend/root/project/media/;
}
location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}
The problem came from the way I mounted my volumes in the docker-compose.yml (it was a miss understanding from my part).
First, we create a host mounted volume (./backend/) referencing our /app/ folder that exist in our django service. We created this folder and added all the relevant files in our Dockerfile located in the backend folder. This will basically link our /app/ folder that exist on the django Docker image to ./backend folder that exist on the host - refer file structure from OP.
Once we have this volume, whenever an update is made to our /app/ folder (i.e. uploading a new image), it will be reflected in our host mounted volumes (i.e. ./backend/) - and vice versa.
We finally create 2 more sets of host mounted volumes (./backend/root/staticfiles/..., and ./backend/root/project/media/) that we'll use to serve our media and static files via Nginx. We share these host mounted volumes between nginx and django service. Starting with version 2 docker-compose automatically creates a network between you Docker images which allows you to share volumes between services.
Finally in our nginx.conf we reference the host mounted volumes in the docker-compose.yml file for the static and media url.
docker-compose.yml
version: '3'
volumes:
postgres_data: {}
postgres_backup: {}
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env
django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
- ./backend/root/staticfiles/admin:/usr/share/nginx/html/static/admin
- ./backend/root/staticfiles/rest_framework:/usr/share/nginx/html/static/rest_framework
- ./backend/root/staticfiles/summernote:/usr/share/nginx/html/static/summernote
- ./backend/root/project/media/:/usr/share/nginx/html/media/
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py collectstatic --no-input &&
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'
env_file: .env
nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"
volumes:
- ./backend/root/staticfiles/admin:/usr/share/nginx/html/static/admin
- ./backend/root/staticfiles/rest_framework:/usr/share/nginx/html/static/rest_framework
- ./backend/root/staticfiles/summernote:/usr/share/nginx/html/static/summernote
- ./backend/root/project/media/:/usr/share/nginx/html/media/
nginx.conf
....
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
charset utf-80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ #proxy_to_app;
}
location #proxy_to_app {
rewrite ^(.+)$ /index.html last;
}
location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}
location ^~ /media/ {
autoindex on;
alias /usr/share/nginx/html/media/;
}
location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}

serving Django static files with Docker, nginx and gunicorn

I am setting us a Django 2.0 application with Docker, nginx and gunicorn.
It's running the server but static files are not working.
Here is the settings.py content
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_my_project')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static_cdn', 'static_root')
While developing, I put my static files inside static_my_project, which on running collectstatic copies to static_cdn/static_root
The directory structure is like
app
|- myapp
|- settings.py
|- static_my_project
|- static_cdn
|- static_root
|- config
|- nginx
|- nginx.conf
|- manage.py
|- Docker
|- docker-compose.yml
on running
docker-compose up --build
on running collectstatic, it gives path where static files will be copied
koober-dev | --: Running collectstatic
koober-dev |
koober-dev | You have requested to collect static files at the destination
myapp-dev | location as specified in your settings:
myapp-dev |
myapp-dev | /app/static_cdn/static_root
myapp-dev |
myapp-dev | This will overwrite existing files!
myapp-dev | Are you sure you want to do this?
myapp-dev |
myapp-dev | Type 'yes' to continue, or 'no' to cancel:
myapp-dev | 0 static files copied to '/app/static_cdn/static_root', 210 unmodified.
the config/nginx/nginx.conf file contains following settings
upstream web {
ip_hash;
server web:9010;
}
server {
location /static {
autoindex on;
alias /static/;
}
location / {
proxy_pass http://web;
}
listen 10080;
server_name localhost;
}
docker-compose.yml
version: '3'
services:
nginx:
image: nginx:latest
container_name: "koober-nginx"
ports:
- "10080:80"
- "10443:43"
volumes:
- .:/app
- ./config/nginx:/etc/nginx/conf.d
- ./static_cdn/static_root/:/static
depends_on:
- web
web:
build: .
container_name: "koober-dev"
command: ./start.sh
volumes:
- .:/app
- ./static_cdn/static_root/:/app/static_cdn/static_root
ports:
- "9010:9010"
depends_on:
- db
db:
image: postgres
container_name: "koober-postgres-db"
Dockerfile
FROM ubuntu:18.04
# -- Install Pipenv:
FROM python:3
ENV PYTHONUNBUFFERED 1
ENV LC_ALL C.UTF-8
ENV LANG C.UTF-8
# -- Install Application into container:
RUN set -ex && mkdir /app
WORKDIR /app
ADD requirements.txt /app/
RUN pip install -r requirements.txt
# -- Adding dependencies:
ADD . /app/
But it is not loading static files.
You need to have a shared volume to the STATIC_ROOT directory so that your nginxcontainer can reverse proxy to both web server and static files generated by your web server.
In docker-compose.yml:
services:
nginx:
image: nginx:alpine
volumes:
- ./static_cdn/static_root/:/static
ports:
- 80:80
web:
build: .
volumes:
- ./static_cdn/static_root/:/app/static_cdn/static_root
Now in your nginx.conf add:
location /static/ {
alias /static/;
}
Nginx Dockerfile:
FROM nginx:stable-alpine
COPY default.conf /etc/nginx
COPY default.conf /etc/nginx/conf.d
EXPOSE 80
default.conf referred to in the above Dockerfile:
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://web:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/static/;
}
}
Note: The default.conf and Dockerfile mentioned above is under the same folder, build that image and use it as the Nginx image in the below docker-compose file.
The docker-compose file would look like this:
version: '3.8'
services:
web:
image: <django-image-name>
command: gunicorn --bind 0.0.0.0:8000 licensing_platform.wsgi --workers=4
volumes:
- static_volume:/app/static
- media_volume:/app/media
expose:
- "8000"
networks:
- django-network
nginx:
image: <nginx-image-name>
restart: always
volumes:
- static_volume:/app/static
- media_volume:/app/media
ports:
- "80:80"
depends_on:
- web
networks:
- django-network
networks:
django-network:
name: django-network
volumes:
media_volume:
static_volume:
The app/ path referenced depends on the working directory:
The django application Dockerfile would start with:
FROM ubuntu:20.04
ADD . /app
WORKDIR /app
EXPOSE 8000
Code reference: https://github.com/addu390/licensing-as-a-platform
The code reference mentioned above is an open-source project I'm working on with no commercial benefits.

Docker + Gunicorn + Nginx + Django: redirect non-www to www on AWS Route 53

I have a Docker + Gunicorn + Nginx + Django setup on AWS EC2 and Route 53. Right now I want to redirect mydomain.com to www.mydomain.com.
Is it appropriate to do a redirect in a Nginx configuration? Or are there are better solutions.
Here is docker-compose-yml, using gunicorn to start the Django server.
version: '2'
services:
nginx:
image: nginx:latest
container_name: dj_nginx
ports:
- "80:8000"
- "443:443"
volumes:
- ./src/my_project/static:/static
- ./src:/src
- ./config/nginx:/etc/nginx/conf.d
depends_on:
- web
web:
build: .
container_name: dj_web
command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn my_project.wsgi -b 0.0.0.0:8000"
depends_on:
- db
volumes:
- ./src:/src
- ./apps/django_rapid:/src/my_project/django_rapid
expose:
- "8000"
db:
image: postgres:latest
container_name: dj_db
Here is my Nginx Conf
upstream web {
ip_hash;
server web:8000;
}
# portal
server {
listen 8000;
location / {
proxy_pass http://web/;
}
location /media {
alias /media; # your Django project media files - amend as required
}
location /static {
alias /static; # your Django project static files - amend as required
}
server_name localhost;
}
# portal (https)
server {
listen 443;
server_name localhost;
ssl on;
ssl_certificate /etc/nginx/conf.d/mynginx.crt;
ssl_certificate_key /etc/nginx/conf.d/mynginx.key;
location /media {
alias /media; # your Django project media files - amend as required
}
location /static {
alias /static; # your Django project static files - amend as required
}
location / {
proxy_pass http://web/;
}
}
Yes, it's appropriate to do these kinds of redirects in the webserver. If it's https your certificate needs to cover both domains.
Yes it's appropriate to do nginx redirections, but i find doing PREPEND_WWW more simple.
Add this in your settings.py
PREPEND_WWW = True