上一章咱们实现了在 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 搭建博客教程。
老朋友们,下个教程见!