Docker 部署 Django+Mysql+Redis+Gunicorn+Nginx

一. 前言

docker 技術如今很是火熱,經過容器構建項目環境,運行效率和部署效率都很不錯。因此最近抽空看了一些教程,而後將博客部署方式改成了docker,感受網上沒有特別好的關於 docker 部署django項目的教程,特地寫了這篇文章,算是記錄本身的心得。html

本次教程的測試環境爲 Deepin,主要側重於容器的編排Django 相關部署知識,一些細節方面,例如環境依賴安裝,不會講得特別詳細。因爲是在本地測試,因此在配置 nginx 相關信息時,將配置 http 代理而非 https 代理。python

二. 環境依賴

部署方式選擇了 docker 加 docker-compose,所以須要安裝 docker 和 docker-compose。mysql

  • docker 能夠經過 sudo apt install docker-ce 命令安裝。nginx

  • docker-compose 可經過如下命令安裝。web

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 安裝成功。 redis

    Kyis.png

  • 輸入 docker-compose version,看到如下畫面表示 docker-compose 安裝成功。 sql

    K7P7.png

三. 部署分析

  • 博客項目中使用到了 Django, Mysql, Redis, Nginx,所以須要四個容器,每一個容器對應一個應用,固然這些容器是有前後順序的,也就是說存在依賴關係。而後經過 docker-compose 編排這四個容器,構建容器運行環境。docker

  • 總共四個容器:shell

    1. Redis 容器:緩存服務
    2. Mysql 容器:數據存儲
    3. DjangoGunicorn)容器:處理動態請求
    4. Nginx 容器:反向代理,處理靜態資源
  • 下面是容器的結構圖。 數據庫

    docker2.png

  • 容器依賴關係:Django 容器依賴 Redis 容器和 Mysql 容器,Nginx 容器依賴Gunicorn 容器。

四. 項目結構

看這個教程的小夥伴請儘可能把目錄和教程中目錄保持一致,不然在後續部署過程當中極有可能會出錯。

  • my_blogdjango 項目目錄,deployment 文件夾放置了除 Django 容器外的三個容器配置信息。
    Dockerfile:docker 環境文件
    docker-compose.yml:編排容器文件
    start.sh:容器初始化後執行的 shell 命令腳本
    requirements.txt:django項目環境依賴文件
    gunicorn.conf:gunicorn 配置文件

    20191111194814.png

  • deployment 目錄包含 mysql 容器配置信息,nginx 容器配置信息和 redis 容器數據目錄。
    mysql:放置數據庫配置信息,conf 放置數據庫初始化配置文件 my.cnf,data 用於掛載數據庫數據,init 放置 sql 腳本(導入表結構和數據,並掛載到容器中)。
    nginx:放置 nginx 配置信息,ssl 放置 ssl證書
    redis: 掛載 redis 數據

    20191111195059.png

五. 構建 Django 容器環境

1. Django 項目 Dockerfile編寫

容器環境和本機環境是隔離的,你能夠把容器當作另外一個系統,起初這個系統與你本機的系統並沒有關聯,咱們經過編寫 Dockerfile 文件配置並構建容器環境(像在乾淨的系統中配置 python 環境同樣)。

# 創建 python3.6 環境
FROM daocloud.io/python:3.6

# 鏡像做者
MAINTAINER zyk 2295098032@qq.com

# 設置 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 編寫

20191111195059.png

  • 建立並編寫 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

  • 執行完畢之後看到如下畫面代表構建成功。

    20191111220450.png

  • 在瀏覽器端口訪問127.0.0.1或者你的公網 ip,若能成功訪問代表構建成功。

    20191111220716.png

十. 最後

我也是第一次用 docker-compose 來部署 django 項目,如有寫得不得當或者有誤的地方麻煩你們幫忙指出。

相關文章
相關標籤/搜索