一. 前言
docker技術(shù)現(xiàn)在非?;馃幔ㄟ^容器構(gòu)建項目環(huán)境,運行效率和部署效率都很不錯。所以最近抽空看了一些教程,然后將博客部署方式改為了docker,感覺網(wǎng)上沒有特別好的關(guān)于 docker 部署 django 項目的教程,特意寫了這篇文章,算是記錄自己的心得。
本次教程的測試環(huán)境為 Deepin ,主要側(cè)重于 容器的編排 和 Django 相關(guān)部署知識,一些細(xì)節(jié)方面,例如環(huán)境依賴安裝,不會講得特別詳細(xì)。由于是在本地測試,所以在配置 nginx 相關(guān)信息時,將配置 http 代理而非 https 代理。
二. 環(huán)境依賴
部署方式選擇了 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 安裝成功。
![](/d/20211016/e9add94b674ab272be7fe7ca1524f8e0.gif)
三. 部署分析
博客項目中使用到了 Django , Mysql , Redis , Nginx ,因此需要四個容器,每個容器對應(yīng)一個應(yīng)用,當(dāng)然這些容器是有先后順序的,也就是說存在依賴關(guān)系。然后通過 docker-compose 編排這四個容器,構(gòu)建容器運行環(huán)境。
總共四個容器:
- Redis 容器:緩存服務(wù)
- Mysql 容器:數(shù)據(jù)存儲
- Django(Gunicorn)容器:處理動態(tài)請求
- Nginx 容器:反向代理,處理靜態(tài)資源
下面是容器的結(jié)構(gòu)圖。
![](/d/20211016/9bc2b68acd03c33fb84a890d751bbdad.gif)
容器依賴關(guān)系:Django 容器依賴 Redis 容器和 Mysql 容器,Nginx 容器依賴Gunicorn 容器。
四. 項目結(jié)構(gòu)
看這個教程的小伙伴請盡量把目錄和教程中目錄保持 一致 ,否則在后續(xù)部署過程中極有可能會出錯。
my_blog是 django 項目目錄, deployment 文件夾放置了除 Django 容器外的三個容器配置信息。
Dockerfile:docker 環(huán)境文件
docker-compose.yml:編排容器文件
start.sh:容器初始化后執(zhí)行的 shell 命令腳本
requirements.txt:django項目環(huán)境依賴文件
gunicorn.conf:gunicorn 配置文件
![](/d/20211016/45b747b663fb4ff7c8996b595d8f1ac5.gif)
deployment目錄包含 mysql 容器配置信息, nginx 容器配置信息和 redis 容器數(shù)據(jù)目錄。
mysql:放置數(shù)據(jù)庫配置信息,conf 放置數(shù)據(jù)庫初始化配置文件 my.cnf,data 用于掛載數(shù)據(jù)庫數(shù)據(jù),init 放置 sql 腳本(導(dǎo)入表結(jié)構(gòu)和數(shù)據(jù),并掛載到容器中)。
nginx:放置 nginx 配置信息,ssl 放置 ssl證書
redis: 掛載 redis 數(shù)據(jù)
![](/d/20211016/6aff874a43039808c4a40a3000c28976.gif)
五. 構(gòu)建 Django 容器環(huán)境
1. Django 項目 Dockerfile編寫
容器環(huán)境和本機環(huán)境是 隔離 的,你可以把容器當(dāng)做 另一個系統(tǒng) ,起初這個系統(tǒng)與你本機的系統(tǒng) 并無關(guān)聯(lián) ,我們通過編寫 Dockerfile 文件 配置并構(gòu)建 容器環(huán)境(像在干凈的系統(tǒng)中配置 python 環(huán)境一樣)。
# 建立 python3.6 環(huán)境
FROM daocloud.io/python:3.6
# 鏡像作者
MAINTAINER zyk 2295098032@qq.com
# 設(shè)置 python 環(huán)境變量
ENV PYTHONUNBUFFERED 1
# 創(chuàng)建 my_blog 文件夾
RUN mkdir /my_blog
# 將 my_blog 文件夾為工作目錄
WORKDIR /my_blog
# 將當(dāng)前目錄加入到工作目錄中(. 表示當(dāng)前目錄)
ADD . /my_blog
# 利用 pip 安裝依賴(- i 表示指定清華源,默認(rèn)源下載過慢)
RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
#設(shè)置環(huán)境變量
ENV SPIDER=/my_blog
2. 編寫 gunicorn 配置文件
編寫 gunicorn.conf 文件,用于 gunicorn 的啟動
workers=3 # 并行工作進程數(shù)
threads = 2 # 指定每個工作者的線程數(shù)
bind=['0.0.0.0:8000'] # 監(jiān)聽內(nèi)網(wǎng)端口8000
proc_name='my_blog' # 進程名稱
pidfile='/tmp/blog.pid' # 設(shè)置進程文件目錄
worker_class='gevent' # 工作模式協(xié)程
timeout=30 # 超時
max_requests=6000 # 最大請求數(shù)
3. 編寫 start.sh 命令腳本
start.sh 腳本用于啟動 django 容器
#!/bin/bash
# 從第一行到最后一行分別表示:
# 1. 守護進程執(zhí)行 celery,沒有這個需求的小伙伴可以將第一行命令其刪除
# 2. 收集靜態(tài)文件到根目錄,
# 3. 生成數(shù)據(jù)庫可執(zhí)行文件,
# 4. 根據(jù)數(shù)據(jù)庫可執(zhí)行文件來修改數(shù)據(jù)庫
# 5. 用 gunicorn 啟動 django 服務(wù)
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
六. 構(gòu)建 nginx 容器環(huán)境
1. nginx 容器 Dockefile 編寫
![](/d/20211016/6aff874a43039808c4a40a3000c28976.gif)
創(chuàng)建并編寫 nginx 文件夾下的 Dockerfile
# nginx鏡像
FROM daocloud.io/nginx
# 刪除原有配置文件,創(chuàng)建靜態(tài)資源文件夾和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,將動態(tài)請求分發(fā)至內(nèi)部的 django 容器的8000端口,并配置靜態(tài)資源路徑。
配置反向代理時,注意 host 一定要改為 web,web即是django容器的名稱(在docker-compose.yml中配置)
# 僅用于本地docker環(huán)境測試(80端口代理http請求)
server {
listen 80; # 監(jiān)聽80端口
server_name 127.0.0.1; # 生產(chǎn)環(huán)境請換成域名
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/; #靜態(tài)資源路徑
}
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. 導(dǎo)入初始化 sql 文件(不需要導(dǎo)入初始數(shù)據(jù)庫的小伙伴可以忽略此步驟)
將需要導(dǎo)入的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表容器運行發(fā)生錯誤時一直重啟
db:
image: daocloud.io/mysql:5.7
environment:
- MYSQL_DATABASE=my_blog # 數(shù)據(jù)庫名稱
- MYSQL_ROOT_PASSWORD=19960331 # 數(shù)據(jù)庫密碼
volumes:
- ./deployment/mysql/data:/var/lib/mysql # 掛載數(shù)據(jù)庫數(shù)據(jù)
- ./deployment/mysql/conf/my.cnf:/etc/mysql/my.cnf # 掛載配置文件
- ./deployment/mysql/init:/docker-entrypoint-initdb.d/ # 掛載數(shù)據(jù)初始化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 # 掛載靜態(tài)文件
- ./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 并構(gòu)建容器環(huán)境。
expose表示將端口暴露給其他容器,但 不 暴露給主機(不同容器默認(rèn)相互隔離)。
ports表示將該容器端口映射到主機端口(從右往左讀,例如ports: - "3307:3306",是指把容器的3306端口映射到主機的3307端口),同時該容器端口也會對其他容器開放。
volumes表示掛載,就是將本機的文件和容器中的文件映射起來,容器和本地環(huán)境本來是隔離的,掛載相當(dāng)于是鑿了一個小洞,讓兩者數(shù)據(jù)可以互通。
links表示將容器互聯(lián)起來。
depends_on:表示依賴關(guān)系,因為容器的啟動有先后順序,django 容器依賴于 mysql 容器和 redis 容器(django需要從數(shù)據(jù)庫和緩存中讀寫數(shù)據(jù)),而 nginx 依賴于 django 容器(nginx 容器需要反向代理 django 容器的8000端口)
九. 構(gòu)建、運行容器
在構(gòu)建運行容器之前,需要修改 django 項目的 settings.py 文件。
將 數(shù)據(jù)庫連接 HOST 改為 mysql 容器名稱 db
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # mysql驅(qū)動
'NAME': 'my_blog', # 數(shù)據(jù)庫名稱
'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,
},
},
}
生產(chǎn)環(huán)境部署請將 settings.py 中的 DEBUG = True
改為 DEBUG = False
以關(guān)閉debug模式。
最后在項目根目錄執(zhí)行命令 docker-compose up --build
。
執(zhí)行完畢以后看到以下畫面表明構(gòu)建成功。
![](/d/20211016/29a0d453b878e3e11244510ace79ff23.gif)
在瀏覽器端口訪問127.0.0.1或者你的公網(wǎng) ip,若能成功訪問表明構(gòu)建成功。
![](/d/20211016/93068069397dacc3db3c6d72c5041f1c.gif)
十. 最后
我也是第一次用 docker-compose 來部署 django 項目,若有寫得不得當(dāng)或者有誤的地方麻煩大家?guī)兔χ赋觥?/p>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。