在Docker上部署Python的Flask框架的教程


Posted in Python onApril 08, 2015

本文中,我将尝试展示用Docker开发python应用(主要是Web应用)的可行方法。虽然我本人专注于Python的Flask微框架,但本文目的是演示如何通过Docker更好地开发和共享应用程序,(由任何语言和框架开发的应用程序)。Docker通过封装依赖项,大大减少了开发环境和正式产品的差距。

大多数Python开发人员在开发中使用virtualenv。它提供了一种易用的机制让应用程序使用自己专用的依赖项,这些依赖项可能与在其它应用程序或操作系统存在冲突(尤其是不同的Pyhton版本,还有不同的库版本等等)。个人而言,我对virtualenv一直没有太大兴趣,原因如下:

  1.     我经常忘记启用它,或者在切换工程时忘记切换它,这会遇到含糊的出错信息,另人倍感困惑。
  2.     它无法提供“纯粹的”隔离,只能是Python级别的隔离(系统库和非python的依赖项仍然会出问题)。
  3.     我通常不想在正式产品中运行它,这就意味着在开发环境和正式产品的不一致。
  4.     它让人感觉有点“黑客”作法:它是依靠修改脚本和设置新路径实现的。

( 查看 pythonrants的这篇文章 了解更多为什么你可能不想用virtualenv )

那么,怎么做Docker才能变得更好呢?Docker本质上提供了非常轻量化的VMs(在说法上可以称为“容器”),我们可以使用其创建一个高标准隔离并能大大减少失配的开发和产品环境。(如果你不熟悉Docker,却还想学习更多,你可以查看我在爱丁堡技术座谈会上介绍Docker的谈话)。

当我们建立一个小型的可视化Web APP,我自己和Mark Coleman使用这种方法(文档在这)。这(里面)划出了一个基本镜像安装Python 2.7,还有一些Flask管理以及PostgreSQL的内容。我会依据这个镜像去开发一个hello world的Web应用。我假设你是在Linux上开发,并且你已经有git,还安装了Docker,MacOS的指令应该非常类似。通过克隆和建立基本镜像开始:
 

$ git clone https://github.com/mrmrcoleman/python_webapp
$ docker build -t python_webapp .

现在,我们需要为容器中添加一些代码并详细写明。我们打算新建一个仅仅指向Docker镜像的项目来完成这项工作,而不是直接修改之前的项目。

创建一个具有下列结构的新项目:

 

├── Dockerfile

 ├── example_app

 │   ├── app

 │   │   ├── __init__.py

 │   │   └── views.py

 │   └── __init__.py

 ├── example_app.wsgi 

或者克隆该地址的示例项目: https://github.com/amouat/example_app.git

在example_app/app/_init_.py中写入:
 

from flask import Flask
 
app = Flask(__name__)
from app import views

使另一个_init_.py为空。在views.py中写入:
 

from app import app
 
@app.route('/')
@app.route('/index')
def index():
  return "Hello, World!"

以上就是我们的一个hello world应用的最小flask版本。我在 这个教程中也使用过类似的代码,所以如果你刚刚接触Flask或者Python,你可以根据上述提到的教程,使用Docker而不是virtualenv继续学习。

为了使之运行在Docker容器内部,我们还需要做一些操作。在我们的实例Apache服务器中,example_app.wsgi文件包含了连接Python代码和web服务器的指令。该文件应当包含下列内容:
 

import site
site.addsitedir('/opt/example_app/')
from app import app as application

最终,我们需要一个Dockerfile来构建容器并运行容器。在我们的实例中,它看起来是这样的:
 

FROM python_webapp
 
MAINTAINER amouat
 
ADD example_app.wsgi /var/www/flaskapp/flaskapp.wsgi
CMD service apache2 start && tail -F /var/log/apache2/error.log

ADD那行为启动WSGI注入了一些代码。CMD那行在启动容器,启动apache web服务器时获取任何可能的错误信息,并将其发送至stdout。

如果你下列操作:
 

$ docker build -t example_app .
$ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app

你应当会得到这样的回馈:通过浏览器打开地址localhost:5000,你会看到你的网站正在运行。如果你实在VM或者vagrant中运行,记得打开5000端口。

现在我们运行了web服务器,已经非常接近我们在产品中使用的东西了(我有意的使用Apache来做这点而不是Python默认的web服务器)。我们通过从主机向容器映射的方式向容器中注入代码;也可以在Dockerfile命令行中是用ADD来添加代码,但那样的话当我们队代码进行改动时,每次都需要重新构建容器。

然而,这仍然不是很好 ;开发中我们真的希望使用很大程度上帮助我们调试的Python web服务器。该高兴的是我们不用对Dockerfile进行任何修改。在example_app文件从创建一个run.py文件开始,按照一下内容:
 

!flask/bin/python
from app import app
app.run(debug = True, host='0.0.0.0')

这将启动Python的带调试的web服务器并监听所有连接,我们也能从容器外访问。现在用下列命令重启容器:
 

$ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app python /opt/example_app/run.py

你能看到网页又运行了。这次我们显式地提供运行的命令("python /opt/example_app/ryn.py"),它覆盖了Dockerfile中的CMD行的设置。现在如果编辑在主机上的源程序,就能马上看到网页上的改变。

让我们花点时间看看我们的收获:

  1.     一个运行在隔离容器中的web应用,容器完全封装了应用的Python依赖项和系统依赖项。
  2.     能够使用现有编辑器或IDE开发代码并直接查看变化,就像在本地编辑一样。
  3.     比以前更接近正式产品的运行环境。
  4.     没有使用virtualenv。

如果你想知道如何以这种方式建立程序发布的途径,可以看看Mark Coleman写的关于前面提到的可视化Web应用的文章。

不幸的是,这一切还不完美。还有下列几个问题:

  1.     你可能仍会遇到需要使用virtualenv或其等价解决方案的情况,例如库的操作系统版本与你的程序所需版本间的冲突。
  2.     我们还没完全解决数据托管的问题,仍需做某些测试。
  3.     我假设的“产品”是一个Docker容器,但实际情况常常并非如此而且Docker托管本身也刚刚起步。

尽管如此,我仍然认为这向软件开发的更好未来迈了一大步,大大减轻了部署软件和管理依赖项的痛苦。

Python 相关文章推荐
python网络编程示例(客户端与服务端)
Apr 24 Python
简单介绍Ruby中的CGI编程
Apr 10 Python
Python实现在线暴力破解邮箱账号密码功能示例【测试可用】
Sep 06 Python
Python算法之图的遍历
Nov 16 Python
解析Python中的eval()、exec()及其相关函数
Dec 20 Python
Python学生信息管理系统修改版
Mar 13 Python
Numpy数据类型转换astype,dtype的方法
Jun 09 Python
python操作excel的方法
Aug 16 Python
如何利用Python分析出微信朋友男女统计图
Jan 25 Python
Python selenium如何打包静态网页并下载
Aug 12 Python
Selenium环境变量配置(火狐浏览器)及验证实现
Dec 07 Python
教你使用TensorFlow2识别验证码
Jun 11 Python
python threading模块操作多线程介绍
Apr 08 #Python
Python使用scrapy采集数据时为每个请求随机分配user-agent的方法
Apr 08 #Python
python中Genarator函数用法分析
Apr 08 #Python
探索Python3.4中新引入的asyncio模块
Apr 08 #Python
Windows下用py2exe将Python程序打包成exe程序的教程
Apr 08 #Python
Python bsddb模块操作Berkeley DB数据库介绍
Apr 08 #Python
Python使用scrapy采集数据过程中放回下载过大页面的方法
Apr 08 #Python
You might like
php数组函数序列之array_combine() - 数组合并函数使用说明
2011/10/29 PHP
JavaScript 组件之旅(三):用 Ant 构建组件
2009/10/28 Javascript
让IE8支持DOM 2(不用框架!)
2009/12/31 Javascript
根据一段代码浅谈Javascript闭包
2010/12/14 Javascript
js 链式延迟执行DOME
2012/01/04 Javascript
js关闭浏览器窗口及检查浏览器关闭事件
2013/09/03 Javascript
jquery实现按Enter键触发事件示例
2013/09/10 Javascript
js处理表格对table进行修饰
2014/05/26 Javascript
通过JS来动态的修改url,实现对url的增删查改
2014/09/01 Javascript
js实现图片从左往右渐变切换效果的方法
2015/02/06 Javascript
js网页滚动条滚动事件实例分析
2015/05/05 Javascript
javascript正则表达式总结
2016/02/29 Javascript
jquery 实现回车登录详解及实例代码
2016/10/23 Javascript
JS弹出窗口的运用与技巧大全
2016/11/01 Javascript
利用JS屏蔽页面中的Enter按键提交表单的方法
2016/11/25 Javascript
微信小程序-获得用户输入内容
2017/02/13 Javascript
JS div匀速移动动画与变速移动动画代码实例
2019/03/26 Javascript
JS左右无缝轮播功能完整实例
2019/05/16 Javascript
浅谈Vuex的this.$store.commit和在Vue项目中引用公共方法
2020/07/24 Javascript
js属性对象的hasOwnProperty方法的使用
2021/02/05 Javascript
[03:37]2014DOTA2国际邀请赛 主赛事第一日胜者组TOPPLAY
2014/07/19 DOTA
python编程羊车门问题代码示例
2017/10/25 Python
对python指数、幂数拟合curve_fit详解
2018/12/29 Python
解决tensorboard多个events文件显示紊乱的问题
2020/02/15 Python
Jupyter notebook 远程配置及SSL加密教程
2020/04/14 Python
python中pyqtgraph知识点总结
2021/01/26 Python
英国香水店:The Perfume Shop
2017/03/27 全球购物
Hunkemöller瑞士网上商店:欧洲最大的内衣品牌之一
2018/12/03 全球购物
STAUD官方网站:洛杉矶独有的闲适风格
2019/04/11 全球购物
银行演讲稿范文
2014/01/03 职场文书
小学红领巾中秋节广播稿
2014/01/13 职场文书
2014学习全国两会精神心得体会2000字
2014/03/11 职场文书
初中优秀班集体申报材料
2014/05/01 职场文书
银行贷款委托书范本
2014/10/11 职场文书
2016年第104个国际护士节活动总结
2016/04/06 职场文书
3050和2060哪个好 性能差多少 差距有多大 谁更有性价比
2022/06/17 数码科技