在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继承和抽象类的实现方法
Jan 14 Python
python获取本机mac地址和ip地址的方法
Apr 29 Python
在Python中操作列表之List.pop()方法的使用
May 21 Python
在Linux下使用Python的matplotlib绘制数据图的教程
Jun 11 Python
Python安装第三方库的3种方法
Jun 21 Python
Python读写/追加excel文件Demo分享
May 03 Python
Python读取系统文件夹内所有文件并统计数量的方法
Oct 23 Python
Django 实现将图片转为Base64,然后使用json传输
Mar 27 Python
解决paramiko执行命令超时的问题
Apr 16 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
Aug 11 Python
python 模拟登陆163邮箱
Dec 15 Python
使用numpngw和matplotlib生成png动画的示例代码
Jan 24 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 Try Catch异常测试
2009/03/01 PHP
PHP设计模式 注册表模式(多个类的注册)
2012/02/05 PHP
深入PHP操作MongoDB的技术总结
2013/06/02 PHP
php使用GD库创建图片缩略图的方法
2015/06/10 PHP
在js中使用"with"语句中跨frame的变量引用问题
2007/03/08 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
js加强的经典分页实例
2013/03/15 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
jQuery学习笔记之2个小技巧
2015/01/19 Javascript
jQuery原型属性和原型方法详解
2015/07/07 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
jQuery EasyUI 页面加载等待及页面等待层
2017/02/06 Javascript
详解Angular2中Input和Output用法及示例
2017/05/21 Javascript
js实现登录与注册界面
2017/11/01 Javascript
JavaScript实现百度搜索框效果
2020/03/26 Javascript
微信公众平台 发送模板消息(Java接口开发)
2019/04/17 Javascript
详解vue的数据劫持以及操作数组的坑
2019/04/18 Javascript
谈谈JavaScript中的函数
2020/09/08 Javascript
python实现合并两个数组的方法
2015/05/16 Python
Python设计模式中单例模式的实现及在Tornado中的应用
2016/03/02 Python
python django 实现验证码的功能实例代码
2017/05/18 Python
python 显示数组全部元素的方法
2018/04/19 Python
Python Excel处理库openpyxl使用详解
2019/05/09 Python
浅谈python已知元素,获取元素索引(numpy,pandas)
2019/11/26 Python
使用python实现下载我们想听的歌曲,速度超快
2020/07/09 Python
python实现双人五子棋(终端版)
2020/12/30 Python
SAZAC的动物连体衣和动物睡衣:Kigurumi Shop
2020/03/14 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
党委书记岗位职责
2013/11/24 职场文书
应届毕业生自荐信例文
2014/02/26 职场文书
县政府领导班子四风问题对照检查材料思想汇报
2014/09/26 职场文书
群众路线教育实践活动学习笔记
2014/11/05 职场文书
销售业务员岗位职责
2015/02/13 职场文书
研究生简历自我评
2015/03/11 职场文书
2016年4月份红领巾广播稿
2015/12/21 职场文书
基于Redis结合SpringBoot的秒杀案例详解
2021/10/05 Redis