我在尝试 docker 部署 django ,刚刚接触容器化部署,遇到了一些思维不太好转变的问题。
django 的数据库是要在 docker build container 的时候,就把服务器的数据库配置写到 settings.py 里吗,那 build 完 image ,肯定要在本地看看能不正常启动这个 container ,没问题才可以 push 上去吧。那我每次改 setting 配置,在 git 版本控制的时候,其实这些配置改动不算是一种迭代更新,因为一个程序会运行在许多个服务器,会用到许多个数据库。
除非数据库也用 docker 启动,到时候服务器启动 django 和数据库两个容器。
但是我启动数据库容器的操作也是挺麻烦的,也得改改数据库容器的配置。而且我看到 docker hub 上一些官方镜像,比如 postgresql 也有提到启动完镜像,进去创建数据库这种操作。
综上,我觉得还不如本地调试完 django container ,服务器 pull 下来,改改这个数据库和其他的一些配置。像数据库这种算基础设施,安装在宿主机上,而且这种软件不会像我们写的程序遇到太多安装问题。
整理了一下
数据库开发环境和服务器不一致,所以就要有两种数据库配置(开发 /生产环境)
构建好的镜像本地应该调试好了(不是指调试代码运行的问题,是指调试代码部署的问题),那就要求本地调试的时候,能用上服务器的数据库配置。
开发环境安装数据库软件,并创建和服务器的数据库一样的配置
或者构建数据库镜像
程序会多次部署,会用到不同数据库,每次改动数据库配置,在版本控制上来讲不算是一次迭代更新,所以觉得构建镜像前先改好数据库配置不合理
我最终的想法是,生产环境的配置先把 key 写好了,value 不写。本地测试部署,服务器部署的时候,进入镜像改改再运行
1
dier 2023-01-08 22:31:33 +08:00 via iPhone 1
关键配置或者目录可以用 -v 参数挂载当前系统中的文件或目录到容器的指定位置。
|
2
yanghanlin 2023-01-08 22:39:01 +08:00 1
按照 Twelve-Factor App 的推荐做法( https://12factor.net/config ),似乎把这些配置放到环境变量,然后 settings.py 引用环境变量比较好;或者直接将宿主机的 settings.py 通过挂载到容器中,覆盖容器中的配置?
如果部署的时候还要进入容器手动修改其中的配置文件,感觉好像就不太符合不可变基础设施的思想了😢 |
3
NoahNye 2023-01-08 22:44:47 +08:00 1
一般来说构建会基于一个基础镜像,里面会包含一些初始化信息,比如你的数据库连接信息,每次变更再基于这个镜像构建一个新的部署镜像,如果你想构建新的镜像时写入一些配置,docker 有很多功能实现这个,但我建议是用配置中心或者传配置文件,在程序上处理。
如果不喜欢每次都构建镜像,可以像楼上说的,直接映射目录到容器里,这样,每次更新,只要更新宿主机目录,再停启容器就行,但如果基础镜像有变更还是要重新构建基础镜像,这时你可能需要另外使用一条 ci/cd 去操作。 |
4
xuanbg 2023-01-08 22:55:00 +08:00 1
无论用不用 docker 部署,都最好搞个配置中心来保存配置。这样,不同环境就可以有不同的配置,程序员也不需要担心在代码里泄漏关键的配置,譬如数据库密码。
|
5
simonmao 2023-01-08 22:57:04 +08:00 1
问题:不同环境的配置问题。
像这种问题,一般都会采用环境变量+构建工具+分布式配置中心来解决。 不管在哪构建的镜像,是根据你指定的代码来进行构建,但程序环境是根据你传递的变量进行判断(把配置写死在镜像中的例外) 最简单的做法:在 docker-compose.yml 中配置环境变量,然后变量信息从目录中的 .env 读取进去,然后镜像中的程序读取对应的环境变量信息,所以无论你在本地还是服务端,只需配置不同的 .env 就能区分。 |
6
coolair 2023-01-08 23:06:57 +08:00
用这个 https://github.com/joke2k/django-environ 把配置文件用 -v 挂出来,改完直接重启容器即可。
|
7
Thecosy 2023-01-08 23:10:45 +08:00
我的做法是--link 到别的容器
|
8
phithon 2023-01-09 02:47:56 +08:00
|
9
litchinn 2023-01-09 09:26:49 +08:00
“主流”(也许仅是我眼里的)方式就是环境变量 /挂载配置文件 /配置中心,
单体应用一般环境变量或者配置文件就行了,根据需要镜像使用者自定义的配置项数目来决定。 分布式项目一般都会有配置中心,或者使用 k8s 的 configmap 挂载。 但是无论哪一种,都应该以部署脚本的方式交接,脚本放在代码仓库中,应避免人手动去操作修改参数,同时方便做自动化 |
10
Philippa 2023-01-09 09:36:09 +08:00
settings.py 有几种方法改造
1. env ,把 settings 暴露成 env ,在部署环境设置 env 来解决 2. 通过区分 settings_prod.py, settings_test.py, settings_qa.py 等来区分。但一般 prod 配置里面很多敏感信息不会乱放,所以通过挂载解决。 3. k8s 你还没用到了,里面有 config ,secret 等功能提前配置,但其实不怎么方便。我一般只用来配置 docker hub password 之类的,其他还是 env 。 docker image 理论上不应该因为 settings 在不同环境不一样而需要重新打包,只有在 settings 的 default 配置或其他代码实质变化才改。当然,如果你配置了 CI/CD 或着 k8s 有自己的 controller ,其实也没所谓。 |
11
julyclyde 2023-01-09 09:36:11 +08:00
我是反对把数据库这类有状态的程序放在容器集群运行的
|
12
slark2020 2023-01-09 10:25:18 +08:00
如果只是普通的 django 工程,简单点一般两种方式解决:
1. docker 启动时的环境变量中注入,看看 env 库 2. 把配置文件从宿主机挂载进 docker 容器,不同环境挂载不同配置文件来启动。挂载 setting 文件也可以,setting 文件读取单独的配置文件也可以。 复杂一点可以只注入配置中心的配置,其他配置从配置中心拉取,但是改造起来比较麻烦。建议用上面两种方法 部署时进入容器修改配置文件的方式不太优雅,也不利于 cicd |
13
yukun666 2023-01-09 10:33:00 +08:00
启动容器时-e 添加环境变量更好点吧
|
14
winglight2016 2023-01-09 11:25:53 +08:00
配置信息放在容器外部,这是常识。至于是用 docker -e 、docker-compose 、.env 还是挂载其他配置文件或者搞个配置服务器,都属于具体实现,看 lz 要做到什么程度吧。
|