一. 前言
docker技術現在非常火熱,通過容器構建項目環境,運行效率和部署效率都很不錯。所以最近抽空看了一些教程,然后將博客部署方式改為了docker,感覺網上沒有特別好的關于 docker 部署 django 項目的教程,特意寫了這篇文章,算是記錄自己的心得。
本次教程的測試環境為 deepin ,主要側重于 容器的編排 和 django 相關部署知識,一些細節方面,例如環境依賴安裝,不會講得特別詳細。由于是在本地測試,所以在配置 nginx 相關信息時,將配置 http 代理而非 https 代理。
二. 環境依賴
部署方式選擇了 docker 加 docker-compose,因此需要安裝 docker 和 docker-compose。
-
docker 可以通過
sudo apt install docker-ce
命令安裝。 - docker-compose 可通過以下命令安裝。
1
2
|
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 環境一樣)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 建立 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 的啟動
1
2
3
4
5
6
7
8
|
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 容器
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/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
1
2
3
4
5
6
7
8
9
10
11
|
# 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中配置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 僅用于本地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 配置,這個文件將被掛載到容器中。
1
2
3
4
5
6
7
8
9
|
[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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
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
1
2
3
4
5
6
7
8
9
10
11
12
|
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作為緩存的話,沒配置的話請忽略)
1
2
3
4
5
6
7
8
9
10
11
12
|
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 項目,若有寫得不得當或者有誤的地方麻煩大家幫忙指出。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://juejin.im/post/5dcbb15ee51d4521e12d33e9