我无法弄清楚部署使用 uwsgi/gunicorn 的 Django 项目的“正确”方法是什么(我还没有决定使用什么,可能是 uwsgi,因为它的性能更好,有什么建议吗?)和使用 docker 的 nginx。
我看到有些人把所有东西都放在同一个容器中。我不是 docker 专家,但容器应该只做一件事。因此,拥有 Django + nginx 似乎是 2 而不是 1。
现在,我对部署的想法是:
- 一个包含 Django 和 uwsgi 的容器。在 Dockerfile 的末尾,我运行 uwsgi 脚本。此容器公开端口 8000
- 一个带有 nginx 的容器,链接到 django one。这会公开端口 80 并将请求代理到 django。
还有其他方法吗?有没有更深入地介绍这种情况的教程。我需要一个可靠的产品,而不仅仅是在我的 PC 上测试一些代码。
答案1
我目前正在按照您想要的方式构建一个 django 应用程序。
我使用 docker-compose 来执行此操作。这是我的 docker-compose.yml
version: '2'
services:
nginx:
container_name: nginx-container
links:
- uwsgi
build: ./nginx
ports:
- "8888:80"
volumes_from:
- uwsgi
uwsgi:
container_name: uwsgi-container
build: ./uwsgi
expose:
- "8001"
volumes:
- ./code/conf:/opt/conf
- ./code/app:/opt/app
uWSGI的Dockerfile:
FROM python:3.5
RUN ["pip", "install", "uwsgi"]
CMD ["uwsgi", "--master", "--ini", "/opt/conf/uwsgi.ini"]
nginx 的 Dockerfile:
FROM nginx
RUN ["rm", "/etc/nginx/conf.d/default.conf"]
RUN ["ln", "-s", "/opt/conf/nginx.conf", "/etc/nginx/conf.d/"]
CMD ["nginx", "-g", "daemon off;"]
这是我的目录树:
├── README.md
├── code
│ ├── app
│ └── conf
├── collectstatic.sh
├── docker-compose.yml
├── install.sh
├── migrate.sh
├── nginx
│ └── Dockerfile
├── restart.sh
├── upgrade.sh
├── uwsgi
│ └── Dockerfile
因此,我使用构建我的图像,docker-compose build
然后在后台启动新的容器,然后docker-compose up -d
我可以执行一些设置任务,例如安装 django、生成密钥或任何您希望让您的容器准备好的任务。
nginx 和 uwsgi 容器使用共享卷来读取配置文件并与文件套接字进行通信。
嗯,不确定这是否是最好的方法,但这是一个正在进行的工作。
答案2
我从中找到了这个答案迈克尔·汉普顿:
“这仅当进程位于同一主机、虚拟机或容器中时才有效,因为它尝试连接到同一台机器。当它们位于不同的容器中时,它不起作用。
您需要改变您的 nginx 配置以便它使用 uwsgi 容器的内部 IP 地址。”
如果你将 Nginx 放在不同的容器中,你一定要记住一点,你还必须设置 nginx.conf,将静态文件目录指向别名,以防止出现安全问题。
我希望这个代码对每个人都有用,我花了几个小时才弄清楚如何组合 Gunicorn、docker 和 Nginx:
# nginx.conf
upstream djangoA {
server $DOCKER_CONTAINER_SERVICE:9000 max_fails=3 fail_timeout=0;
# In my case looks like: web:9000
}
Server {
include mime.types;
# The port your site will be served on
listen 80;
# the domain name it will serve for
server_name $YOUR_SERVER_NAME;# substitute your machine's IP address or FQDN
charset utf-8;
#Max upload size
client_max_body_size 512M; # adjust to taste
location /site_media {
alias $DIRECTORY_STATIC_FILES/site_media;#your Django project's media files have to be inside of the container have nginxs, you can copy them with volumes.
expires 30d;
}
location / {
try_files $uri @proxy_to_app;
}
# Finally, send all non-media requests to the Django server.
location @proxy_to_app {
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://djangoA;
}
}
对于docker-compose:
#production.yml
version: '2'
services:
db:
extends:
file: base.yml
service: db
nginx:
image: nginx:latest
volumes:
- ./nginx:/etc/nginx/conf.d/
- ./$STATIC_FILE_ROOT/site_media:/$STATIC_FILE_ROOT/site_media
ports:
- "80:80"
depends_on:
- web
web:
extends:
file: base.yml
service: web
build:
args:
- DJANGO_ENV=production
command: bash -c "python manage.py collectstatic --noinput && chmod 775 -R project/site_media/static && gunicorn project.wsgi:application"
volumes:
- ./$DIRECTORY_APP:/$DIRECTORY_APP
ports:
- "9000:9000"
depends_on:
- db
volumes:
db_data:
external: true
答案3
我最终成功为 Django、Gunicorn、Nginx 和 Postgres 构建了 docker-compose,这主要归功于本教程。
基本上,您有一个用于 Nginx 的容器、一个用于 Django+Gunicorn 的容器和一个用于 Postgres 的容器(如果您想要多个数据库,则可能有更多容器)。
您也可以将 Django+Gunicorn 拆分为两个容器,但我认为将它们都放在一个容器中更有意义,因为一个 Gunicorn 进程始终运行一个 Django wsgi 应用程序。我认为您不可能让 N 个 Gunicorn 运行 1 个 Django,也不可能让 1 个 Gunicorn 运行 N 个 Django,也不可能让 N 个 Gunicorn 运行 N 个 Django,因此这里没有扩展的可能性,除了扩展 N 个 Gunicorn+Django 容器。
卷用于永久保存数据库的数据(以及可选的 Django 的静态/媒体文件)。
您要求提供教程或其他方法,因此我不会在此处发布我的 docker-compose.yml 内容(因为它还需要 Dockerfile、Nginx conf 文件、Gunicorn conf 文件、数据库环境文件和许多 Python 代码片段,如数据库设置),但我会在有时间时尝试制作一个教程并在编辑/评论中发布链接。
同时,我上面提供的链接是一个很好的起点。
编辑:你现在可以看看这个docker 设置示例以及相关博客文章。