使用 Docker 部署 Django 应用的最佳实践是什么?

2017-06-16 22:09:38 +08:00
 chuanqirenwu
我目前的做法是,构建一个容器运行 django,一个容器运行 nginx,把代码所在文件夹挂载到容器里,但是在这种情况下服务器还是需要安装 python 和 django,感觉和用虚拟环境部署没有区别。

我希望大家的效果是服务器只需要安装 Docker 就行了,然后通过镜像就可以运行整个 django 应用,该怎么做?
11674 次点击
所在节点    Python
18 条回复
dalei
2017-06-16 22:22:26 +08:00
你为啥还需要装 python 和 Django?不是都打包进镜像了吗
billlee
2017-06-16 22:28:24 +08:00
首先,大部分发行版都是自带 python 的,你不能不装 python, 否则系统基本服务都跑不起来
其次,并不需要在 docker 外面装 django
另外,最好把代码也打包到镜像里
chuanqirenwu
2017-06-16 22:41:04 +08:00
@dalei 是这样的,我是把源代码文件夹通过 volumes 挂载到容器里,那么在此之前,需要运行 manage.py 的一些命令,如迁移数据库,收集静态文件。那么运行这些命令前又要配置一个完整的 django 环境。而如果将这些动作放到容器里执行的话,我又遇到两个问题:

如何将容器中的数据库挂载到本机?这样保证容器万一挂了数据还在。

由于 django 和 nginx 运行在不同容器,如何让 nginx 容器访问到 django 的容器已获得静态文件?当然思路肯定是 volumes,但是几天来查了很多文档还是不知道该如何设置。
chuanqirenwu
2017-06-16 22:43:45 +08:00
@billlee 两个问题该如何解决:

如何将容器中的数据库挂载到本机?这样保证容器万一挂了数据还在。

由于 django 和 nginx 运行在不同容器,如何让 nginx 容器访问到 django 的容器已获得静态文件?当然思路肯定是 volumes,但是几天来查了很多文档还是不知道该如何设置。
guyskk
2017-06-16 22:54:29 +08:00
docker exec 进容器里执行命令,容器间通过 docker network 通信。用 docker-compose 更方便一些,它会自动配置网络。
yangxuan8282
2017-06-16 23:30:27 +08:00
你可以贴一下你的 Dockerfile

一般的 volume 挂载,如果本机上没有这些文件,而容器里有的话,可以给 Dockerfile 里加个 `docker-entrypoint.sh` 当 ENTRYPOINT,用脚本先判断一下文件是否存在,不存在的话就复制过来,具体例子可以看下 library 里官方怎么做的

至于第二个问题,不同容器间的文件的访问,可以在 docker compose 里指定一个 top-level volumes
ohhe
2017-06-16 23:33:55 +08:00
1、数据库的 data 目录是 volume 挂载的,不怕容器挂啊。
2、收集静态文件可以容器内执行。也可以本地开发机执行后,git 更新,这样更好,一般是。
3、数据库迁移可以本地测试通过后,fabric 自动执行。
chuanqirenwu
2017-06-16 23:43:55 +08:00
@ohhe 如果在本地服务器上执行就需要在搭建一套完整的 django 环境,我希望的是能在容器中执行。
ohhe
2017-06-17 00:20:32 +08:00
@chuanqirenwu 你说的开发机?不是服务器?
开发还是 virtualenv 好使。部署用 docker。
ohhe
2017-06-17 00:33:57 +08:00
感觉楼主对 docker 不是很理解。可别在生产上随便用。
docker 不是虚拟机,设置错误会丢数据的。
楼主意思应该是:
docker 1 web(django) : link:db,volume :project
docker 2 nginx : 反代 web,volume:project_static volume :nginx_config
docker 3 db volume :data
django 的一些命令可以通过 docker1 手动执行或启动时自动执行
darrenfang
2017-06-17 07:34:16 +08:00
你需要 docker-compose
franky_xhl
2017-06-17 09:04:43 +08:00
可以参考 https://github.com/pydanny/cookiecutter-django 里的 docker 配法
maikcn
2017-06-17 09:31:33 +08:00
我是 nginx 和 django 放在一个容器里

# docker run -p 80:80 -p 8000:8000 .........
# docker exec -it {your container} bash
# python manange.py runserver 0.0.0.0:8000

这样就用 80 端口和 8000 端口区分开 nginx 和 django dev server 的访问路径了
除此以外,就是 Volume 的配置,和 db container link 的配置而已,这些官方文档都有
chuanqirenwu
2017-06-17 10:04:01 +08:00
@franky_xhl 我就是按照这个库配的,按他的配法遇到的问题就是 nginx 没法反代静态文件
dylanninin
2017-06-17 10:51:19 +08:00
10 楼已经一针见血指出问题,楼主对 docker 理解不足,所以暂时不用急着用 docker,建议:
- 先搞清楚在不用 docker 的情况下如何该部署,架构如何,并自动化,这是后续步骤的前提
- 如果真心想用 docker,先花一些时间进行系统化的学习,看看官方文档、跟着实践等等
- 在项目中,可以先从 demo 环境开始使用 docker,相信你会遇到一些问题,尝试解决之
- 对于 production,不要急着用,除非你已经足够自信
chuanqirenwu
2017-06-17 11:12:31 +08:00
@dylanninin 谢谢指出!我确实是刚学 Docker 不久,昨晚根据大家的回答我重新看了一遍 Docker 的 volumes 文档,目前问题基本解决了。虽然不确定是不是好的解决方案。目前 docker-compose.yml 是这样的:

version: '2'

services:
django:
build:
context: .
dockerfile: ./compose/django/Dockerfile
command: /gunicorn.sh
volumes:
- static-file:/app/static
- sqlite3-db:/app/database

nginx:
build: ./compose/nginx
depends_on:
- django
volumes:
- static-file:/home/app/static
ports:
- "0.0.0.0:80:80"

volumes:
static-file: {}
sqlite3-db: {}

我把静态文件和数据库文件均放到一个数据卷容器里,让 django 和 nginx 共享,这样 nginx 可以代理静态文件了,从新构建容器启动容器数据库也还在了。不知道这样的解决方案是否合理?
dylanninin
2017-06-17 12:15:29 +08:00
@chuanqirenwu 赞,楼主学习动手能力不错。

看你的 yml,可以改进的地方:
- nginx 可以直接使用 docker 上已有的 image,不需要自己 build ;配置文件以 volume 的方式挂在即可
- 可以试着把 docker-compose 中写死的变量 ENV 化

12 楼给出了一个参考的链接,很不错,建议楼主也看看。
chuanqirenwu
2017-06-17 12:29:25 +08:00
@dylanninin 嗯,谢谢,我就是参考这个项目做得。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/368982

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX