Связывание контейнеров Django и nginx при развертывании
Когда я использую docker-compose для создания образов и запуска контейнеров, все работает нормально, и я могу получить доступ к своему приложению в браузере через localhost.
Затем я переименовываю/отмечаю образы и загружаю их на dockerhub.
Я написал второй docker-compose.yml, который извлекает эти два образа из dockerhub, создает сеть и запускает их. Оба образа загружаются правильно, но когда я направляю браузер на localhost, то получаю только окно "Welcome to Ngninx - further configuration required".
Я использовал 'docker network inspect' для сравнения двух сетей, и все кажется одинаковым, за исключением очень незначительных изменений ip-адресов.
CHESS_NN_WEBAPP
│ docker-compose.yml
│ docker-compose_deploy.yml
│ Dockerfile
│ requirements.txt
│
├───config
│ └───nginx
│ └───conf.d
│ local.conf
│
├───django_wrapper
│ │ db.sqlite3
│ │ manage.py
│ │
│ ├───django_wrapper
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │
│ └───webapp
│ │ admin.py
│ │ apps.py
│ │ chess_tools.py
│ │ urls.py
│ │ views.py
│ │
│ ├───templates
│ index.html
│
└───other stuff
Докерфайл для контейнера приложений django/gunicorn:
# start from official image
FROM python:3.10-slim
# arbitrary location choice: you can change the directory
RUN mkdir -p /opt/services/djangoapp/src
WORKDIR /opt/services/djangoapp/src
# install dependencies
COPY requirements.txt /opt/services/djangoapp/src/
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install opencv-python-headless
# copy project code
COPY . /opt/services/djangoapp/src
# start django server
RUN cd django_wrapper && python manage.py
# expose port 80
EXPOSE 80
# define default command to run when starting the container
CMD ["gunicorn", "--chdir", "django_wrapper", "--bind", ":80",
"django_wrapper.wsgi:application", "--timeout", "0"]
docker-compose.yml, который собирает изображения:
version: '3'
services:
djangoapp:
build: .
volumes:
- .:/opt/services/djangoapp/src
networks:
- nginx_network
nginx:
image: pagespeed/nginx-pagespeed:latest
ports:
- 80:80
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
depends_on:
- djangoapp
networks:
- nginx_network
networks:
nginx_network:
driver: bridge
Nginx conf.d:
# first we declare our upstream server, which is our Gunicorn application
upstream chess_nn {
server djangoapp:80;
}
# now we declare our main server
server {
listen 80;
server_name localhost;
location / {
# everything is passed to Gunicorn
proxy_pass http://chess_nn;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Пока все работает как надо (т.е. у меня есть доступ через localhost), поэтому два получившихся образа помечаем как 'colurw/chess_nn:webapp' и 'colurw/chess_nn:nginx' и отправляем в Docker Hub.
Мой файл docker-compose.yml для извлечения и запуска этих образов выглядит так:
version: '3'
services:
djangoapp:
image: colurw/chess_nn:webapp
networks:
- nginx_network
nginx:
image: colurw/chess_nn:nginx
ports:
- 80:80
depends_on:
- djangoapp
networks:
- nginx_network
networks:
nginx_network:
driver: bridge
Запуск docker-compose с этим файлом приводит к тому, что оба контейнера работают... Я вижу экран nginx в браузере, а в журнале gunicorn написано "Listening at: http://0.0.0.0:80", но я также вижу из журнала, что запрос браузера не проходит так далеко, поскольку нормальный ответ (который включает загрузку chess_tools.py при первом обращении к localhost) не происходит.
Вот результаты "docker network investigate" для сети нерабочих контейнеров:
[
{
"Name": "chess_nn_webapp_nginx_network",
"Id": "40ece5962610e64d605b579ee27bf71b3e665767bc67af3d0767a1e58a27adff",
"Created": "2024-02-01T15:57:41.422912742Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"2b89f8fbe62acc31d08420cb97fb7fc264743b2efb3715856d78e3b13ffe5265": {
"Name": "chess_nn_webapp-djangoapp-1",
"EndpointID": "20abea988881a827caa1671e3ffb38cc35983b52961fde9674781c1bdc56a1d1",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"b3669a895bd52023c949505b7174f4e1d0a6570dbfa955af22f0fc5f5789afc3": {
"Name": "chess_nn_webapp-nginx-1",
"EndpointID": "2e156010866564e4261befda0d6980b7aea2c12bc0077a6ea5e4bb4c854f80e0",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "nginx_network",
"com.docker.compose.project": "chess_nn_webapp",
"com.docker.compose.version": "2.23.3"
}
}
]
Спасибо, что дошли так далеко! Пожалуйста, если у вас есть предположения о том, в чем проблема, я буду очень благодарен.
Для контейнера Nginx в вашей локальной среде вы внедряете локальный файл конфигурации Nginx во время выполнения
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
но в удаленном развертывании эта конфигурация отсутствует.
Ваше удаленное развертывание уже написано так, чтобы ожидать пользовательский образ для прокси Nginx, поэтому самым простым изменением может быть включение конфигурационного файла в образ. Это может быть очень простой Dockerfile
# Dockerfile.nginx
FROM pagespeed/nginx-pagespeed:latest
COPY config/nginx/conf.d/ /etc/nginx/conf.d/
и вашему файлу Compose нужно сказать, чтобы он создавал образ, а не монтировал том
nginx:
image: colurw/chess_nn:nginx
build:
context: .
dockerfile: Dockerfile.nginx
ports:
- 80:80
# volumes: <-- delete
# - ./config/nginx/conf.d:/etc/nginx/conf.d
depends_on:
- djangoapp
networks: # consider deleting as well
- nginx_network
В локальной среде я бы аналогичным образом рассмотрел возможность удаления volumes:
для контейнера djangoapp
. Это приведет к замене всего кода образа содержимым хост-системы, что означает, что локально вы фактически не запускаете развертываемый образ. Также безопасно удалить все блоки networks:
из всего файла, поскольку Compose создаст сеть с именем default
и автоматически присоединит к ней все контейнеры.