用Docker部署Django+uWSGI+Nginx

用Docker部署Django+uWSGI+Nginx

  • 本文是在一个Centos容器中安装Python、Django、uWSGI、Nginx等软件,运行Django项目,最后生成Docker镜像。同时,在任意一台Linux主机上安装MySQL服务器。
  • 练手时可以把这些软件都在一个容器内启动。实际应用时将每个软件单独运行在一个容器中,隔离开来。比如 Django 独占一个容器、 Nginx 独占一个容器。这样停止一个容器时只会停止一个服务,其它服务不受影响。

部署目标分为几个层次:

  1. 部署 Python + Django + Mysql ,此时能启动 Django 自带的测试服务器,给测试环境足够用了。
  2. 再部署 uWSGI 服务器,用它启动 Django 项目(而不是自带的测试服务器),算是正式部署。
  3. 再部署 Nginx 服务器,为 uWSGI 服务器做 HTTP 代理,优化服务器的性能。适用于生产环境。
    • 代理原理:让 uWSGI 监听 79 端口,Nginx 监听 80 端口。当Nginx收到客户端访问80端口的HTTP请求时,就转发到79端口,由uWSGI处理。最后返回响应报文给客户端。

创建Centos容器

  1. 登录一台Linux主机,安装docker软件。

    yum install docker-ce     # 安装docker社区版
    
    • 如果安装时报错找不到该package,就试着添加docker官方的镜像源:
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    
  2. 试用docker,如果安装成功的话会显示一些欢迎信息。

    systemctl start docker    # 启动docker服务
    docker run hello-world
    
  3. 创建一个Centos容器,让它在后台运行。

    docker run -d --name deploy1 --network host centos:7 tail -f /dev/null
    
        -d                # 让它以daemon方式在后台运行
        --name deploy1    # 设置容器的名称
        --network host    # 让它使用宿主机的网卡,使得容器监听的所有端口直接暴露在宿主机上
        centos:7          # 要运行的镜像及其版本
        tail -f /dev/null # 让容器一直执行某条命令,以免没有任务而自动退出
    
  4. 进入Centos容器。

    docker exec -it deploy1 bash
    
        -it     # 打开该容器的输入(stdin)和终端(tty)
        bash	# 在容器中执行bash命令,启动一个shell,供用户操作
    
  5. Ctrl+D退出容器。 将Django项目的源代码从宿主机拷贝到Centos容器中:

    docker cp /root/django deploy1:/root/
    
  6. 之后便可以在Centos容器里部署Django项目,不满意就销毁重建。

    docker ps                    # 列出所有运行中的容器
    docker stop <容器名或ID>     # 终止一个运行中的容器
    

安装Python及pip

  1. 进入容器中的Django项目目录

  2. 安装Python解释器:

    yum install epel-release		# 添加epel软件库
    yum install python34			  # 安装指定版本的python
    
  3. 安装pip

    yum install python34-pip    # 安装指定版本的pip
    
  4. 然后用pip安装Django项目需要的Python第三方库。

    • 如果项目目录下有一个requirements.txt,则可以用 pip3 install -r requirements.txt 一键安装所有第三方库。
    • 如果某些依赖库没有成功安装,则后面尝试运行Django测试服务器就可能报错,可以到那个时候再根据报错信息安装它。

安装依赖库的过程挺麻烦,可能少安装了某些依赖库、安装了多余的东西,也可能安装了错误的版本,甚至无法下载或安装。还好,遇到的报错大多可以在网上搜到解决方案。


安装MySQL

任选一台主机来安装MySQL:

wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
yum install mysql57-community-release-el7-10.noarch.rpm		# 添加mysql5.7的yum源
yum install mysql-community-server                        # 安装mysql
systemctl start mysqld                                    # 启动mysql服务器

cat /var/log/mysqld.log | grep password                   # 查看初始密码
mysql -u root -p                                          # 登录mysql客户端,此时需要输入初始密码
set password for "root"@"localhost" = password("******"); # 第一次登录时要修改root的密码

create user "user1"@"%" identified by "******";  	        # 创建一个用户
create database db1 default character set utf8mb4;        # 创建一个database
grant all on db1.* to "user1"@"%";                        # 给用户分配权限

使Django连接到MySQL

  1. 进入容器中的Django项目目录,在某个子文件夹中找到settings.py,按如下格式修改数据库信息:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',   # 数据库引擎,不用改
            'NAME': 'db1',          # database名,需要在mysql中已存在
            'USER': 'user1',
            'PASSWORD': '******',
            'HOST': '172.24.0.1',
            'PORT': '3306',
        }
    }
    
  2. 执行以下命令初始化数据库。

    python3 manage.py makemigrations
    python3 manage.py migrate
    

尝试运行Django测试服务器

进入容器中的项目目录,输入以下命令,启动Django测试服务器:

python3 manage.py runserver 0.0.0.0:80

启动后,另开一个终端,执行命令curl 127.0.0.1:80,如果看到Web首页的html,则说明该Django应用可以运行。(也可以在浏览器中尝试访问它)

然后停止测试服务器,继续之后的部署。

如果出现报错,则需要根据报错信息排查错误。常见的错误包括:

  • Python解释器没安装成功,或版本不对
  • 缺少Django项目的依赖库,或版本不对
  • 不能通过网络连接到数据库,或者没有数据库的操作权限
  • Django项目的代码本身有Bug

运行uWSGI服务器

  1. 安装依赖库:yum install build-essential python-devel

  2. 安装uWSGI:pip install uwsgi

  3. 进入Django项目目录,执行mkdir uwsgi,创建一个uwsgi文件夹。再执行vi uwsgi/uwsgi.ini,在其下创建一个uwsgi.ini,作为配置文件。其内容如下:

    [uwsgi]
    
    http = 0.0.0.0:79        ; 监听来自哪些IP地址、发送到哪个端口的HTTP请求
    ; socket = 127.0.0.1:79  ; 通过socket与Nginx通信,更快
    
    chdir = /root/django     ; 设置工作目录
    
    wsgi-file = %(chdir)/app0/wsgi.py     ; 指明wsgi.py的位置
    daemonize = %(chdir)/uwsgi/uwsgi.log  ; 设置保存日志的位置
    pidfile = %(chdir)/uwsgi/uwsgi.pid    ; 设置保存pid文件的位置
    
  4. 使用配置文件启动uWSGI服务器(默认在后台运行):uwsgi --ini uwsgi/uwsgi.ini

  5. 执行curl 127.0.0.1:79,如果看到Web首页的html,则说明运行成功。
    如果显示以下报错,则可能是服务器没有启动,或者IP地址、端口号填错了。

    Failed connect to 127.0.0.1:79; Connection refused
    
  6. 停止uWSGI服务器:uwsgi --stop uwsgi/uwsgi.pid


运行Nginx服务器

  1. 安装Nginx:yum install nginx

  2. 修改Nginx的配置文件 vi /etc/nginx/nginx.conf
    修改http{…}中的server{…}部分,格式如下:

    server {
        listen  80;              # nginx监听的端口
    
        charset  utf-8;
    
        # 设置保存日志的目录
        access_log  /var/log/nginx/access.log;
        error_log  /var/log/nginx/error.log;
    
        # Load configuration files for the default server block.
        include  /etc/nginx/default.d/*.conf;
    
        # 设置网站的根目录
        location / {
            # 连接uwsgi服务器时的配置文件
            include    /etc/nginx/uwsgi_params;
    
            # 如果有HTTP请求访问该网站,Nginx就转发给uwsgi服务器
            uwsgi_pass    127.0.0.1:79;
        }
    
        # 设置静态文件的目录
        location /static/ {
            alias /root/django/static/;
        }
    
        # 将404页面重定向到根目录下的/404.html
        error_page 404 /404.html;
            location = /40x.html {
        }
    
        # 将500~504页面重定向到根目录下的/50x.html
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
    
  3. 先启动uWSGI服务器,再用nginx启动nginx服务器(默认作为守护进程运行)。

  4. 执行curl 127.0.0.1:80,如果看到Web首页的html,则说明运行成功。
    如果显示以下报错,则可能是服务器没有启动,或者IP地址、端口号填错了。

    Failed connect to 127.0.0.1:80; Connection refused
    
  5. 停止nginx服务器:nginx -s quit


制作Docker镜像

部署的最后环节:

  • 如果成功部署了Django项目,可以把它制作成一个Docker镜像,便于移植到其它主机上直接运行。

  • 要求不严时,可以执行以下命令,将之前部署完成的Centos容器直接打包成一个Docker镜像,不过这会保留一些冗余数据,且不方便以后的修改。

    docker commit deploy1 deploy:v1
        # 将名为deploy1的容器打包成镜像,镜像名为deploy,版本为v1
    
  • 正式使用时,应该编写一个Dockerfile文件,记录部署的主要过程。根据它生成Docker镜像。

    • 本文的Dockerfile的大致内容:

      FROM centos:7
      
      WORKDIR /root/django/
      COPY . .
      
      RUN yum -y install epel-release && \
          yum -y install python34 && \
          yum -y install python34-pip && \
          pip3 install -r requirements.txt && \
          yum -y install nginx
      
      EXPOSE 80
      
      ENTRYPOINT run.sh
      
      • ENTRYPOINT用于执行一些容器刚启动时的初始化命令,可以把这些命令打包成一个.sh脚本一起执行。
    • 根据Dockerfile构建Docker镜像:

      docker build . –t deploy:v1 --network host
      
          .               # 指明Dockerfile的位置
          -t deploy:v1    # 设置镜像名字、版本号
          --network host  # 允许在构建镜像的过程中连到外网
      
    • 查看镜像,可以把它推送到远端的镜像仓库。

      docker images
      docker push ...
      
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值