Docker部署Django+Mysql+Redis+Gunicorn+Nginx的實現
一. 前言
docker技術現在非常火熱,通過容器構建專案環境,執行效率和部署效率都很不錯。所以最近抽空看了一些教程,然後將部落格部署方式改為了docker,感覺網上沒有特別好的關於 docker 部署 django 專案的教程,特意寫了這篇文章,算是記錄自己的心得。
本次教程的測試環境為 Deepin ,主要側重於 容器的編排 和 Django 相關部署知識,一些細節方面,例如環境依賴安裝,不會講得特別詳細。由於是在本地測試,所以在配置 nginx 相關資訊時,將配置 http 代理而非 https 代理。
二. 環境依賴
部署方式選擇了 docker 加 docker-compose,因此需要安裝 docker 和 docker-compose。
- docker 可以通過
sudo apt install docker-ce
命令安裝。 - docker-compose 可通過以下命令安裝。
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
安裝完成以後,輸入 docker version
,看到以下畫面表示 docker 安裝成功。
輸入 docker-compose version
,看到以下畫面表示 docker-compose 安裝成功。
三. 部署分析
部落格專案中使用到了 Django,Mysql,Redis,Nginx ,因此需要四個容器,每個容器對應一個應用,當然這些容器是有先後順序的,也就是說存在依賴關係。然後通過 docker-compose 編排這四個容器,構建容器執行環境。
總共四個容器:
- Redis 容器:快取服務
- Mysql 容器:資料儲存
- Django(Gunicorn)容器:處理動態請求
- Nginx 容器:反向代理,處理靜態資源
下面是容器的結構圖。
容器依賴關係:Django 容器依賴 Redis 容器和 Mysql 容器,Nginx 容器依賴Gunicorn 容器。
四. 專案結構
看這個教程的小夥伴請儘量把目錄和教程中目錄保持 一致 ,否則在後續部署過程中極有可能會出錯。
my_blog是 django 專案目錄, deployment 資料夾放置了除 Django 容器外的三個容器配置資訊。
Dockerfile:docker 環境檔案
docker-compose.yml:編排容器檔案
start.sh:容器初始化後執行的 shell 命令指令碼
requirements.txt:django專案環境依賴檔案
gunicorn.conf:gunicorn 配置檔案
deployment目錄包含 mysql 容器配置資訊, nginx 容器配置資訊和 redis 容器資料目錄。
mysql:放置資料庫配置資訊,conf 放置資料庫初始化配置檔案 my.cnf,data 用於掛載資料庫資料,init 放置 sql 指令碼(匯入表結構和資料,並掛載到容器中)。
nginx:放置 nginx 配置資訊,ssl 放置 ssl證書
redis: 掛載 redis 資料
五. 構建 Django 容器環境
1. Django 專案 Dockerfile編寫
容器環境和本機環境是 隔離 的,你可以把容器當做 另一個系統 ,起初這個系統與你本機的系統 並無關聯 ,我們通過編寫 Dockerfile 檔案 配置並構建 容器環境(像在乾淨的系統中配置 python 環境一樣)。
# 建立 python3.6 環境 FROM daocloud.io/python:3.6 # 映象作者 MAINTAINER zyk [email protected] # 設定 python 環境變數 ENV PYTHONUNBUFFERED 1 # 建立 my_blog 資料夾 RUN mkdir /my_blog # 將 my_blog 資料夾為工作目錄 WORKDIR /my_blog # 將當前目錄加入到工作目錄中(. 表示當前目錄) ADD . /my_blog # 利用 pip 安裝依賴(- i 表示指定清華源,預設源下載過慢) RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ #設定環境變數 ENV SPIDER=/my_blog
2. 編寫 gunicorn 配置檔案
編寫 gunicorn.conf 檔案,用於 gunicorn 的啟動
workers=3 # 並行工作程序數 threads = 2 # 指定每個工作者的執行緒數 bind=['0.0.0.0:8000'] # 監聽內網埠8000 proc_name='my_blog' # 程序名稱 pidfile='/tmp/blog.pid' # 設定程序檔案目錄 worker_class='gevent' # 工作模式協程 timeout=30 # 超時 max_requests=6000 # 最大請求數
3. 編寫 start.sh 命令指令碼
start.sh 指令碼用於啟動 django 容器
#!/bin/bash # 從第一行到最後一行分別表示: # 1. 守護程序執行 celery,沒有這個需求的小夥伴可以將第一行命令其刪除 # 2. 收集靜態檔案到根目錄, # 3. 生成資料庫可執行檔案, # 4. 根據資料庫可執行檔案來修改資料庫 # 5. 用 gunicorn 啟動 django 服務 celery multi start w1 -A celery_tasks.tasks worker -l info&& python manage.py collectstatic --noinput&& python manage.py makemigrations&& python manage.py migrate&& gunicorn my_blog.wsgi:application -c gunicorn.conf
六. 構建 nginx 容器環境
1. nginx 容器 Dockefile 編寫
建立並編寫 nginx 資料夾下的 Dockerfile
# nginx映象 FROM daocloud.io/nginx # 刪除原有配置檔案,建立靜態資原始檔夾和ssl證書儲存資料夾 RUN rm /etc/nginx/conf.d/default.conf \ && mkdir -p /usr/share/nginx/html/static \ && mkdir -p /usr/share/nginx/html/media \ && mkdir -p /usr/share/nginx/ssl # 新增配置檔案 ADD ./nginx.conf /etc/nginx/conf.d/
2. 配置 nginx.conf
nginx.conf用於反向代理域名或者 ip,將動態請求分發至內部的 django 容器的8000埠,並配置靜態資源路徑。
配置反向代理時,注意 host 一定要改為 web,web即是django容器的名稱(在docker-compose.yml中配置)
# 僅用於本地docker環境測試(80埠代理http請求) server { listen 80; # 監聽80埠 server_name 127.0.0.1; # 生產環境請換成域名 location / { proxy_pass http://web:8000; # 反向代理 django容器8000埠,web為django容器名稱,切記不要寫域名或者ip proxy_set_header Host $host; proxy_redirect off; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /static/ { alias /usr/share/nginx/html/static/; #靜態資源路徑 } location /media/ { alias /usr/share/nginx/html/media/; #上傳檔案路徑 } }
七. 配置 mysql
1. 編寫 my.cnf 檔案
my.cnf 檔案用於初始化 mysql 配置,這個檔案將被掛載到容器中。
[mysqld] user=mysql default-storage-engine=INNODB character-set-server=utf8 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION [client] default-character-set=utf8 [mysql] default-character-set=utf8
2. 匯入初始化 sql 檔案(不需要匯入初始資料庫的小夥伴可以忽略此步驟)
將需要匯入的sql檔案放入init目錄下,並修改其名稱為init.sql
八. 利用 docker-compose 編排容器
編寫 docker-compose.yml
version: "3" services: redis: image: daocloud.io/redis:3 command: redis-server volumes: - ./deployment/redis:/data ports: - "6379:6379" restart: always # always表容器執行發生錯誤時一直重啟 db: image: daocloud.io/mysql:5.7 environment: - MYSQL_DATABASE=my_blog # 資料庫名稱 - MYSQL_ROOT_PASSWORD=19960331 # 資料庫密碼 volumes: - ./deployment/mysql/data:/var/lib/mysql # 掛載資料庫資料 - ./deployment/mysql/conf/my.cnf:/etc/mysql/my.cnf # 掛載配置檔案 - ./deployment/mysql/init:/docker-entrypoint-initdb.d/ # 掛載資料初始化sql指令碼 ports: - "3306:3306" restart: always web: build: . expose: - "8000" volumes: - .:/my_blog - /tmp/logs:/tmp command: bash start.sh links: - db - redis depends_on: - db - redis restart: always nginx: build: deployment/nginx ports: - "80:80" - "443:443" expose: - "8000" volumes: - ./collect_static:/usr/share/nginx/html/static # 掛載靜態檔案 - ./media:/usr/share/nginx/html/media # 掛載上傳檔案 - ./deployment/nginx/ssl:/usr/share/nginx/ssl # 掛載ssl證書目錄 links: - web depends_on: - web restart: always
redis,db,web,nginx為容器名稱。
image表示拉取映象名稱, build 會在給定目錄下尋找 Dockerfile 並構建容器環境。
expose表示將埠暴露給其他容器,但 不 暴露給主機(不同容器預設相互隔離)。
ports表示將該容器埠對映到主機埠(從右往左讀,例如ports: - "3307:3306",是指把容器的3306埠對映到主機的3307埠),同時該容器埠也會對其他容器開放。
volumes表示掛載,就是將本機的檔案和容器中的檔案對映起來,容器和本地環境本來是隔離的,掛載相當於是鑿了一個小洞,讓兩者資料可以互通。
links表示將容器互聯起來。
depends_on:表示依賴關係,因為容器的啟動有先後順序,django 容器依賴於 mysql 容器和 redis 容器(django需要從資料庫和快取中讀寫資料),而 nginx 依賴於 django 容器(nginx 容器需要反向代理 django 容器的8000埠)
九. 構建、執行容器
在構建執行容器之前,需要修改 django 專案的 settings.py 檔案。
將 資料庫連線 HOST 改為 mysql 容器名稱 db
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql',# mysql驅動 'NAME': 'my_blog',# 資料庫名稱 'USER': 'root',# 登入帳號 'PASSWORD': '19960331',# 登入密碼 'HOST': 'db',# 主機地址(容器部署) # 'HOST': '127.0.0.1',# 主機地址 'PORT': '3306',# 埠 'OPTIONS': {'charset': 'utf8mb4'},} }
將快取配置中的 host 改為 redis 容器名稱 redis (如果你配置了redis作為快取的話,沒配置的話請忽略)
CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache','LOCATION': 'redis://redis:6379',# redis(容器) # 'LOCATION': '127.0.0.1:6379','OPTIONS': { "CLIENT_CLASS": "django_redis.client.DefaultClient","CONNECTION_POOL_KWARGS": {"max_connections": 100},'SOCKET_TIMEOUT': 10,},}
生產環境部署請將 settings.py 中的 DEBUG = True
改為 DEBUG = False
以關閉debug模式。
最後在專案根目錄執行命令 docker-compose up --build
。
執行完畢以後看到以下畫面表明構建成功。
在瀏覽器埠訪問127.0.0.1或者你的公網 ip,若能成功訪問表明構建成功。
十. 最後
我也是第一次用 docker-compose 來部署 django 專案,若有寫得不得當或者有誤的地方麻煩大家幫忙指出。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。