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


posted @   垄山小站  阅读(1604)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示