本篇文章源自作者团队在长期开发过程中总结的宝贵经验,其中supervisor、gunicorn以及nginx更是在使用python开发web应用时最常用的软件,因此对于打算使用docker部署python应用的读者而言,这些最佳实践是很有参考价值。同时希望各位在日常实践过程中,也能将各自踩到过的“坑”以及宝贵的经验分享出来,大家共同进步!
我们可以使用docker简单而高效的部署python应用,同时,也有一些最佳实践来帮助我们愉快的完成部署。当然,也不是说这些最佳实践就是完成部署的唯一方式,只不过我们团队发现它们具有高可用性,并且容易维护。注意本文中大多数内容都只是代表我的立场,基于docker的实现方式有很多,你可以随便选择。本文中我不会过多的介绍volume,因为它可能需要一个单独的话题来解释。我们通常会使用volume将源代码复制到容器中,而不是在每次运行时都重新构建。
debian_frontend
docker用户应该都很熟悉这个环境变量,它告知操作系统应该从哪儿获得用户输入。如果设置为”noninteractive”,你就可以直接运行命令,而无需向用户请求输入(译者注:所有操作都是非交互式的)。这在运行apt-get命令的时候格外有用,因为它会不停的提示用户进行到了哪步并且需要不断确认。非交互模式会选择默认的选项并以最快的速度完成构建。
请确保你只在dockerfile中调用的run命令中设置了该选项,而不是使用env命令进行全局的设置,因为env命令在整个容器运行过程中都会生效,所以当你通过bash和容器进行交互时,如果进行了全局设置那就会出问题。例子如下:
# 正确的做法 – 只为这个命令设置env变量
run debian_frontend=noninteractive apt-get install -y python3
# 错误地做法 – 为接下来的任何命令都设置env变量,包括正在运行地容器
env debian_frontend noninteractive
run apt-get install -y python3requirements.txt
相比于基本的代码(codebase),应用的依赖很少发生变化,因此我们可以在dockerfile中安装项目依赖,这也可以加快之后的构建速度(之后的构建只需要构建变更的代码)。docker容器的层级构建可以缓存依赖安装的过程,所以之后的的构建速度会非常快,因为它不需要重新下载和构建依赖。
文件顺序
按照上面的思路(利用缓存)来推断,文件添加到容器的顺序至关重要。我们应该把频繁变更的文件放置到dockerfile的下方,以便充分使用缓存来加速docker的构建过程。例如,应用配置、系统配置和依赖都很少改变,我们就可以把它们放到dockerfile的顶部。而源文件,比如路由文件、视图(views)和数据库代码会经常发生改变,所以我们就可以把它们放在dockerfile的下方,注意是docker配置命令(expose、env等)的下方。
另外,不要考虑如何将你的文件拷贝到docker,它不会加快你的构建速度,因为大多数的文件根本不会用到,比如应用源文件。
应用密钥
之前我们一直不知道如何把应用密钥安全的传递给应用,后来我们发现可以使用docker run命令中的env-file参数。我们会把所有的密钥和配置都放在app_config.list文件中,然后通过这个文件交付给应用。具体如下:
docker run -d -t -—env-file app_config.list
这个方法允许我们简单地改变应用设置和密钥,而无需重建一个容器。
注意:请务必确保app_config.list在.gitignore文件的记录中,不然它不会被检录到源文件中。
gunicorn
我们使用gunicorn作为容器内部的应用服务器,gunicorn非常的稳定并且性能很好,它有非常多的配置选项,比如指定worker数量和类型(green threads、gevent等)的能力,你可以根据负载来调整应用,以获得最佳性能。
启动gunicorn很简单:
# 安装
pip3 install gunicorn
# 运行服务器
gunicorn api:app -w 4 -b 127.0.0.1:5000
最后是在nginx后面运行你的应用服务器,这样你可以进行负载均衡。
supervisord
你是不是想过在容器中运行多个进程?我想supervisord绝对是你的最佳辅助工具。假设我们想部署这样一个容器,它包含nginx反向代理以及gunicorn应用。你通过bash脚本可能就能实现,但是让我们想更加简洁一点。
supevisor是“一个进程控制系统,它支持用户在类unix操作系统上,监视并控制一些进程”。听起来很完美!你需要先在你的docker容器内安装supervisor。
run debian_frontend=noninteractive apt-get install -y
supervisor
为了让supervisor知道该运行什么以及如何管理进程,我们接下来需要为它写一个配置文件。
[supervisord]
nodaemon = true # 这个会让supervisord运行在前端
[program:nginx] # 你想运行的第一个程序的命名
command = /usr/sbin/nginx # nginx可执行程序的路径
startsecs = 5 # 如果nginx保持开启5s,我们视为启动成功
[program:app-gunicorn]
command = gunicorn api -w 4 -b 127.0.0.1:5000
startsecs = 5
这是非常基本的配置,它还有很多的配置项,比如控制日志、stdout/stderr重定向、重启策略等。这个工具真不错。
一旦你完成了配置,请确保docker将其复制到了容器中。
add supervisord.conf /etc/supervisord.conf
让supervisor作为容器的自启动命令。
cmd supervisord -c /etc/supervisord.conf
它将会在容器启动的时候,运行gunicorn和nginx。如果已经配置过了,那将会按需重启它们。
学到的东西以及未来的目标
我们已经花了很长时间在docker中部署代码,并且接下来会投入更多的时间。在使用docker的过程中,我们学到的最重要经验就是如何最小化思考(think minimally)。在一个容器中运行你的整个系统真的很诱人,但是在应用各自的容器中运行应用进程却更容易维护。一般情况下,我们会在容器中运行nignx和web服务器,并且在一些场景中,使用单独的容器来运行nginx却没有任何优势,它可能只会增加复杂度。我们发现对于大多数情况,它在容器中的开销是可接受的。
我希望这些信息对各位有价值!当我们团队学到更多最佳实践时,我会更新这篇文章。
以上就是使用docker部署python应用的方法总结的详细内容,更多请关注 第一php社区 其它相关文章!