如何将 Python 项目打包为 Docker

编写 requirement.txt

在封装打包为 docker 镜像前,需要确定 Python 项目所需要的 pip 依赖,并且必须确定该依赖的包的版本。浏览各个 .py 文件,检查 import 语句后的包是否非 Python 自带。以 requests 为例,确定项目引用了 requests 后,在控制台输入 pip list | grep requests 即可查看其版本。

请注意,并非每个 Python 包版本都能用该方法查询。例如 import yaml 指代的就是 PyYAML 包,然而 “yaml” 和 “PyYAML” 二者没有一个字母是相同的。在这种情况下,只能直接输入 pip list 手动查看包版本

确认了第三方包及其版本后,编写 requirement.txt ,下方是一个例子:

1
2
PyYAML==6.0
requests==2.28.1

整理项目文件夹

将项目文件全部复制到一个新的文件夹中,此处我取名为 /docker 文件夹。复制时需要注意:

  • 清空 /data/config/logs 文件夹
  • 无需复制 /doc/testREADME.md
  • /docker 新建一个 Dockerfile

一般来说,Python 项目的配置文件都放在根目录,然而为了使得 Docker 能映射卷到宿主机以在宿主机配置程序,此处仍然需要将配置文件放在专门的目录里

文件树如下(README.md 也可以删除)

1
2
3
4
5
6
7
8
9
10
.
├── bgpdump
├── config
├── data
├── Dockerfile
├── logs
├── README.md
├── requirements.txt
├── setup.py
└── src

bgpdump 作为欲使用的工具,需要先行编译后放入,否则构建镜像时可能没有编译它的环境

编写 Dockerfile

Dockerfile 内容编写如下:

1
2
3
4
5
6
7
8
9
10
11
FROM python:3.7.10-slim
# 将 python 添加进环境变量
ENV PATH /usr/local/bin:$PATH
# 对于时间敏感的项目,需要添加时区环境变量。此处为亚洲,上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
# 将项目文件复制到工作文件夹
ADD . /BGP_Collector
WORKDIR /BGP_Collector
# 安装依赖(通过清华源)
RUN pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn \
&& pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn

构建镜像

在确保已经通过 cd 打开 /docker 的前提下,控制台运行:

1
docker build -t bgp_collector ./

构建完成后通过 docker images 即可看到该镜像

1
2
3
[root@localhost BGP_Collector]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bgp_collector latest 427714bb01cd 13 minutes ago 125MB

创建容器

接下来需要创建容器,直接贴出指令:

1
docker run -itd --name="BGP_Collector" -v /home/docker/BGP_Collector/config:/BGP_Collector/config -v /home/docker/BGP_Collector/logs:/BGP_Collector/logs -v /home/bgpdata/ripe:/BGP_Collector/data --privileged=true bgp_collector /bin/sh
  • -itd: 后台交互模式运行并分配一个伪终端
  • –name: 容器名
  • -v {host_dir}:{container_dir}: 将宿主机和容器之间的特定文件进行映射,请注意,是以宿主机文件为准,即原来复制到镜像的文件都会被宿主机目录的文件替换
  • –privileged=true: 以最高权限运行容器,因为涉及数据卷的操作
  • bgp_collector: 采用的镜像名
  • /bin/sh: 执行的脚本,通俗的讲就是在内部控制台启动 bash

运行容器中的 Python 程序

接下来需要进入正在运行的容器。与 docker exec 相比,我更推荐简洁的 docker attach BGP_Collector 进入容器。

在容器中的终端(一个精简的 Debian 内核系统)运行你的程序,例如 python setup.py -d 。你能看到它能正常运行,然后,使用快捷键 Ctrl + P + Q 即可不停止程序和容器运行而退出容器。如果需要返回这个正在运行的容器,直接输入 docker attach BGP_Collector 即可。

请勿使用 exit 退出容器,这样将直接让容器关闭