使用docker部署django技術(shù)棧項目的方法步驟
隨著Docker的普及成熟,已經(jīng)逐漸成為部署項目的首選,今天來和大家分享下如何使用docker部署django技術(shù)棧項目。
我們這里說的Django技術(shù)棧為:python3.6、Django2.2、redis、mysql、celery、gunicorn和nginx。在實(shí)際的生產(chǎn)項目中,這些組件分布在集群的不同機(jī)器,如Nginx、redis和Mysql可能會有單獨(dú)的團(tuán)隊或部門負(fù)責(zé)。涉及的部署架構(gòu)和容器的編排會更為復(fù)雜,本文暫不去深究。本文主要介紹,如何使用 docker-compose 來編排這些組件,這種方式適用于測試環(huán)境的部署或者你的個人 sideproject 的部署。
本文默認(rèn)你已經(jīng)了解 docker 和 docker-compose 的一些基本知識,若你不了解,可閱讀下面這些資料:
下面我們來說下如何部署。
項目組織結(jié)構(gòu)
首先,看下我們的項目組織結(jié)構(gòu),結(jié)構(gòu)如下:
├── LICENSE ├── README.md ├── compose │ ├── celery │ │ ├── Dockerfile │ │ ├── celery-beat.sh │ │ └── celery.sh │ ├── mysql │ │ └── my.cnf │ ├── nginx │ │ └── nginx.conf │ └── web │ ├── Dockerfile │ ├── entrypoint.sh │ ├── gunicorn.conf │ └── gunicorn.sh ├── docker-compose.yml ├── docker_django_demo │ ├── __init__.py │ ├── celery.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── env.tpl ├── manage.py ├── requirements.txt
除了Django的項目文件外,主要增加了 compose 配置文件目錄和 docker-compose.yml 配置文件。
- compose目錄主要存放各組件的dockerfile文件和啟動腳本。
- docker-compose.yml 是docker-compose的編排配置文件。
編寫Dockerfile 及啟動初始化腳本
在docker-compose中,容器的啟動有兩種方法,一種是直接使用公共的鏡像來啟動容器,另一種是通過我們自己編寫的Dockerfile。因?yàn)槲覀円惭b額外的工具包和初始化相關(guān)配置,web和celery組件我們使用自定義的Dockerfile方式。
web容器的 compose/web/Dockerfile :
FROM python:3.6 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY ./requirements.txt /code/ RUN pip install --no-cache-dir -r requirements.txt \ && rm -rf requirements.txt COPY . /code/ COPY ./compose/web/*.sh /code/ RUN sed -i 's/\r//' gunicorn.sh \ && chmod +x gunicorn.sh \ && sed -i 's/\r//' entrypoint.sh \ && chmod +x entrypoint.sh ENTRYPOINT ["/bin/bash", "entrypoint.sh"]
web容器的其他文件:
- compose/web/entrypoint.sh web容器的啟動腳本,執(zhí)行一些初始化或檢測邏輯。
- compose/web/gunicorn.conf gunicorn配置文件。
- compose/web/gunicorn.sh gunicorn的啟動腳本。
celery的Dockerfile:
FROM python:3.6 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY ./requirements.txt /code/ COPY ./compose/celery/*.sh /code/ RUN pip install --no-cache-dir -r requirements.txt \ && rm -rf requirements.txt && sh init_env.sh COPY . /code/ COPY ./compose/celery/*.sh /code/ RUN sed -i 's/\r//' celery.sh \ && chmod +x celery.sh \ && sed -i 's/\r//' celery-beat.sh \ && chmod +x celery-beat.sh
celery的其他文件:
- compose/celery/celery.sh celery的啟動腳本。
- compose/celery/celery-beat.sh celery-beat的啟動腳本。
編寫Compose啟動配置文件
docker-compose 配置如下:
version: '2' services: redis: image: redis ports: - "6379:6379" db: restart: always image: mysql:5.7.19 # command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./compose/mysql/:/etc/mysql/conf.d - ./db:/var/lib/mysql # for test ports: - "127.0.0.1:3307:3306" # (HOST:CONTAINER) env_file: - .env web: # restart: always build: context: . dockerfile: ./compose/web/Dockerfile command: sh gunicorn.sh # ["/bin/bash", "gunicorn.sh"] ports: - "8080:8002" # (HOST:CONTAINER) volumes: - ./logs:/var/logs/ - ./collect_static:/code/collect_static - ./static:/code/static - ./templates:/code/templates - ./uploads:/code/uploads env_file: .env depends_on: - redis - db nginx: restart: always image: nginx:1.13.0 volumes: - ./compose/nginx:/etc/nginx/conf.d/ - ./staticfiles:/code/staticfiles - ./logs:/var/log/nginx ports: - "80:80" # (HOST:CONTAINER) depends_on: - web celery: build: context: . dockerfile: ./compose/celery/Dockerfile command: sh celery.sh volumes: - ./logs:/var/logs/ - ./uploads:/code/uploads depends_on: - redis - db env_file: .env celery-beat: build: context: . dockerfile: ./compose/celery/Dockerfile command: sh celery-beat.sh volumes: - ./logs:/var/logs/ depends_on: - redis - db env_file: .env
celery 的worker 和beat這里我們使用同一個鏡像Dockerfile, 按照一個鏡像一個進(jìn)程的原則,啟動兩個容器來分別跑worker和beat進(jìn)程。
編譯測試
編寫好配置文件之后,編譯鏡像測試運(yùn)行:
docker-compose build docker-compose up # 前臺運(yùn)行 docker-compose up -d # 無誤后可后臺運(yùn)行
docker-compose ps 可以看到啟動好的容器:
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------------
dockerdjangodemo_celery-beat_1 sh celery-beat.sh Up
dockerdjangodemo_celery_1 sh celery.sh Up
dockerdjangodemo_db_1 docker-entrypoint.sh mysqld Up 127.0.0.1:3307->3306/tcp
dockerdjangodemo_nginx_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp
dockerdjangodemo_redis_1 docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
dockerdjangodemo_web_1 /bin/bash entrypoint.sh sh ... Up 0.0.0.0:8080->8002/tcp
映射端口可根據(jù)自己的實(shí)際情況調(diào)整。
問題
下面說下在構(gòu)建過程中的幾個需要注意的問題。
mysql 編碼問題
docker 提供的mysql鏡像,默認(rèn)編碼為 latin1 , 在保存中文時會顯示亂碼。官方提供了一種修改編碼方式的方法,在啟動腳本后指定編碼格式,文檔可見這里。mysql容器5.7.19版本可直接在docker-compose.yml 中的command后跟上參數(shù) --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci 。這種方式,只是修改server端的編碼。可直接使用配置文件覆蓋的方式,指定所有的編碼格式。
配置如下:
[mysqld] default-storage-engine=INNODB character-set-server=utf8mb4 collation-server=utf8mb4_general_ci init-connect='SET NAMES utf8mb4' init_connect='SET collation_connection = utf8mb4_general_ci' skip-character-set-client-handshake # 跳過客戶端的編碼配置,客戶端直接使用服務(wù)端的編碼配置 bind-address = 0.0.0.0
注:mysql 5.7.19 配置文件方式成功,5.7.4、5.7.17 均失敗,可做參考。
web等mysql啟動完成后再繼續(xù)
mysql 容器在啟動起來之前是無法接受數(shù)據(jù)庫鏈接的,在web啟動初始化時,若數(shù)據(jù)庫還沒有啟動好會導(dǎo)致web容器啟動失敗直接退出。我們可以增加在web容器啟動時增加檢測腳本,數(shù)據(jù)庫連通之后,再繼續(xù)。
腳本如下:
#!/usr/bin/env bash
set -o errexit
set -o pipefail
echo $MYSQL_PASSWORD
echo $MYSQL_DATABASE
echo $MYSQL_HOST
echo $MYSQL_USER
echo $MYSQL_PORT
function mysql_ready(){
python << END
import sys
import pymysql
try:
conn = pymysql.connect(host="db", port=3306, user="root", passwd="$MYSQL_ROOT_PASSWORD", db='$MYSQL_DATABASE', charset='utf8')
except pymysql.err.OperationalError:
sys.exit(-1)
sys.exit(0)
END
}
until mysql_ready; do
>&2 echo "MySQL is unavailable - sleeping"
sleep 1
done
>&2 echo "MySQL is up - continuing..."
總結(jié)
到此,使用docker來部署django技術(shù)棧服務(wù)就完成了,完整的項目代碼,大家可參閱 docker-django-demo 。
文章開始說了,該部署方式不適合大型網(wǎng)站的線上生產(chǎn)服務(wù),耦合度太高,不好維護(hù)等存在著許多問題。但是,部署自己的sideproject或者測試環(huán)境,在硬件資源有限的情況的下還是非常不錯的。除了減少環(huán)境部署搭建的麻煩外,遷移起來也是很方便的。
demo 項目中也有些開發(fā)環(huán)境下如何使用docker的案例,但是個人一直認(rèn)為docker更適合部署,在開發(fā)環(huán)境方便不如直接搭建來的靈活方便。歡迎大家留言,共同討論docker在開發(fā)和部署上的使用心得。
參考
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用腳本一鍵打包并上傳docker鏡像的實(shí)現(xiàn)代碼
這篇文章主要介紹了使用腳本一鍵打包并上傳docker鏡像的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Docker 中快速構(gòu)建 Redis Cluster 集群的詳細(xì)過程
Redis Cluster 集群模式提供了數(shù)據(jù)分區(qū)和高可用性,通過分布式方式存儲和管理數(shù)據(jù),實(shí)現(xiàn)更高的擴(kuò)展性,本指南將演示如何使用 Docker 快速構(gòu)建一個包含 3 個節(jié)點(diǎn)的 Redis Cluster 集群,感興趣的朋友一起看看2024-05-05
Docker鏡像的遷移與備份及Dockerflie 使用方法詳解
遷移和備份主要有三個操作命令將容器保存為鏡像、備份鏡像(將鏡像導(dǎo)出為一個文件)、鏡像的遷移與恢復(fù),這篇文章主要介紹了Docker鏡像的遷移與備份、Dockerflie 使用方法,需要的朋友可以參考下2022-07-07
使用Docker運(yùn)行Microsoft SQL Server 2017的方法
本篇文章主要介紹了使用Docker運(yùn)行Microsoft SQL Server 2017的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
Docker實(shí)踐之python應(yīng)用容器化
這篇文章主要介紹了Docker實(shí)踐之python應(yīng)用容器化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06

