Docker基础知识 (10) - 使用 Docker 部署 Nginx + uWSGI + Django 项目
uWSGI 是一种 Web 服务器,用 C 语言编写的,它实现了 WSGI 协议、uwsgi、http 等协议。Nginx 中 HttpUwsgiModule 的作用是与uWSGI 服务器进行数据交换。WSGI 是一种 Web 服务器网关接口。它是一个 Web 服务器(如 nginx,uWSGI 等服务器)与 web 应用(如用 Flask、Django 框架写的程序)通信的一种规范。
uWSGI:https://projects.unbit.it/uwsgi
GitHub:https://github.com/unbit/uwsgi
Django 是一个开放源代码的 Web 应用框架,用 Python 语言编写的。采用了 MTV 的框架模式,即模型 M,模版 T 和视图 V。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统)软件。
Django:http://www.djangoproject.com
GitHub:https://github.com/django
1. 部署 uWSGI + Django
1) 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
uwsgi 目录:/home/docker/uwsgi # 在 Docker 所在主机上,手动创建各级目录,下同
2) 创建 uwsgi.ini 文件
$ cd /home/docker/uwsgi
$ vim uwsgi.ini
[uwsgi]
;socket=0.0.0.0:8001
http=0.0.0.0:8001
chdir=/home/docker/uwsgi/demo
wsgi-file=demo/wsgi.py
static-map=/static=/home/docker/uwsgi/demo/static
;processes=4
;threads=2
;master=True
buffer-size=65536
pidfile=/home/docker/uwsgi/uwsgi.pid
logto=/home/docker/uwsgi/uwsgi.log
注:与 nginx 配合时,使用 socket=0.0.0.0:8001。配置里的 demo 是一个 Django/3.0.1 项目,demo/wsgi.py 就是这个 Django 项目的 wsgi 入口文件。
本文配置 uwsgi.ini 时,demo 项目没创建,我们把创建 demo 项目的工作,放在安装好容器内的 Django/3.0.1 环境之后来完成。
static-map=/static=项目路径/static,配置静态文件目录,注意不要漏了前面的'/static=',第二个'/static' 是 Django 项目下的静态文件目录。
3) 创建 Dockerfile
$ cd /home/docker/uwsgi
$ vim Dockerfile
FROM python:3.8
RUN pip install -i https://mirrors.aliyun.com/pypi/simple uwsgi==2.0.18
RUN pip install -i https://mirrors.aliyun.com/pypi/simple django==3.0.1
EXPOSE 8001
CMD uwsgi --ini /home/docker/uwsgi/uwsgi.ini
注:也可以使用镜像网站 https://pypi.tuna.tsinghua.edu.cn/simple 。
4) 创建 python_uwsgi 镜像,并运行容器
$ cd /home/docker/uwsgi
# 创建镜像
$ docker build -t python_uwsgi:3.8-2.0.18 .
Sending build context to Docker daemon 75.26kB
Step 1/5 : FROM python:3.8
---> a08150c12a68
Step 2/5 : RUN pip install -i https://mirrors.aliyun.com/pypi/simple uwsgi==2.0.18
---> Running in 0467339ea511
Looking in indexes: https://mirrors.aliyun.com/pypi/simple
Collecting uwsgi==2.0.18
Downloading https://mirrors.aliyun.com/pypi/packages/e7/1e/3dcca007f974fe4eb369bf1b8629d5e342bb3055e2001b2e5340aaefae7a/uwsgi-2.0.18.tar.gz (801 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 801.6/801.6 KB 308.7 kB/s eta 0:00:00
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with status 'done'
Building wheels for collected packages: uwsgi
Building wheel for uwsgi (setup.py): started
Building wheel for uwsgi (setup.py): finished with status 'done'
Created wheel for uwsgi: filename=uWSGI-2.0.18-cp38-cp38-linux_x86_64.whl size=586592 sha256=8de601ca03a5bfd97b386a4927fec3b47d1fe38e7fb986db8f8e1315c3e34f50
Stored in directory: /root/.cache/pip/wheels/02/96/61/2a2ef285af8e7e610774d49a4fc82036dd2e1e9d4283b6071f
Successfully built uwsgi
Installing collected packages: uwsgi
Successfully installed uwsgi-2.0.18
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 22.0.4; however, version 22.2.2 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
Removing intermediate container 0467339ea511
---> b96f309dc0a0
Step 3/5 : RUN pip install -i https://mirrors.aliyun.com/pypi/simple django==3.0.1
---> Running in 6248e82ebb05
Looking in indexes: https://mirrors.aliyun.com/pypi/simple
Collecting django==3.0.1
Downloading https://mirrors.aliyun.com/pypi/packages/6a/23/08f7fd7afdd24184a400fcaebf921bd09b5b5235cbd62ffa02308a7d35d6/Django-3.0.1-py3-none-any.whl (7.4 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.4/7.4 MB 348.3 kB/s eta 0:00:00
Collecting asgiref~=3.2
Downloading https://mirrors.aliyun.com/pypi/packages/af/6d/ea3a5c3027c3f14b0321cd4f7e594c776ebe64e4b927432ca6917512a4f7/asgiref-3.5.2-py3-none-any.whl (22 kB)
Collecting sqlparse>=0.2.2
Downloading https://mirrors.aliyun.com/pypi/packages/05/40/d836d55fb3f467243ee839ab7b814822fda522cd395fa41e282684e71ee5/sqlparse-0.4.2-py3-none-any.whl (42 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.3/42.3 KB 369.2 kB/s eta 0:00:00
Collecting pytz
Downloading https://mirrors.aliyun.com/pypi/packages/d5/50/54451e88e3da4616286029a3a17fc377de817f66a0f50e1faaee90161724/pytz-2022.2.1-py2.py3-none-any.whl (500 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 500.6/500.6 KB 357.5 kB/s eta 0:00:00
Installing collected packages: pytz, sqlparse, asgiref, django
Successfully installed asgiref-3.5.2 django-3.0.1 pytz-2022.2.1 sqlparse-0.4.2
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 22.0.4; however, version 22.2.2 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
Removing intermediate container 6248e82ebb05
---> cdfc5eb0c54a
Step 4/5 : EXPOSE 8001
---> Running in 9f3e746cbab8
Removing intermediate container 9f3e746cbab8
---> b7f4c0483bd3
Step 5/5 : CMD uwsgi --ini /home/docker/uwsgi/uwsgi.ini
---> Running in c39ade6ffcc9
Removing intermediate container c39ade6ffcc9
---> 9b90e61f4d97
Successfully built 9b90e61f4d97
Successfully tagged python_uwsgi:3.8-2.0.18
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE python_uwsgi 3.8-2.0.18 9e05fd2ad4e0 27 seconds ago 957MB python 3.8 a08150c12a68 11 days ago 912MB ...
# 运行容器
$ docker run --name python_uwsgi-3.8 -p 8001:8001\
-v /home/docker/uwsgi:/home/docker/uwsgi\
--privileged=true\
-d python_uwsgi:3.8-2.0.18
$ docker exec -it python_uwsgi-3.8 /bin/bash # 进入容器
# 创建 Django 项目 root@1076fd112e8a:/# cd /home/docker/uwsgi root@1076fd112e8a:/home/docker/uwsgi# django-admin startproject demo root@1076fd112e8a:/home/docker/uwsgi# cd demo root@1076fd112e8a:/home/docker/uwsgi/demo# ls manage.py demo root@1076fd112e8a:/home/docker/uwsgi/demo# exit # 退出容器
# 在 Django 项目 demo/static 目录下添加 test.html
$ cd /home/docker/uwsgi/demo
$ mkdir static
$ cd static
$ vim test.html
<h3>uWSGI/Django - test.html</h3>
$ docker restart python_uwsgi-3.8 # 重启容器
python_uwsgi-3.8
$ docker exec -it python_uwsgi-3.8 /bin/bash # 再进入容器
# 访问动态文件,demo/wsgi.py root@1076fd112e8a:/# curl http://127.0.0.1:8001 <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="robots" content="NONE,NOARCHIVE"> <title>DisallowedHost at /</title> ... # 访问静态文件,demo/static/test.html root@1076fd112e8a:/# curl http://127.0.0.1:8001/static/test.html <h3>uWSGI/Django - test.html</h3>
浏览器访问 http://192.168.0.10:8001,动态页面显示结果如下:
DisallowedHost at / Invalid HTTP_HOST header: '192.168.0.10:8001'. You may need to add '192.168.0.10' to ALLOWED_HOSTS. Request Method: GET Request URL: http://192.168.0.10:8001/ Django Version: 3.0.1 Exception Type: DisallowedHost ...
注:访问 Django 页面成功,这个错误页面提示 192.168.0.10 不在 Django 配置的 ALLOWED_HOSTS。
浏览器访问 http://192.168.0.10:8001/static/test.html,静态页面显示结果如下:
uWSGI/Django - test.html
2. 部署 Nginx + uWSGI + Django
1) 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
2) 拉取 nginx 镜像
$ docker pull nginx # 相当于 docker pull nginx:latest
$ docker images # 查看镜像列表
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2b7d6430f78d 10 days ago 142MB
...
注:可以访问 Dockers Hub(https://hub.docker.com/_/nginx?tab=tags)查询 Nginx 镜像。
3) 修改 uwsgi.ini 文件
$ cd /home/docker/uwsgi
$ vim uwsgi.ini
[uwsgi] socket=0.0.0.0:8001 ;http=0.0.0.0:8001 chdir=/home/docker/uwsgi/demo wsgi-file=demo/wsgi.py static-map=/static=/home/docker/uwsgi/demo/static ;processes=4 ;threads=2 ;master=True buffer-size=65536 pidfile=/home/docker/uwsgi/uwsgi.pid logto=/home/docker/uwsgi/uwsgi.log
注:与 nginx 配合时,使用 socket=0.0.0.0:8001。
$ docker restart python_uwsgi-3.8 # 重启容器
python_uwsgi-3.8
4) 配置 nginx 为纯代理服务器
(1) 创建 nginx.conf 文件
在 Docker 所在主机上,创建 /home/docker/nginx/conf.d 目录,在该目录下创建 nginx.conf 文件。
server { listen 80 default_server; server_name localhost; location / { include uwsgi_params; uwsgi_pass python_uwsgi-3.8:8001; uwsgi_ignore_client_abort on; } }
参数说明:
server.location.uwsgi_pass: python_uwsgi-3.8:8001 表示 “容器名称:端口”,也可以写成 “ip:端口”,获取 ip 的方法,运行如下命令:
$ docker inspect --format='{{.NetworkSettings.IPAddress}}' python_uwsgi-3.8
172.17.0.2
(2) 创建 test2.html 文件
$ cd /home/docker/uwsgi/demo/static
$ vim test2.html
<h3>Nginx/uWSGI/Django - test2.html</h3>
注:这种模式下,静态文件由 uWSGI 处理,uwsgi.ini 配置的静态文件路径是 /home/docker/uwsgi/demo/static,也就是 Django 项目的 static 目录。
(3) 运行 nginx 容器
$ docker run --name nginx-uwsgi-3.8 -p 8888:80\
-v /home/docker/nginx/conf.d:/etc/nginx/conf.d\
--privileged=true\
--link python_uwsgi-3.8\
-d nginx
参数说明:
--name nginx-uwsgi-3.8:将容器命名为 nginx-uwsgi-3.8。
-p 8888:80:端口进行映射,将本地 8888 端口映射到容器内部的 80 端口。
-v:将本地文件夹与容器文件夹挂载。
--privileged=true:使用该参数,容器内的 root 拥有真正的 root 权限。否则,容器内的 root 只是外部的一个普通用户权限。
-d:设置容器在后台一直运行。
nginx: 这里表示 nginx:latest,镜像:tag。
$ docker ps # 查看运行的容器列表
浏览器访问 http://192.168.0.10:8888/,动态页面显示如下:
DisallowedHost at / Invalid HTTP_HOST header: '192.168.0.10:8888'. You may need to add '192.168.0.10' to ALLOWED_HOSTS. Request Method: GET Request URL: http://192.168.0.10:8888/ Django Version: 3.0.1 Exception Type: DisallowedHost ...
浏览器访问 http://192.168.0.10:8888/static/test2.html,静态页面显示如下:
Nginx/uWSGI/Django - test2.html
5) 配置 nginx 为动态文件的代理服务器,nginx 自己处理静态文件
(1) 创建 nginx.conf 文件
在 Docker 所在主机上,创建 /home/docker/nginx/conf.d 目录,在该目录下创建 nginx.conf 文件。
server { listen 80 default_server; server_name localhost; location / { include uwsgi_params; uwsgi_pass python_uwsgi-3.8:8001; uwsgi_ignore_client_abort on; } # nginx 自己处理 /static 对应的静态文件 root /usr/share/nginx/html; location /static { alias /usr/share/nginx/html; } }
参数说明:
a) server.location.uwsgi_pass: python_uwsgi-3.8:8001 表示 “容器名称:端口”,也可以写成 “ip:端口”,获取 ip 的方法,运行如下命令:
$ docker inspect --format='{{.NetworkSettings.IPAddress}}' python_uwsgi-3.8
172.17.0.2
b) server.root: /usr/share/nginx/html 是 nginx 容器内的路径。静态文件 (HTML/CSS/JS/Images 等文件)对应的映射目录是 /usr/share/nginx/html;
location /static: nginx 自己处理 /static 对应的静态文件
(2) 创建 test3.html 文件
$ cd /home/docker/nginx/html
$ vim test3.html
<h3>Nginx/uWSGI/Django - test3.html</h3>
注:这种模式下,静态文件由 nginx 处理,nginx 容器内的静态文件目录是 /usr/share/nginx/html,运行 nginx 容器会把 Docker 所在主机上的 /home/docker/nginx/html 挂载到 /usr/share/nginx/html。
Django 项目的 static 目录下的文件,需要复制到 /home/docker/nginx/html 下,或使用目录的软链接,才能被访问到。
(3) 运行 nginx 容器
$ docker run --name nginx-uwsgi-3.8 -p 8888:80\
-v /home/docker/nginx/html:/usr/share/nginx/html\
-v /home/docker/nginx/conf.d:/etc/nginx/conf.d\
--privileged=true\
--link python_uwsgi-3.8\
-d nginx
参数说明:
--name nginx-uwsgi-3.8:将容器命名为 nginx-uwsgi-3.8。
-p 8888:80:端口进行映射,将本地 8888 端口映射到容器内部的 80 端口。
-v:将本地文件夹与容器文件夹挂载。
--privileged=true:使用该参数,容器内的 root 拥有真正的 root 权限。否则,容器内的 root 只是外部的一个普通用户权限。
-d:设置容器在后台一直运行。
nginx: 这里表示 nginx:latest,镜像:tag。
$ docker ps # 查看运行的容器列表
浏览器访问 http://192.168.0.10:8888/,动态页面显示如下:
DisallowedHost at / Invalid HTTP_HOST header: '192.168.0.10:8888'. You may need to add '192.168.0.10' to ALLOWED_HOSTS. Request Method: GET Request URL: http://192.168.0.10:8888/ Django Version: 3.0.1 Exception Type: DisallowedHost
浏览器访问 http://192.168.0.10:8888/static/test3.html,静态页面显示如下:
Nginx/uWSGI/Django - test3.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步