上一章咱們實現了在 Docker 中添加了 MySQL 數據庫,但採用的開發服務器雖然使用便捷,但性能差、可靠性低,沒法應用在生產環境中。python
所以本章將實現 Docker + Django + MySQL + Nginx + Gunicorn 容器項目,完成最終的服務器部署。mysql
直接進入本章的 Docker 入門讀者,建議回到教程第一章開始閱讀,不然某些內容很差理解。對 Django 項目部署都沒有概念的讀者,還能夠先閱讀個人博文:將 Django 項目部署到服務器。nginx
在部署到服務器以前,先來嘗試本地部署。git
在上一章的基礎上,繼續修改 docker-compose.yml
配置:github
version: "3"
services:
app:
restart: always
build: .
command: bash -c "python3 manage.py collectstatic --no-input && python3 manage.py migrate && gunicorn --timeout=30 --workers=4 --bind :8000 django_app.wsgi:application"
volumes:
- .:/code
- static-volume:/code/collected_static
expose:
- "8000"
depends_on:
- db
networks:
- web_network
- db_network
db:
image: mysql:5.7
volumes:
- "./mysql:/var/lib/mysql"
ports:
- "3306:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=mypassword
- MYSQL_DATABASE=django_app
networks:
- db_network
nginx:
restart: always
image: nginx:latest
ports:
- "8000:8000"
volumes:
- static-volume:/code/collected_static
- ./config/nginx:/etc/nginx/conf.d
depends_on:
- app
networks:
- web_network
networks:
web_network:
driver: bridge
db_network:
driver: bridge
volumes:
static-volume:
複製代碼
有點複雜。來看看大致思路:web
app
、 db
和 nginx
。容器之間經過定義的端口進行通信。web_network
和 db_network
。只有處在相同網絡的容器才能互相通信。不一樣網絡之間是隔離的,即使採用一樣的端口,也沒法通信。static-volume
。數據卷很是適合多個容器共享使用同一數據,你能夠看到 app
和 nginx
都用到了它。expose
和 ports
均可以暴露容器的端口,區別是 expose 僅暴露給其餘容器,而 ports 會暴露給其餘容器和宿主機。這麼講可能仍是很難理解,讓咱們繼續分解。sql
Docker 容許用戶給每一個容器定義其工做的網絡,只有在相同的網絡之中才能進行通信。你能夠看到 nginx
容器處於 web_network
網絡,而 db
容器處於 db_network
網絡,所以它兩是沒法通信的,實際上確實也不須要通信。而 app
容器同時處於 web_network
和 db_network
網絡,至關因而橋樑,連通了3個容器。docker
定義網絡能夠隔離容器的網絡環境,也方便運維人員一眼看出網絡的邏輯關係。shell
以前咱們見識過的用於映射宿主機和容器目錄的捲了,實際上稱爲掛載;如今新出現的 static-volume
才叫卷。它的使用方式像這樣:static-volume:/code/collected_static
,冒號後面仍是容器內的目錄,但冒號前的卻不是宿主機目錄、僅僅是卷的名稱而已。從本質上講,數據卷也是實現了宿主機和容器的目錄映射,可是數據卷是由 Docker 進行管理的,你甚至都不須要知道數據卷保存在宿主機的具體位置。數據庫
相比掛載,數據卷的優勢是因爲是 Docker 統一管理的,不存在因爲權限不夠引起的掛載問題,也不須要在不一樣服務器指定不一樣的路徑;缺點是它不太適合單配置文件的映射。
和掛載同樣,數據卷的生命週期脫離了容器,刪除容器以後卷仍是存在的。下次構建鏡像時,指定卷的名稱就能夠繼續使用了。
既然 Docker 可以管理卷,因此要想刪除卷也是很是容易的。指令嘛,我不告訴你,生產環境千萬不要手賤。按期備份數據是個好習慣。
數據卷有個很重要的特性:啓動時若是卷是空的,則會將容器映射目錄的全部內容複製到卷裏去。換句話說就是,只要卷初始化完成後,容器原始的 collected_static
目錄就不會再使用了,新增的文件也只存在於卷中,容器中是沒有的。
實際上 static 靜態文件(以及 media 媒體文件)的持久存儲,經過掛載或者數據卷均可以實現;具體用哪一種,這個就見仁見智了,你本身選擇。
篇幅有限,教程沒有講到 media 媒體文件,但它的設置和 static 是徹底相同的。
首先修改 Nginx 的配置文件,即映射到 nginx
容器的 config/nginx/django_app.conf
:
upstream app {
ip_hash;
server app:8000;
}
server {
listen 8000;
server_name localhost;
location /static/ {
autoindex on;
alias /code/collected_static/;
}
location / {
proxy_pass http://app/;
}
}
複製代碼
此配置下 Nginx 會監聽容器的 8000 端口,並將受到的請求發送到 app
容器(靜態文件請求除外)。
在 requirements.txt
文件中增長 gunicorn
庫:
django==2.2
mysqlclient==1.3.14
gunicorn==19.9.0
複製代碼
最後修改 django_app/settings.py
的域和靜態文件存放目錄的配置:
...
ALLOWED_HOSTS = ['*']
...
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
STATIC_URL = '/static/'
複製代碼
全部配置就完成了。
教程使用空的 Django 項目,爲演示效果,就沒有修改 DEBUG=False 了。若你用的本身的項目測試,記得把它爲 False。
測試指令就一條:
$ docker-compose up
複製代碼
瀏覽器訪問 127.0.0.1:8000
又看到熟悉的 Django 小火箭了。
和上一章相似,第一次啓動容器時可能會出現沒法鏈接 MySQL 的錯誤,這是因爲雖然 db 容器已經啓動,但初始化並未完成;從新啓動容器以後就能夠正常工做了。若屢次啓動都沒法正常工做,那就是別的緣由了,好好檢查吧。
本地部署成功,下一步服務器部署。
有了本地部署的經驗,服務器部署就很是很是簡單了。
仍是相似的,部署前將 Docker 、 Docker-compose 、 Python3 等工具在服務器上安裝好;將項目用 Git 克隆到服務器本地。
接下來把 settings.py
、config/nginx/django_app.conf
、requirements.txt
相關位置都按教程流程改好;將 docker-compose.yml
和 Dockerfile
複製到服務器。
因爲 http 請求默認爲 80 端口,因此爲了接收公網請求,還須要作一點點修改 docker-compose.yml
的工做:
version: "3"
services:
app:
...
command: bash -c "... your_project_name.wsgi:application" # 改成你的項目名稱
...
db:
...
nginx:
...
ports:
- "80:8000" # 監聽 80 端口
...
networks:
...
volumes:
...
複製代碼
修改 Gunicorn 綁定的項目名稱,以及讓宿主機監聽公網 http 默認的 80 端口。
此外還要修改 config/nginx/django_app.conf
:
upstream your_domain_name {
ip_hash;
server app:8000;
}
server {
...
location / {
proxy_pass http://your_domain_name/;
}
}
複製代碼
這個改動主要是爲了照顧各類第三方登陸的回調地址(不改這裏, GitHub、Weibo 三方登陸都會失敗)。若是你沒有相似的需求,不改也是能夠的。好比博主的我的網站是 www.dusaiphoto.com
,因此這裏的 your_domain_name
就修改成 www.dusaiphoto.com
。
最後,記得將 settings.py
中的 DEBUG 配置修改好:
# DEBUG=True 註釋掉
DEBUG=False
複製代碼
這樣就能夠了!構建鏡像並啓動容器:
docker-compose up
複製代碼
在瀏覽器中就能夠正常訪問你的網站了。
如今你已經能夠部署一個線上的容器化 Django 項目了,恭喜!
若本教程對你有幫助,請到GitHub給個 Star 喲,也歡迎閱讀個人Django 搭建博客教程。
老朋友們,下個教程見!