本文適合使用 django
進行 web 開發(fā)史简,并有對 docker
有一定了解的同學削樊。閱讀完能幫助你:
- 在開發(fā)環(huán)境中使用 docker 快速搭建和開發(fā) django 項目
- 在生產(chǎn)環(huán)境中使用 docker 方便快捷地部署個人 django 項目
對于 docker匣缘,你至少需要理解 鏡像
、容器
、宿主機
這幾個概念。
如果你還不知道 docker 是什么陷舅,你可以通過這篇 《Docker 傻瓜入門》 文章
大致了解一下。
開始構(gòu)建開發(fā)環(huán)境
假設你的系統(tǒng)非常純潔审洞,沒有 python 更沒有 django莱睁,只有 docker。我們要做的第一步就是利用 docker 來創(chuàng)建一個安裝有 django 的環(huán)境芒澜。
創(chuàng)建一個名叫 Dockerfile
的文件仰剿,內(nèi)容如下:
FROM python:3.8
RUN pip install django
CMD bash
這個文件的內(nèi)容很簡單,就是構(gòu)建一個基于 python3.8 的鏡像痴晦,然后額外的安裝一下 django南吮,至于 CMD bash
可以暫時不予理會。
然后用 build
命令構(gòu)建出一個鏡像:
docker build -t dj .
從以上命令可以看出誊酌,我們給構(gòu)建的鏡像取名叫 dj
部凑,構(gòu)建完成后可以通過 docker images
命令看到這個鏡像
創(chuàng)建 django 項目
好了我們已經(jīng)有了一個 python3.8 + django 的開發(fā)環(huán)境了,接下來要做的是進入這個開發(fā)環(huán)境:
docker run --name dev -it -p 8000:8000 -v `pwd`/workspace:/workspace dj
這時你就進入了一個容器中碧浊,我們給他取名叫 dev
涂邀,并且將他和宿主機之間建立了端口和目錄的映射關(guān)系,即宿主機上當前目錄下的 workspace
和容器里面的 /workspace
是等價的辉词。
我們進入容器里的 /workspace
目錄創(chuàng)建個 django 項目
cd /workspace
django-admin.py startproject myproj
cd myproj
python manage.py startapp myapp
接下來必孤,我們新開一個終端,回到宿主機上的 workspace
目錄瑞躺,可以看到剛在容器里創(chuàng)建的 myproj
項目也出現(xiàn)在了這里
.
├── manage.py
├── myapp
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── myproj
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
現(xiàn)在你可以使用任何喜歡的編輯器在宿主機上進行代碼編寫和開發(fā)了敷搪。
運行項目
項目開發(fā)到一定程度后我們就需要運行我們的 web 服務了,由于我們的宿主機并沒有 python 和 django 環(huán)境,運行不了代碼,所以我們必須在 dev
容器中運行纪岁。
還能找到 dev
容器的那個終端嗎滓窍?如果不小心關(guān)了也沒關(guān)系损离,只要運行以下命令,就可以重新進入 dev
了:
docker start dev
docker exec -it dev bash
在 dev
容器中我們使用 runserver 啟動 django 的 web 服務:
cd /workspace/myproj
python manage.py runserver 0.0.0.0:8000
現(xiàn)在在宿主機上打開瀏覽器,訪問 http://127.0.0.1:8000
可以看到你的項目運行起來啦,恭喜践樱!
以上就是在開發(fā)環(huán)境實踐 django + docker 的步驟了,不過我個人其實不太推薦這種做法凸丸,因為給你的電腦安裝一個 python 然后在 pip install 一下 django 并不算太費事拷邢,反而是使用 docker 需要不斷的在容器和宿主機之間來回切換,有點傷神屎慢。
但是如果你安裝 python 和 django 或其他依賴時總是莫名地出現(xiàn)問題瞭稼,為了避免 “安裝環(huán)境花了一周時間” 的悲劇出現(xiàn)在你的身上(雖然這通常是 Java 程序員才會遇到的 )忽洛,你就應該及時使用 docker 了。
構(gòu)建生產(chǎn)鏡像
對于生產(chǎn)環(huán)境部署來說环肘, django + docker 才算是真的派上大用場了
在部署之前我們需要稍微修改一下我們的項目代碼欲虚,首先我們需要一個 requirements.txt
文件記錄下項目所需的所有依賴庫,它看上去應該像這樣:
# python3.8
django==3.0.4
gunicorn==20.0.4
gevent==1.4.0
然后在 myproj
目錄中新建一個 Dockerfile
文件悔雹,其內(nèi)容如下:
FROM python:3.8
WORKDIR /workspace
COPY requirements.txt /workspace/requirements.txt
RUN pip install -r requirements.txt
ADD . /workspace
EXPOSE 8000
CMD gunicorn -k gevent -w 5 -b 0.0.0.0:8000 myproj.wsgi
接著本地構(gòu)建和運行一下我們的項目看看
docker build -t prod .
docker run --name prod -d -p 8001:8000 prod
在瀏覽器打開 http://127.0.0.1:8001
如果看的網(wǎng)站運行正常复哆,就可以進行正式的生產(chǎn)部署了
生產(chǎn)部署
在上生產(chǎn)前確認下 settings.py
里 DEBUG
已設為 False
,以及 STATIC_ROOT
配置的路徑荠商。
下面假設我們的 STATIC_ROOT
是 /workspace/static
將整個項目代碼包括 Dockerfile 文件推送到生產(chǎn)服務器寂恬,在服務器上運行如下命令:
docker build -t prod .
docker run --rm -it prod python manage.py migrate
docker run --rm -it -v /var/www/html/static:/workspace/static prod python manage.py collectstatic --noinput
docker run --name prod -d -p 8000:8000 prod
接著配置一下 nginx
反向代理到 8000
端口,靜態(tài)文件路由指向 /var/www/html/static
即可莱没。
進階
如果你的項目有用到 celery
的話,可能還需要這些命令來啟動異步任務和監(jiān)控:
docker run --name worker -d prod worker -A myproj
docker run --name beat -d prod beat -A myproj
docker run --name flower -d -p 5555:5555 prod flower -A myproj --address=0.0.0.0
如果每次啟動都要敲這么多命令酷鸦,那也太鬧心了饰躲,讓我們可以利用 docker 的 entrypoint
功能來優(yōu)化一下
我們在 myproj
目錄下創(chuàng)建一個 entrypoint.sh
文件,內(nèi)容如下:
#!/bin/bash
appname=myproj;
echo $appname;
if [[ -z "$1" ]]; then
echo "run server";
python manage.py migrate;
python manage.py collectstatic --noinput;
gunicorn -k gevent -w 5 -b 0.0.0.0:8000 $appname.wsgi;
elif [[ "$1" = "worker" ]]; then
echo "run celery worker";
celery worker -A $appname -l info;
elif [[ "$1" = "beat" ]]; then
echo "run celery beat";
celery beat -A $appname -l info;
elif [[ "$1" = "flower" ]]; then
echo "run celery flower";
flower -A $appname --address=0.0.0.0;
else
echo "$@"
exec "$@"
fi
再修改一下我們原來的 Dockerfile
:
FROM python:3.8
WORKDIR /workspace
COPY requirements.txt /workspace/requirements.txt
RUN pip install -r requirements.txt
ADD . /workspace
EXPOSE 8000
ENTRYPOINT ["entrypoint.sh"]
重新 build 鏡像:
docker build -t prod .
啟動時只需要這樣就行了:
docker run --name prod -d -p 8000:8000 -v /var/www/html/static:/workspace/static prod
docker run --name worker -d prod worker
docker run --name beat -d prod beat
docker run --name flower -d -p 5555:5555 prod flower
后話
當然真正的企業(yè)級生產(chǎn)部署不可能這么簡單臼隔,他們一般會在代碼提交后通過 CI
自動化地測試和構(gòu)建鏡像嘹裂,生產(chǎn)服務器上則直接拉取穩(wěn)定版本的鏡像運行。
企業(yè)級的生產(chǎn)也不會使用質(zhì)樸的 docker run
來運行鏡像摔握,更多的會在 k8s
集群里調(diào)度運行寄狼,或至少會使用 docker-compose
來部署。