I'm writting a web site which has api backend part and frontend part. I do not write a frontend part. And frontend is heavily tested and should be work fine. So the problem is with my backend.
Media files are being loaded in docker container (checked) but are not being loaded in website (localhost). I have no 404's. It looks like there is no requests to media files on website.
global urls:
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
)
settings:
MEDIA_URL = '/media_backend/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'backend_media')
nginx:
server {
listen 80;
server_name 127.0.0.1;
location /static_backend/ {
alias /app/backend_static/;
}
location /static/admin {
alias /app/backend_static/admin/;
}
location /media_backend/ {
alias /app/backend_media/;
}
location /api/docs/ {
root /usr/share/nginx/html;
try_files $uri $uri/redoc.html;
}
location /api/ {
proxy_pass http://backend:8000;
}
location /admin/ {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://backend:8000/admin/;
}
location / {
root /usr/share/nginx/html;
}
}
docker-compose:
version: '3.8'
services:
db:
image: postgres:12
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env
backend:
image: konstantin05/foodgram_backend:latest
expose:
- 8000
restart: always
volumes:
- static_value:/app/backend_static/
- media_value:/app/backend_media/
env_file:
- ./.env
nginx:
image: nginx:1.21.3-alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ../frontend/build:/usr/share/nginx/html/
- ../docs/redoc.html:/usr/share/nginx/html/api/docs/redoc.html
- ../docs/openapi-schema.yml:/usr/share/nginx/html/api/docs/openapi-schema.yml
- static_value:/app/backend_static/
- media_value:/app/backend_media/
restart: always
depends_on:
- frontend
frontend:
image: konstantin05/foodgram_frontend:latest
volumes:
- ../frontend/:/app/result_build/
volumes:
static_value:
media_value:
postgres_data:
instead of this:
volumes:
- static_value:/app/backend_static/
- media_value:/app/backend_media/
Try this way:
volumes:
- dev-static-data:/vol/web #I have removed media_value from volumes
And in your settings.py file:
STATIC_URL = '/static/static/'
MEDIA_URL = '/static/media/'
MEDIA_ROOT = '/vol/web/media'
STATIC_ROOT = '/vol/web/static'
Do above things only in docker compose and settings.py file.
And see if this is solves?
Related
I am working on my django + nginx + docker-compose project
I want to access my site via ip and mysite.com
Problem -- ip url is working, but mysite.com returns error:
403 Forbidden Nginx
My code - docker-compose.yml
services:
django:
build: ./project # path to Dockerfile
command: sh -c "
sleep 3 && gunicorn --bind 0.0.0.0:8000 core_app.wsgi"
...
expose:
- 8000
env_file:
- ./.env
depends_on:
- db
nginx:
image: nginx:1.19.8-alpine
depends_on:
- django
env_file:
- ./.env
ports:
- "80:80"
volumes:
- ./project/nginx-conf.d/:/etc/nginx/conf.d
...
nginx-conf.conf
upstream app {
server django:8000;
}
server {
listen 80;
server_name 127.0.0.1 mysite.com www.mysite.com;
location / {
proxy_pass http://django:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /static/ {
alias /var/www/html/static/;
}
}
UPDATE
I was trying to replace proxy_pass http://django:8000; with proxy_pass http://app; but it didn't help
Value of proxy_pass is incorrect.
When you're referencing an upstream group, you've to pass the name of the group to proxy_pass.
In your case, the name of upstream group is "app". So the value of proxy_pass should look like this:
proxy_pass http://app;
I have connected my Django (DRF) to Gunicorn and Nginx and put it all in docker.
When I load mysite.com/admin/ it looks bad, just plain text. So it seems like it does not load any static file. However, in Browser Console there are zero errors.
Moreover, I see that all the static files have been successfully loaded from server (all the /static/ requests are HTTP 200) and I can open them right in my browser by putting url: mysite.com/static/admin/css/base.css. And this file will successfully open. But admin site does not want to apply it.
On localhost with Debug=True everything is working fine too.
On main web site all the /media/ is working good too, so the problem is only within /static/.
nginx.conf
events {}
http {
server {
listen 80;
server_name mysite.com;
server_tokens off;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 80;
server_name api.mysite.com;
server_tokens off;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name mysite.com;
server_tokens off;
ssl_certificate /etc/nginx/certs/mysite.com-chain.pem;
ssl_certificate_key /etc/nginx/certs/mysite.com-key.pem;
location / {
proxy_pass http://10.0.2.237:3004; # React Frontend
}
}
server {
listen 443 ssl;
server_name api.mysite.com;
server_tokens off;
ssl_certificate /etc/nginx/certs/api.mysite.com-chain.pem;
ssl_certificate_key /etc/nginx/certs/api.mysite.com-key.pem;
location /media/ {
autoindex on;
alias /django-media/;
}
location /static/ {
autoindex on;
alias /django-static/;
}
location / {
try_files $uri #proxy_api;
}
location #proxy_api {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://10.0.2.237:7000; # Django Gunicorn Backend
}
}
}
docker-compose.backend.yml
version: '3.8'
services:
postgres_db:
container_name: postgres-prod
image: postgres
ports:
- "5543:5543"
volumes:
- postgres_data_prod:/var/lib/postgresql/data/
env_file:
- .env.production
command: -p 5543
web:
container_name: django-backend-prod
build: .
env_file:
- .env.production
ports:
- "7000:8001"
entrypoint: ./entrypoint.production.sh
volumes:
- .:/code
- media:/code/media
- static:/code/project/static
depends_on:
- postgres_db
networks:
- default
restart: always
volumes:
media:
driver_opts:
type: none
device: ${PWD}/media
o: bind
postgres_data_prod:
networks:
default:
external:
name: sentry-net
docker-compose.frontend.yml (in different directory, static and media are connected through volumes)
version: '3.8'
services:
frontapp:
container_name: React-Frontend-PROD
build:
context: .
dockerfile: Dockerfile
volumes:
- '.:/app'
- '/app/src'
- '/app/node_modules'
ports:
- "3004:3000"
env_file:
- .env.production
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- .nginx/nginx.conf:/etc/nginx/nginx.conf
- .certs/:/etc/nginx/certs
- django-backend-prod_media:/django-media
- django-backend-prod_static:/django-static
links:
- frontapp
depends_on:
- frontapp
networks:
- default
volumes:
django-backend-prod_media:
external: true
django-backend-prod_static:
external: true
networks:
default:
external:
name: sentry-net
In my project, I am using Django and nginx, but I want to manage my cloud databases through phpmyadmin.
Django is working fine but I can't do the same with phpmyadmin because it is running in apache at localhost:8080, when I want it to run in nginx at localhost/phpmyadmin.
here is the docker-compose.yml
version: "3.9"
services:
web:
restart: always
build:
context: .
env_file:
- .env
volumes:
- ./project:/project
expose:
- 8000
nginx:
restart: always
build: ./nginx
volumes:
- ./static:/static
ports:
- 80:80
depends_on:
- web
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
restart: always
environment:
PMA_HOST: <host_address>
PMA_USER: <user>
PMA_PASSWORD: <password>
PMA_PORT: 3306
UPLOAD_LIMIT: 300M
ports:
- 8080:80
and nginx default.conf
upstream django{
server web:8000;
}
server{
listen 80;
location / {
proxy_pass http://django;
}
location /pma/ {
proxy_pass http://localhost:8080/;
proxy_buffering off;
}
location /static/ {
alias /static/;
}
}
I hope somebody will be able to tell me how to make nginx work as a reverse proxy for the phpMyAdmin docker container.
If some important information is missing please let me know.
You can access another docker container with its hostname and the internal port (not the exposed one).
Also a rewrite of the url is necessary.
location ~ \/pma {
rewrite ^/pma(/.*)$ $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://phpmyadmin;
}
I tested with this docker-compose.yml:
version: "3.9"
services:
nginx:
image: nginx:latest
volumes:
- ./templates:/etc/nginx/templates
ports:
- 80:80
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
I'm not sure how much sense it would make, but I was learning docker to deploy Django app with Gunicorn + Nginx + AWS.
So far, it works fine, where I have unit tested it in production.
My question is how can I access pgAdmin4 now?
docker-compose.staging.yml
version: '3.8'
# networks:
# public_network:
# name: public_network
# driver: bridge
services:
web:
build:
context: .
dockerfile: Dockerfile.prod
# image: <aws-account-id>.dkr.ecr.<aws-region>.amazonaws.com/django-ec2:web
command: gunicorn djangotango.wsgi:application --bind 0.0.0.0:8000
volumes:
# - .:/home/app/web/
- static_volume:/home/app/web/static
- media_volume:/home/app/web/media
expose:
- 8000
env_file:
- ./.env.staging
networks:
service_network:
db:
image: postgres:12.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env.staging.db
networks:
service_network:
# depends_on:
# - web
pgadmin:
image: dpage/pgadmin4
env_file:
- ./.env.staging.db
ports:
- "8080:80"
volumes:
- pgadmin-data:/var/lib/pgadmin
depends_on:
- db
links:
- "db:pgsql-server"
environment:
- PGADMIN_DEFAULT_EMAIL=pgadmin4#pgadmin.org
- PGADMIN_DEFAULT_PASSWORD=fakepassword
- PGADMIN_LISTEN_PORT=80
networks:
service_network:
nginx-proxy:
build: nginx
# image: <aws-account-id>.dkr.ecr.<aws-region>.amazonaws.com/django-ec2:nginx-proxy
restart: always
ports:
- 443:443
- 80:80
networks:
service_network:
volumes:
- static_volume:/home/app/web/static
- media_volume:/home/app/web/media
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
- /var/run/docker.sock:/tmp/docker.sock:ro
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
depends_on:
- web
nginx-proxy-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
env_file:
- .env.staging.proxy-companion
networks:
service_network:
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- certs:/etc/nginx/certs
- html:/usr/share/nginx/html
- vhost:/etc/nginx/vhost.d
depends_on:
- nginx-proxy
networks:
service_network:
volumes:
postgres_data:
pgadmin-data:
static_volume:
media_volume:
certs:
html:
vhost:
I can access the django application through my domain name like xyz.example.com. I have just shown the docker-compose here.
Also within local I can access pgadmin4 via localhost:8080.
Is it possible to do it in production? If yes how?
I would be using AWS RDS for database, but for now my database is within docker container, so I'm thinking how to access it now?
I found some documentation.
https://www.pgadmin.org/docs/pgadmin4/development/container_deployment.html
The url to access your pgadmin page would be configured in nginx. This example:
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name _;
ssl_certificate /etc/nginx/server.cert;
ssl_certificate_key /etc/nginx/server.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location /pgadmin4/ {
proxy_set_header X-Script-Name /pgadmin4;
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_pass http://localhost:5050/;
proxy_redirect off;
}
}
The important parts I am catching here are the location /pgadmin4/ redirecting to the localhost:5050. In your case, it would be localhost:8080.
It looks like in your other post you included your nginx config:
https://www.digitalocean.com/community/questions/no-live-upstream-while-connecting-to-upstream-jwilder-ngnix-proxy
upstream djangotango.meghaggarwal.com {
server web:8000;
}
server {
listen 80;
listen 443;
server_name djangotango.meghaggarwal.com
location / {
proxy_pass http://djangotango.meghaggarwal.com;
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/static/;
add_header Access-Control-Allow-Origin *;
}
location /media/ {
alias /home/app/web/media/;
add_header Access-Control-Allow-Origin *;
}
}
I would suggest adding a section like :
location /pgadmin4/ {
proxy_set_header X-Script-Name /pgadmin4;
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_pass http://localhost:8080/;
proxy_redirect off;
}
It might not be the only configuration you need to add... I have only skimmed the documentation. I am sure the link may help you more if this doesn't do the trick.
[SOLVED] This is a duplicate. Please see this question.
I have a basic Django API working in development when I launch via the runserver command. I am returning a list of objects including the URL of an image in my media folder. In development, this image URL includes the port as shown below. The link works fine when I click it in the browser.
"image_url": "http://0.0.0.0:1337/mediafiles/publisher/sample-image4.jpg",
In production (gunicorn, nginx, docker) everything works the same except the URLs returned by the API do not include the port, so the links are broken. How can I ensure the port is included even in production?
"image_url": "http://0.0.0.0/mediafiles/publisher/sample-image4.jpg",
My guess is it could be an nginx config issue since it works in development server, but I don't really know where the problem is so my searches are not really helping. I'm still quite new to nginx, django and docker.
settings.py
...
STATIC_URL = '/staticfiles/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_URL = '/mediafiles/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'mediafiles')
...
docker-compose.yml
version: '3.7'
services:
web:
build: ./app
command: gunicorn hello_django.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- "8000"
env_file: ./app/.env
environment:
- DB_ENGINE=django.db.backends.postgresql
- DB_USER
- DB_PASSWORD
- DB_HOST=db
- DB_PORT=5432
- DATABASE=postgres
depends_on:
- db
networks:
- backend
nginx:
build: ./nginx
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- "1337:80"
depends_on:
- web
networks:
- backend
networks:
backend:
driver: bridge
volumes:
postgres_data:
static_volume:
media_volume:
nginx.conf
upstream hello_django {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /usr/src/app/staticfiles/;
}
location /mediafiles/ {
alias /usr/src/app/mediafiles/;
}
location /favicon.ico {
access_log off;
log_not_found off;
}
}