使用docker-compose部署nginx+gunicorn+mariadb的django應用

来源:https://www.cnblogs.com/luizyao/archive/2019/10/26/11741695.html
-Advertisement-
Play Games

我們來使用 docker-compose 並基於 gunicorn + mariadb + nginx 部署一個簡單的 django 博客應用; ...


目錄

我們來使用 docker-compose 並基於 gunicorn + mariadb + nginx 部署一個簡單的 django 博客應用;

1. docker-compose 項目的組織目錄

.                                              
├── django-blog                                
│   ├── blogproject                            
│   │   ├── __init__.py                        
│   │   ├── settings.py                        
│   │   ├── urls.py                            
│   │   └── wsgi.py                            
│   ├── Dockerfile                             
│   ├── manage.py                              
│   ├── requirements.txt                       
│   └── static                                 
├── docker-compose.yaml                        
├── mysql                                      
│   ├── conf                                   
│   │   └── django-blog.cnf                    
│   └── data                                   
└── nginx                                      
    ├── conf                                   
    │   └── mysite.template                    
    ├── log                                    
    └── ssl     

2. 構建 mysql 容器

mysql/
├── conf
│   └── django-blog.cnf
└── data
  • 配置資料庫使用utf8mb4編碼:

    # mysql/conf/django-blog.cnf
    
    [client]
    default-character-set = utf8mb4
    
    [mysql]
    default-character-set = utf8mb4
    
    [mysqld]
    character-set-client-handshake = FALSE
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    init_connect='SET NAMES utf8mb4'
  • docker-compose.yaml 中 mysql service 的配置:

    db:
        image: mariadb:10.4
        container_name: django-blog-db
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: <root 用戶的密碼>
            MYSQL_DATABASE: <容器啟動時,自動創建的資料庫名>
            MYSQL_USER: <容器啟動時,自動創建的資料庫用戶,其對上述資料庫擁有全部的許可權>
            MYSQL_PASSWORD: <上述資料庫用戶的密碼>       
        volumes:
            - ./mysql/conf:/etc/mysql/conf.d  # 掛載自定義配置目錄,即上述的 mysql/conf/django-blog.cnf 中的配置
            - ./mysql/data:/var/lib/mysql  # 掛載數據目錄
            - ./mysql/log:/var/log  # 掛載日誌目錄
  • 為什麼不用 mysql,而是使用 mariadb ?

    mysql:latest 預設的認證方式變為caching_sha2_password,直接使用會報錯:Authentication plugin 'caching_sha2_password' cannot be loaded

    使用 mariadb:latest 或者使用 mysql:5.7 是沒有問題的;

    關於這個問題的討論可以參考如下鏈接,裡面提到一些規避的方法:

3. 構建 django-blog 容器

django-blog/
├── blogproject
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── Dockerfile
├── manage.py
├── requirements.txt  # 包依賴
└── static  # python manage.py collectstatic 命令收集到的靜態文件的目錄
  • 編寫 Dockerfile:

    FROM python:3.7-alpine  # 使用 alpine 版本,精簡 image 體積;
    RUN echo "https://mirrors.ustc.edu.cn/alpine/latest-stable/main" > /etc/apk/repositories \
        && apk update \
        # alpine 中 mariadb 代替了 mysql: <https://alpinelinux.org/posts/Alpine-3.2.0-released.html>
        && apk add mariadb-dev build-base
    RUN mkdir /code
    WORKDIR /code
    COPY requirements.txt ./
    RUN pip install --no-cache-dir -r requirements.txt

    其中, requirements.txt 內容為:

    -i https://mirrors.aliyun.com/pypi/simple
    Django==2.2.5
    django-haystack==2.8.1
    gunicorn==19.9.0
    jieba==0.39
    Markdown==3.1.1
    mysqlclient==1.4.4
    Whoosh==2.7.4
  • docker-compose.yaml 中 web service 的配置:

    web:
        build: django-blog/
        image: django-blog:2.2.5  # 構建後,image 的名字,2.2.5是目前使用的 django 版本
        container_name: django-blog-web
        restart: always
        depends_on:
            - db
        volumes:
             - ./django-blog:/code  # 掛載項目代碼
             # - /code/static   # 可以選擇不掛載項目代碼中的 static 文件夾;https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder#
        command: /bin/bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn blogproject.wsgi -w 3 -k gthread -b 0.0.0.0:8000"
        ports:
            - "8000:8000"
        environment:  # settings.py 中可以使用到的環境變數
            DB_NAME: <mysql 容器中配置的資料庫>
            DB_USER: <mysql 容器中配置的資料庫用戶>
            DB_PASS: <mysql 容器中配置的資料庫用戶的密碼>
            DB_PORT: 3306
            DJANGO_SECRET_KEY: "<django 密鑰>"
  • 修改 django-blog/blogproject/settings.py 文件相關項:

    import os
    
    _env = os.environ
    
    # 使用上述定義的環境變數代替具體值
    DATABASES = {
        # 'default': {
        #     'ENGINE': 'django.db.backends.sqlite3',
        #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        # }
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': _env['DB_NAME'],
            'USER': _env['DB_USER'],
            'PASSWORD': _env['DB_PASS'],
            'HOST': 'db',  # docker-compose.yaml 中資料庫的服務名
            'PORT': _env['DB_PORT'],  # 預設的服務埠號
            'OPTIONS': {
                # 存儲引擎啟用嚴格模式,非法數據值被拒絕
                'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
                'charset': 'utf8mb4',
            },
        }
    }
    
    # 安全考慮,不要直接顯示密鑰,定義在容器的環境變數中
    SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
    
    # 生產環境不要將其置為 True
    DEBUG = False

4. 構建 nginx 容器

nginx/
├── conf
│   └── mysite.template  # 用戶配置
├── log
└── ssl  # 存放證書
  • docker-compose.yaml 中 nginx service 的配置:

    nginx:
        image: nginx:stable  # 使用穩定版
        container_name: django-blog-nginx
        restart: always
        depends_on:
            - web
        ports:
            - 80:80
            - 443:443
        environment:  # 定義環境變數
            NGINX_HOST: luizyao.com
            NGINX_PORT: 80
            NGINX_SSL_PORT: 443
            WEB_PORT: 8000
        volumes:
            # 用戶配置目錄
            - ./nginx/conf/mysite.template:/etc/nginx/conf.d/mysite.template
            # ssl 證書目錄
            - ./nginx/ssl:/etc/nginx/ssl
            # 靜態文件,即 python manage.py collectstatic 命令收集到的靜態文件的目錄
            - ./django-blog/static:/data/apps/django-blog/static
            # 日誌
            - ./nginx/log/:/var/log/nginx/
        command: /bin/bash -c "envsubst '$$NGINX_HOST $$NGINX_PORT $$NGINX_SSL_PORT $$WEB_PORT' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"  # 只有這幾個變數需要轉義:'$$NGINX_HOST $$NGINX_PORT $$NGINX_SSL_PORT $$WEB_PORT',否則會報錯
  • 編寫 mysite.template 文件:

    upstream django-blog {
            server web:${WEB_PORT};
    }
    
    server {
            charset utf-8;
            listen ${NGINX_PORT};
            server_name ${NGINX_HOST};
    
            rewrite ^(.*)$ https://${server_name}$1 permanent;
    }
    
    server {
            listen ${NGINX_SSL_PORT} ssl http2 default_server;
            server_name ${NGINX_HOST};
    
            ssl_certificate /etc/nginx/ssl/1_www.luizyao.com_bundle.crt;
            ssl_certificate_key /etc/nginx/ssl/2_www.luizyao.com.key;
            ssl_session_timeout 5m;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
            ssl_prefer_server_ciphers on;
    
            location /static {
                    alias /data/apps/django-blog/static;
            }
    
            location / {
                    proxy_pass http://django-blog;
                    proxy_redirect    off;
                    proxy_set_header  Host $http_host;
                    proxy_set_header  X-Real-IP $remote_addr;
            }
    
            error_page 404 /404.html;
            location = /40x.html {}
    
            error_page 500 502 503 504 /50x.html;
            location = /50x.html {}
    }

5. docker-compose.yaml 文件

version: '3.7'  # docker 版本:18.06.0+

services:
    db:
        image: mariadb:10.4 
        container_name: django-blog-db
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: <root 用戶的密碼>
            MYSQL_DATABASE: <容器啟動時,自動創建的資料庫名>
            MYSQL_USER: <容器啟動時,自動創建的資料庫用戶,其對上述資料庫擁有全部的許可權>
            MYSQL_PASSWORD: <上述資料庫用戶的密碼>       
        volumes:
            - ./mysql/conf:/etc/mysql/conf.d  # 掛載自定義配置
            - ./mysql/data:/var/lib/mysql  # 掛載數據存儲目錄
            - ./mysql/log:/var/log  # 掛載日誌存儲目錄
            
    web:
        build: django-blog/
        image: django-blog:2.2.5  # 構建後,image 的名字,2.2.5是目前使用的 django 版本
        container_name: django-blog-web
        restart: always
        depends_on:
            - db
        volumes:
             - ./django-blog:/code  # 掛載項目代碼
             # - /code/static   # 可以選擇不掛載項目代碼中的 static 文件夾;https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder#
        command: /bin/bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn blogproject.wsgi -w 3 -k gthread -b 0.0.0.0:8000"
        ports:
            - "8000:8000"
        environment:  # settings.py 中可以使用到的環境變數
            DB_NAME: <mysql 容器中配置的資料庫>
            DB_USER: <mysql 容器中配置的資料庫用戶>
            DB_PASS: <mysql 容器中配置的資料庫用戶的密碼>
            DB_PORT: 3306
            DJANGO_SECRET_KEY: "<django 密鑰>"

    nginx:
        image: nginx:stable  # 使用穩定版
        container_name: django-blog-nginx
        restart: always
        depends_on:
            - web
        ports:
            - 80:80
            - 443:443
        environment:  # 定義環境變數
            NGINX_HOST: luizyao.com
            NGINX_PORT: 80
            NGINX_SSL_PORT: 443
            WEB_PORT: 8000
        volumes:
            # 用戶配置目錄
            - ./nginx/conf/mysite.template:/etc/nginx/conf.d/mysite.template
            # ssl 證書目錄
            - ./nginx/ssl:/etc/nginx/ssl
            # 靜態文件,即 python manage.py collectstatic 命令收集到的靜態文件的目錄
            - ./django-blog/static:/data/apps/django-blog/static
            # 日誌
            - ./nginx/log/:/var/log/nginx/
        command: /bin/bash -c "envsubst '$$NGINX_HOST $$NGINX_PORT $$NGINX_SSL_PORT $$WEB_PORT' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"  # 只有這幾個變數需要轉義:'$$NGINX_HOST $$NGINX_PORT $$NGINX_SSL_PORT $$WEB_PORT',否則會報錯

6. docker-compose up 啟動服務組

[luizyao@centos_7_6_1810 blog]$ docker-compose up
Creating network "blog_default" with the default driver
Creating django-blog-db ... done
Creating django-blog-web ... done
Creating django-blog-nginx ... done
Attaching to django-blog-db, django-blog-web, django-blog-nginx
django-blog-db | 2019-09-24  8:45:41 0 [Note] mysqld (mysqld 10.4.8-MariaDB-1:10.4.8+maria~bionic) starting as process 1 ...
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Using Linux native AIO
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Uses event mutexes
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Number of pools: 1
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Using SSE2 crc32 instructions
django-blog-db | 2019-09-24  8:45:41 0 [Note] mysqld: O_TMPFILE is not supported on /tmp (disabling future attempts)
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: Completed initialization of buffer pool
django-blog-db | 2019-09-24  8:45:41 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: 128 out of 128 rollback segments are active. django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: Creating shared tablespace for temporary tables
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: Waiting for purge to start
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: 10.4.8 started; log sequence number 21042225; transaction id 15378
django-blog-db | 2019-09-24  8:45:42 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
django-blog-db | 2019-09-24  8:45:42 0 [Note] Plugin 'FEEDBACK' is disabled.
django-blog-db | 2019-09-24  8:45:42 0 [Note] Server socket created on IP: '::'.
django-blog-db | 2019-09-24  8:45:42 0 [Note] Reading of all Master_info entries succeeded
django-blog-db | 2019-09-24  8:45:42 0 [Note] Added new Master_info '' to hash table
django-blog-db | 2019-09-24  8:45:42 0 [Note] mysqld: ready for connections.
django-blog-db | Version: '10.4.8-MariaDB-1:10.4.8+maria~bionic'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution
django-blog-web | No changes detected
django-blog-db | 2019-09-24  8:45:43 0 [Note] InnoDB: Buffer pool(s) load completed at 190924  8:45:43
django-blog-web | Operations to perform:
django-blog-web |   Apply all migrations: admin, auth, blog, comment, contenttypes, sessions
django-blog-web | Running migrations:
django-blog-web |   No migrations to apply.
django-blog-web | [2019-09-24 08:45:44 +0000] [1] [INFO] Starting gunicorn 19.9.0
django-blog-web | [2019-09-24 08:45:44 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
django-blog-web | [2019-09-24 08:45:44 +0000] [1] [INFO] Using worker: gthread
django-blog-web | [2019-09-24 08:45:44 +0000] [10] [INFO] Booting worker with pid: 10
django-blog-web | [2019-09-24 08:45:44 +0000] [11] [INFO] Booting worker with pid: 11
django-blog-web | [2019-09-24 08:45:44 +0000] [12] [INFO] Booting worker with pid: 12

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、斷開原因 WebSocket斷開的原因有很多,最好在WebSocket斷開時,將錯誤列印出來。 錯誤狀態碼: WebSocket斷開時,會觸發CloseEvent, CloseEvent會在連接關閉時發送給使用 WebSockets 的客戶端. 它在 WebSocket 對象的 onclose ...
  • 待補充 ...
  • 領域建模有很多種方法,對於同樣的問題域使用不同的建模手段得到的模型可能也不盡相同。於是我經常聽到這樣一個問題:怎麼才能保證建模的正確性? 領域建模有很多種方法,對於同樣的問題域使用不同的建模手段得到的模型可能也不盡相同。於是我經常聽到這樣一個問題:怎麼才能保證建模的正確性? 這聽起來是個合理的質疑, ...
  • 1.安裝Tomcat並配置啟動 2.Tomcat部署項目 網市場 1.配置server.xml文件 ,新增在 engline內 2.創建站點目錄,上傳源碼包 3.使用mvn編譯 4.Nginx配置反向代理 5.重啟Tomcat服務 6.配置功能變數名稱解析 7.安裝圖解: 8.部署多節點組建集群 9.接入負 ...
  • (上圖是聖卡塔利娜島,美國南加州的一個小島,也是 mac OS 10.15 版本的官方預設壁紙) ___ 概述 Hello,大家好,我們又來講面試中的基礎題了,今天這是一道很經典又很猥瑣的題 說猥瑣是因為這兩個異常名字比較近似,但事實上他們完全不同,導致很多同學會經常容易把它們搞混 說經典是因為由這 ...
  • 許可權部分將分兩章介紹,第一章由淺入深介紹許可權理論知識及應用,第二章介紹具體實現。後期再講述中間件的使用時,還會插入一些許可權內容,本質上屬於中間件的應用。 許可權模塊是業務系統最常見、最基本的子集。本章假定了一個系統從最初簡單的需求到逐漸成熟且完善的許可權體系的實現過程。 閱讀本章預計花費20分鐘。 1. ...
  • 簡介 外觀模式(Facade Pattern):外部與一個子系統的通信必須通過一個統一的外觀對象進行,為子系統中的一組介面提供一個一致的界面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。外觀模式又稱為門面模式,它是一種對象結構型模式。 模式分析 根據“單一職責原則”,在軟體中將一 ...
  • 1. 常用的設計模式有哪些,作用是什麼 設計模式一共23種,常用的設計模式有: 1. 工廠模式: 構建多個對象的工廠。 1. 單例模式:單例類負責創建自己的對象,同時確保只有單個對象被創建 1. 代理模式:代理其他類,增強原來類的功能。 1. 外觀模式:包裝多個類的複雜性,對外提供統一的方法。 1. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...