Docker-compose с NGINX не обслуживает Django на localhost
Я пытаюсь обслужить простое приложение Django через NGINX с помощью Docker Compose. Я не совсем понимаю, откуда берется проблема, но сборка прошла успешно. Есть идеи, почему приложение не работает правильно?
Это установка:
├── app
│ ├── templates
│ ├── webapp
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── Dockerfile
│ ├── Dockerfile.prod
│ ├── entrypoint.sh
│ ├── entrypoint.prod.sh
│ └── requirements.txt
├── nginx
│ ├── Dockerfile
│ └── nginx.conf
├── .env
├── docker-compose.ci.yml
├── docker-compose.prod.yml
└── docker-compose.yml
app/webapp/settings.py:
.env
DEBUG=0
SECRET_KEY=<foo>
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=webapp_django_prod
SQL_USER=webapp_django
SQL_PASSWORD=<password>
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
YOUTUBE_DATA_API_KEY=<foo>
app/Dockerfile
# pull official base image
FROM python:3.9.6-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install psycopg2
RUN apk update \
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
&& pip install psycopg2 \
&& apk del build-deps
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r /usr/src/app/requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh /usr/src/app/entrypoint.sh
# copy project
COPY . /usr/src/app/
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.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"
fi
python manage.py flush --no-input
python manage.py migrate
python manage.py collectstatic --no-input --clear
exec "$@"
app/Dockerfile.prod
# pull official base image
FROM python:3.9.6-alpine
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install psycopg2
RUN apk update \
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
&& pip install psycopg2 \
&& apk del build-deps
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r /usr/src/app/requirements.txt
# copy entrypoint-prod.sh
COPY ./entrypoint.prod.sh /usr/src/app/entrypoint.prod.sh
# copy project
COPY . /usr/src/app/
# run entrypoint.prod.sh
ENTRYPOINT ["/usr/src/app/entrypoint.prod.sh"]
app/entrypoint.prod.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"
fi
exec "$@"
nginx/Dockerfile
FROM nginx:1.21-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
nginx/nginx.conf
upstream webapp {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://webapp;
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/;
}
}
docker-compose.yml
version: '3.8'
services:
web:
build: ./app
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
ports:
- 8000:8000
environment:
- DEBUG=1
- SECRET_KEY=<foo>
- SQL_ENGINE=django.db.backends.postgresql
- SQL_DATABASE=webapp_django_prod
- SQL_USER=webapp_django
- SQL_PASSWORD=<foo>
- SQL_HOST=db
- SQL_PORT=5432
- DATABASE=postgres
depends_on:
- db
db:
image: postgres:13-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=webapp_django
- POSTGRES_PASSWORD=<foo>
- POSTGRES_DB=webapp_django_prod
volumes:
postgres_data:
docker-compose.ci.yml
version: '3.8'
services:
web:
build:
context: ./app
dockerfile: Dockerfile.prod
cache_from:
- "${WEB_IMAGE}"
image: "${WEB_IMAGE}"
command: gunicorn webapp.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
expose:
- 8000
env_file: .env
nginx:
build:
context: ./nginx
cache_from:
- "${NGINX_IMAGE}"
image: "${NGINX_IMAGE}"
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- 80:80
depends_on:
- web
volumes:
static_volume:
media_volume:
docker-compose.prod.yml
version: '3.8'
services:
web:
image: "${WEB_IMAGE}"
command: gunicorn webapp.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- 8000:8000
env_file: .env
nginx:
image: "${NGINX_IMAGE}"
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- 80:80
depends_on:
- web
volumes:
static_volume:
media_volume:
Поскольку я не могу комментировать до сих пор. Самый простой способ определить проблему - просмотреть журналы.
Вы можете проверить контейнеры Docker, запустив это на каждом экземпляре:
docker logs --follow your-container-name
Или вы можете добавить это в ваш файл docker-compose, если контейнер docker будет убит, вы можете получить доступ к нему с помощью journalctl:
mycontainer:
image: myimage
logging:
driver: journald
options:
tag: mytag
И затем получить доступ к нему, используя:
journalctl -u docker CONTAINER_NAME=mycontainer_name
journalctl -u docker CONTAINER_TAG=mytag
Ответ частично взят из: https://stackoverflow.com/a/43663253/16891224