使用docker封装python应用

Posted by Hsz on May 15, 2017

为什么要使用docker

python的工具链非常完善,从开发调试测试到部署,有一系列简单好用的工具. 而批量部署的话也有fabric可以实现. 从运维的角度来说docker的所谓一次编辑随处部署在python的世界里是多余的.那为什么还要用docker呢?

假设有这样一个场景,你没有考略到你的应用要占用多少cpu资源内存资源就把你的项目上线了,然后由于你的应用把内存资源耗尽,服务器主机当机了.这种情况非常容易发生,而且似乎我们也没有什么好办法避免.这种时候就只能依靠docker这种虚拟化技术了.

依赖

项目依赖flaskpymongo

docker构建依赖docker

封装python应用

我们以一个简单的flask项目作为例子,看怎么封装的,项目在我的github上.

该项目由一个requirements.txt文件和一个app.py文件构成,它需要外部的mongodb来存取数据. 项目的共能也非常简单–为一个collection提供增,查功能.代码如下

from flask import Flask, request, json
from flask.views import MethodView
from pymongo import MongoClient
import argparse


def args_parse():
    parser = argparse.ArgumentParser()
    parser.add_argument("-H", "--host", type=str,
                        help="主机", default="localhost")
    parser.add_argument("-p", "--port", type=int, help="端口", default=27017)
    parser.add_argument("-d", "--database", type=str,
                        help="数据库", default="default")
    args = parser.parse_args()
    return args


args = args_parse()
client = MongoClient(args.host, args.port)
db = client[args.database]
user_collection = db.user


class UserAPI(MethodView):

    def get(self):
        if not request.args:
            result = [i for i in user_collection.find()]
        else:
            if request.args["user_name"]:
                result = [i for i in user_collection.find(
                    {"user_name": request.args["user_name"]})]

            else:
                result = [i for i in user_collection.find()]

        return json.dumps(str(result))

    def post(self):
        obj = request.get_json()
        result = user_collection.save(obj)
        return json.dumps({'result': str(result), 'ok': True})


app = Flask(__name__)
app.add_url_rule('/users/', view_func=UserAPI.as_view("users"))


def main():
    app.run(debug=True, host="0.0.0.0")


if __name__ == '__main__':
    main()

app默认链接localhost的27017的mongodb.可以通过命令行修改链接的mongo主机和端口 默认启动在本地5000端口,并且可以内网访问

Dockerfile

Dockerfile

FROM python:3.6
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt

在项目目录下使用docker build -t example_app .创建镜像

跑项目只要:

docker run -p 5000:5000 example_app python /code/app.py -H <你的mongo主机> -p <你的端口> -d <你的数据库名>

限制资源

这边是重点了,之所以要使用docker甚至不惜牺牲一些性能主要也就是为了可以控制资源使用.

Cpu限制

要限制cpu使用某几个cpu

  • 默认的libcontainer引擎

    只要run后面加上参数--cpuset=0,3来指定.这样就是只是用了1号和4号cpu了.

    如果要设置相对的cpu权重比,可以使用--cpu-shares=nn必须为一个非负数

  • 如果使用lxc引擎,

    可以指定 –lxc-conf=”lxc.cgroup.cpuset.cpus = 0,1” 如果要设置相对的cpu权重比,可以使用--lxc-conf="lxc.cgroup.cpu.shares = 1234"

内存限制

-m参数可以直接设定内存的最大使用量

-m 100m这样就是只允许使用100m大小的内存,多了就会自己崩溃

本文主要是针对python玩家,专业的运维还需要了解docker-compose这类容器编排工具.这就不在本文的范围内了.