2.3.4 打包示例

下面我们结合Pipenv和Docker两个工具,开发和部署一个可迁移到不同操作系统和平台的Web服务。该服务是一个简易的Python/Flask Web服务,以展现Docker中的开发模式。这里涉及一个特殊的文件Dockerfile,Dockerfile是构建镜像的文本文件,内容由一行行命令组成,支持以#开头的注释行。Dockerfile一般可分为4个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。限于篇幅本书,不详细讲述如何编写Dockerfile,只说明其用到的指令的含义。

1)建立项目目录、Dockerfile文件、源文件。


mkdir docker_web;cd docker_web
touch Dockerfile
mkdir src
touch src/index.py

2)使用Pipenv构建所需要的flask包,该命令会自动创建Pipfile和Pipfile.lock文件。该文件将作为软件包发布。


pipenv install flask

得到如下的Pipfile内容:


[~/mb/docker_web] # cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
flask = "*"
[requires]
python_version = "3.6"

3)编码实现Web服务,代码如下:


# cat /src/index.py
from flask import Flask
from flask import Response
app = Flask(__name__)
@app.route("/")
def hello():
    res = Response("Hi, Python")
    res.headers['Content-Type'] = 'text/plain'
    return res
if __name__ == "__main__":
    app.run(host='0.0.0.0')

4)运行测试。Flask会默认开启5000端口,访问http://localhost:5000/将返回“Hi,Python”。


python3 src/index.py

上述4个步骤的目的是在本地开发、测试Web服务。至此,该过程生成的Pipfile*已经可以作为Python环境的发布文件。下面我们更进一步,将上述开发的内容以Docker方式打包并发布,以说明使用Docker的开发模式的完整流程。

5)编写Dockerfile文件。


# 拉取镜像
FROM python:3.6-alpine
# 开放5000的端口
EXPOSE 5000
# 镜像内安装Pipenv
RUN pip install pipenv
# 镜像内建立源文件目录
RUN mkdir -p /app/src
# 切换为工作目录
WORKDIR /app
# 将本地文件添加到镜像目录/app中
ADD Pipfile /app
ADD Pipfile.lock /app
ADD src/index.py /app/src
# 在镜像内重现上述Web环境
# --system参数说明镜像内不再构建虚拟环境,而是使用系统的Python环境
# --ignore-pipfile 表明只使用Pipfile.lock中的信息
RUN pipenv install --system --deploy --ignore-pipfile
# 镜像启动时运行index.py文件,即启动Web服务
CMD ["python", "/app/src/index.py"]

6)构建镜像。


# 在Dockerfile所在目录执行。成功后可使用docker images查看新构建的镜像docker_web.v1
docker image build -t docker_web.v1 .

7)使用镜像启动容器。


# -d 后台运行容器
# -p 宿主机端口:容器内端口
# --name 容器名称
docker run -d -p 9876:5000 --name docker_web docker_web.v1

8)宿主机测试返回“Hi,Python”,说明镜像发布成功。


curl http://localhost:9876

至此,本节快速而简洁地构建了一个Web服务,模拟了开发、测试、发布这一流程,该服务虽没有任何实质性的功能,但这种独立的服务,可归类到微服务(Microservice)概念范畴。第17章将会详细讲述如何构建企业级的、大规模模型服务上线的微服务框架,感兴趣的读者可跳转阅读,将本节内容作为铺垫。