文章目录
- 1、生成requirements.txt
- 2、编写dockerfile
- 3、构建镜像
- 4、启动容器
- 5、编写脚本自动化完成上述操作
- 6、end
1、生成requirements.txt
这里使用pipreqs
进行依赖库的识别。使用 pipreqs 可以自动检索到当前项目下的所有组件及其版本,并生成 requirements.txt 文件。相比直接用pip freeze 命令,避免将整个python环境的依赖包写入。
在项目的当前目录中执行
pipreqs ./ --encoding=utf8 --force
这里使用的是一个基于flask项目,目录结构如下
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运行控制台了。
我们本地访问我们配置的映射端口即可,浏览器输入127.0.0.1:5001
即可
查看我们刚刚生成的容器。
5、编写脚本自动化完成上述操作
通过脚本去将第二章中的dockerfile设置为模板,每次只需要自定义镜像名称即可,也可直接使用默认值。
脚本按如下逻辑依次执行
完整代码如下
import osimport sysimport timedef 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_nameself.image_name = image_namedef 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.txtCOPY . {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 Truedef 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 imagesreturn Falsedef 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)
运行完成后的输出如下
6、end
如果需要部署示例的这份源码可以关注公众号”一颗程序树“在公众号菜单进行获取