博客 / 詳情

返回

nginx和uwsgi部署Django項目

一、防火牆和端口設置

  • 開啓防火牆:systemctl start firewalld
  • 關閉防火牆:systemctl stop firewalld
  • 查看防火牆狀態:systemctl status firewalld
  • 重啓防火牆:systemctl restart firewalld
  • 設置開機自啓:systemctl enable nginx firewalld
  • 查看開放端口列表:firewall-cmd --list-ports
  • 開放指定的端口:firewall-cmd --zone=public --add-port=端口號/tcp --permanent

    需要注意的是:開放端口之後需要重啓防火牆才能生效

二、項目環境安裝

  • 依賴安裝

    yum install python3-devel zlib-devel mysql-devel libffi-devel bzip2-devel openssl-devel java wget gcc
  • 安裝nginx

    yum install nginx
  • 安裝redis和mysql

    yum install mysql-server
    yum install redis
  • 安裝python進程管理工具supervisor

    yum install supervisor
  • 設置開機啓動

    systemctl enable redis mysqld nginx supervisord

    注意:

    1. mysql安裝之後默認不會啓動,需要使用systemctl start mysqld.service來啓動,或者mysqld.service替換為mysqld
    2. 設置開機自啓動時是mysqld和supervisord,不是mysql和supervisor
  • 安裝python3.7

    • 下載源碼包:wget https://www.python.org/ftp/py...
    • 解壓:tar -xf Python-3.7.8rc1.tar.xz
    • 在/usr/local下新建python3目錄,用於安裝python3.7.8
    • 進入python3.7.8源碼包安裝:./configure --prefix=/usr/local/python3 --enable-optimizations
    • 執行命令:make && make install,吐過上一步添加了--enable-optimizations,這一步會比較耗時間,這個參數可以不加
    • 把python3和pip3軟連接到/usr/bin上:

      • 軟連接python3:ln /usr/local/python3/bin/python3 /usr/bin/python3
      • 軟連接pip3:ln /usr/local/python3/bin/pip3 /usr/bin/pip3
      問題:使用pip3 install -r requirements.txt安裝依賴時,報錯:Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-ifh_bc24/cryptography/
      解決方法:命令行pip3 install --upgrade setuptools,然後重試

三、Django部署中nginx設置

  • nginx配置文件

    # For more information on configuration, see:
    #   * Official English Documentation: http://nginx.org/en/docs/
    #   * Official Russian Documentation: http://nginx.org/ru/docs/
    
    user root;
    worker_processes auto;
    error_log /var/log/nginx/error.log;
    pid /run/nginx.pid;
    
    # Load dynamic modules. See /usr/share/nginx/README.dynamic.
    #include /usr/share/nginx/modules/*.conf;
    
    events {
      worker_connections 1024;
    }
    
    http {
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
    
      access_log  /var/log/nginx/access.log  main;
    
      sendfile            on;
      tcp_nopush          on;
      tcp_nodelay         on;
      keepalive_timeout   65;
      types_hash_max_size 2048;
    
      include             /etc/nginx/mime.types;
      default_type        application/octet-stream;
    
      # Load modular configuration files from the /etc/nginx/conf.d directory.
      # See http://nginx.org/en/docs/ngx_core_module.html#include
      # for more information.
      include /etc/nginx/conf.d/*.conf;
    
      upstream uwsgi_backend {  # http請求轉發配置
          server localhost:8888;
      }
    
      upstream channels-backend {  # websocket請求轉發配置
          server localhost:8000;
      }
    
      server {
          listen       80 default_server;
          listen       [::]:80 default_server;
          server_name  www.ejpro.top; # 顯示在瀏覽器上的名稱
          charset utf-8;
          client_max_body_size 75M; #客户端請求體最大的限制
    
          # Load configuration files for the default server block.
          include /etc/nginx/default.d/*.conf;
    
    
          ##### 靜態文件設置
          location /static/ {
              root  /home/tourism;  # static文件所在的目錄路徑
          }
    
          location /media/ {
              root  /home/tourism;  # media文件所在的目錄路徑
          }
    
    
          #### 動態轉發請求
          location / {
              uwsgi_pass 127.0.0.1:8001;
              include /etc/nginx/uwsgi_params; # 指向的是nginx,Django本身沒有該文件
          }
      }
    }
    
  • 注意事項:

    • 註釋掉include /usr/share/nginx/modules/*.conf,如果不註釋這行nginx會默認使用/etc/nginx/nginx.conf.default文件,註釋掉後nginx就會使用nginx.conf的配置
    • 靜態文件路徑配置,static和media的配置路徑都只能寫到上一層,不能包含static和media這一層,這一點必須要注意,否則會出現如下錯誤:

      [error] 14635#0: *49 open() "/home/tourism/static/static/admin/simpleui-x/particles/particles.js"
      # 多寫了一層static
    • 動態請求中需要注意的是:uwsgi_params路徑在/etc/nginx下,Django本身沒有該文件

四、uwsgi.ini配置

  • 配置文件

    [uwsgi]
    # Django manage.py 所在文件夾路徑
    #Django項目源碼目錄
    chdir = /home/tourism
    # Django系統的uwsgi,如果不記得可以從settings.py文件中WSGI_APPLICATION查看
    module = project.wsgi:application
    # 啓用master進程管理
    master = true
    # 綁定的 UNIX socket
    socket = 127.0.0.1:8888
    # uwsgi的進程數
    processes = 4
    # 重啓進行耗時超過30秒就關閉
    harakiri = 30
    # 最大請求處理數,之後重新生成進程
    max-requests = 5000
    # 退出時清理環境
    vacuum = true
    # socket
    socket = 127.0.0.1:8001
    # uid
    uid = 1000
    # gid
    gid = 2000
    
    
    # pidfile路徑
    pidfile = /home/tourism/deploy/sub/master.pid
    # deamonize日誌文件路徑
    deamonize = /home/tourism/deploy/sub/tourism.log
    # 當服務器關閉或退出時是否清除pidfile和deamonize文件
    vacuum=True
    
    static-map = /static = /home/tourism/static
  • 如果部署上線後項目在虛擬環境中,還需要另外配置home參數,即python的虛擬環境。如果沒有虛擬環境,不需要配置該項
  • 需要配置static-map = /static = /home/tourism/static

六、nginx配置SSL使用https

  • 到雲平台申請域名和SSL證書,企業用户付費可以得到純IP綁定的SSL證書,個人用户不支持,所以域名是必須的,各個平台上都有免費的個人證書,本次使用的是華為雲
  • 域名申請後,需要把域名解析到ECS雲服務器上,填寫公網IP
  • 到SSL證書管理頁面下載SSL證書到本地,找到Nginx結尾的包,把裏邊crt和key結尾的兩個文件改一個名字,改名這一步不是必須的。
  • 在雲服務器上的/etc/nginx目錄下新建cert文件夾用於存放nginx的SSL證書,通過SFTP把本地的兩個證書上傳到雲服務器中/etc/nginx/cert目錄。
  • 配置nginx.conf文件

    user root;
    worker_processes auto;
    error_log /var/log/nginx/error.log;
    
    
    events {
      worker_connections 1024;
    }
    
    http {
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
    
      access_log  /var/log/nginx/access.log  main;
    
      sendfile            on;
      tcp_nopush          on;
      tcp_nodelay         on;
      keepalive_timeout   65;
      types_hash_max_size 2048;
    
      include             /etc/nginx/mime.types;
      default_type        application/octet-stream;
    
      upstream uwsgi_backend {  # http請求轉發配置
          server localhost:8888;
      }
    
      upstream channels-backend {  # websocket請求轉發配置
          server localhost:8000;
      }
    
      server {
          listen 80;
          server_name SSL證書綁定的域名;
          rewrite ^/(.*) https://$server_name$1 permanent; #當使用的是http時跳轉到Https
      }
    
      server {
          listen 443;
          charset utf-8;
          client_max_body_size 75M; #客户端請求體最大的限制
    
          ssl          on;
          server_name  SSL證書綁定的域名;
          ssl_certificate      /etc/nginx/cert/server.crt; #替換成您的證書文件的路徑。
          ssl_certificate_key  /etc/nginx/cert/server.key; #替換成您的私鑰文件的路徑。
          ssl_session_cache    shared:SSL:1m;
          ssl_session_timeout  5m;
          ssl_ciphers  HIGH:!aNULL:!MD5; #加密套件。
          ssl_prefer_server_ciphers  on;
    
          ##### 靜態文件設置
          location /static/ {
              root  /home/tourism;  # static文件所在的目錄路徑
          }
    
          location /media/ {
              root  /home/tourism;  # media文件所在的目錄路徑
          }
    
          #### 動態轉發請求
          location / {
              uwsgi_pass 127.0.0.1:8001;
              include /etc/nginx/uwsgi_params; # 指向的是nginx,Django本身沒有該文件
          }
      }
    }
    
  • 第一個server是設置http服務的,嚴格來説,如果使用https加密服務,那麼不用再設置http這種不安全的傳輸服務。要是必須使用的話,可以設置訪問http服務時定向跳轉到https服務。這一個設置也是可以省略的。

    server {
          listen 80;
          server_name SSL證書綁定的域名;
          rewrite ^/(.*) https://$server_name$1 permanent; #當使用的是http時跳轉到Https
      }
  • 在雲服務器的安全規則中設置允許443端口訪問的規則
  • 在雲服務器上命令行開啓443端口訪問
  • 重啓nginx服務

    nginx -s reload    # 重新加載nginx配置文件
    nginx -t   # 查看nginx是否正常
    systemctl restart nginx    # 重啓nginx服務
  • 到這一步就可以通過https服務成功訪問域名了。

    七、小坑

  • 問題一:部署上線後靜態文件加載不了
  • 解決辦法:

    • nginx中把第一行 user nginx改成user root,提高權限
    • nginx中的static和media配置路徑,路徑不能包括static和media
    • 配置Django項目和靜態資源文件路徑,需要特別注意的是:如果media和static目錄下還有子目錄,只設置這兩個目錄的權限會報權限禁止的錯誤,需要要使用chmod 777 子目錄命令對所有子目錄進行權限的設置。
    • 在uwsgi.ini中添加static-map = /static = static的絕對路徑
    • 收集靜態文件:python3 manage.py collectstatic
    • 注意查看settings.py文件中的static和media路徑配置是否正確
  • 問題二:使用firewall-cmd --list-ports查看端口時報錯ModuleNotFoundError: No module named 'six'
  • 解決辦法:命令行輸入

    cp /usr/local/lib/python3.6/site-packages/six.py /usr/lib/python3.6/site-packages/
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.