1、生成requirements.txt

这里使用pipreqs进行依赖库的识别。使用 pipreqs 可以自动检索到当前项目下的所有组件及其版本,并生成 requirements.txt 文件。相比直接用pip freeze 命令,避免将整个python环境的依赖包写入。
在项目的当前目录中执行
pipreqs ./ --encoding=utf8 --force
这里使用的是一个基于flask项目,目录结构如下
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP

2、编写dockerfile

dockerfile定义python版本号,将本地项目进行拷贝,定义启动命令。
这部分固定流程我们其实可以抽象出来通过自定义脚本去一键生成。这里做一个简单的示例。自动生成脚本见文末。

# 基于的基础镜像
FROM python:3.8.8

# 设置app文件夹是工作目录
WORKDIR /usr/src/app

# 先将依赖文件拷贝到项目中
COPY requirements.txt /usr/src/app

# 执行指令,安装依赖
RUN pip install -r requirements.txt

# 拷贝当前目录的项目文件和代码
COPY . /usr/src/app

# 执行命令
CMD [ "python", "/usr/src/app/app.py" ]

3、构建镜像

这里以我自己写的一个疫情可视化的flask项目为例,项目名称为epidemic

docker build -f dockerfile -t epidemic .

这里就是读取项目目录下的dockerfile进行构建
-f

4、启动容器

镜像构建完成后使用docker run启动容器,-p指定

docker run -it -p 5001:5000 --name epidemic_container epidemic

-p 指定端口映射,格式为:主机(宿主)端口:容器端口
-i: 以交互模式运行容器,通常与 -t 同时使用;
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
运行完成后我们就能看到如下界面,这里的控制台输出的就是此时容器中的flask运行控制台了。
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP

我们本地访问我们配置的映射端口即可,浏览器输入127.0.0.1:5001即可
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP
查看我们刚刚生成的容器。
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP

5、编写脚本自动化完成上述操作

通过脚本去将第二章中的dockerfile设置为模板,每次只需要自定义镜像名称即可,也可直接使用默认值。
脚本按如下逻辑依次执行

完整代码如下

import os
import sys
import time


def get_cmd(cmd):
    res = os.popen(cmd)
    return res.read()


class Generate:
    def __init__(self, dockerfile_name="generate.dockerfile", image_name="docker_img"):
        self.dockerfile_name = dockerfile_name
        self.image_name = image_name

    def generate_dockerfile(self, work_dir="/usr/src/app", main_file="app.py"):
        # 首先生成dockerfile模板,python版本通过命令行获取
        python_version = sys.version.split(" ")[0]
        template = f"""
FROM python:{python_version}
WORKDIR {work_dir}
COPY requirements.txt {work_dir}
RUN pip install -i https://pypi.doubanio.com/simple/ -r requirements.txt
COPY . {work_dir}
CMD [ "python", "{work_dir}/{main_file}" ]
"""
        # 检查requirements.txt文件是否存在,不存在则调用命令生成生成
        if not os.path.exists("requirements.txt"):
            print("正在等待requirements.txt文件生成,请稍候....")
            os.system("pip install -i https://pypi.doubanio.com/simple/ pipreqs && pipreqs ./ --encoding=utf8 --force")
            while not os.path.exists("requirements.txt"):
                print("正在等待requirements.txt文件生成...")
                time.sleep(2)

        # 确定requirements文件生成后,将dockerfile写入到本地
        with open(self.dockerfile_name, "w") as f:
            f.write(template)
        print(f"dockerfile生成成功,文件名称为{self.dockerfile_name}")
        return True

    def build_image(self):
        images = get_cmd(f"docker images")
        if self.image_name not in images:
            cmd = f"docker build -f {self.dockerfile_name} -t {self.image_name} ."
            print(cmd)
            os.system(cmd)
            return self.image_name in images
        return False

    def run_container(self, container_name, local_port=5001, container_port=5000):
        cmd = f"docker run -p {local_port}:{container_port} --name {container_name} {self.image_name}"
        #cmd = f"docker run {self.image_name}"
        print(cmd)
        os.system(cmd)


if __name__ == '__main__':
    generate = Generate(dockerfile_name="generate_dockerfile.dockerfile", image_name="epidemic")
    generate.generate_dockerfile()
    generate.build_image()
    generate.run_container(container_name="epidemic_container", local_port=5001, container_port=5000)

运行完成后的输出如下
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP

6、end

如果需要部署示例的这份源码可以关注公众号"一颗程序树"在公众号菜单进行获取
windows部署python项目(以Flask为例)到docker,通过脚本一键生成dockerfile并构建镜像启动容器-LMLPHP

07-15 08:36