引言
一个成熟的python项目可能会依赖很多特定的环境,然而项目运行的结果不仅取决于代码,和运行代码的环境也息息相关。这很有可能会造成,开发环境上的运行结果和测试环境、线上环境上的结果都不一致的现象。为了解决这个问题,我们可以将python项目打包成docker镜像,这样即使在不同的机器上运行打包后的项目,我们也能够得到一致的运行结果。
准备工作
安装docker
可以使用如下脚本一键安装
1 | sudo curl -sSL https://get.daocloud.io/docker | sh |
也可参考 CentOS Docker基础环境安装
准备python项目
在项目根目录下添加以下两个文件
requirements.txt 该文件描述了python项目的依赖环境,使用如下命令即可导出相关库的信息并自动生成依赖文件
1
pip freeze > requirements.txt
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 将官方 Python 运行时用作父镜像,根据需要选择python版本
FROM python:3.7
# 记录维护这信息
MAINTAINER zhangjie@parkson.com.cn
# 将工作目录设置为 /myapps
WORKDIR ./myapps
# 将当前目录内容复制到位于 /myapps 中的容器中
ADD . .
# 安装 requirements.txt 中指定的任何所需软件包
RUN pip install -r requirements.txt
# 使用匿名卷持久化存储日志或者其它数据,匿名卷实际地址在docker安装目录下,可以用docker inspect查看
VOLUME [/logs1,/logs2]
# 定义环境变量
ENV name1=var1 name2=var2
# 暴露端口配置,默认TCP,可指定为udp
EXPOSE [80/tcp,80/udp]
# 在容器启动时运行 hello_world.py
ENTRYPOINT ["python", "./myapps/hello_world.py"]note:有时候pip install -r requirements.txt很慢,可以考虑换源,只需将原命令改为如下即可
1
RUN pip install -r requirements.txt -i https://pypi.douban.com/simple
打包镜像
在Dockerfile所在的目录下运行
1 | sudo docker build -t demo:v1 . |
其中demo为镜像名称,v1为镜像tag用于版本管理
运行容器
1 | sudo docker run demo:v1 |
其它常用参数,根据需要使用:
- -d: 后台运行容器,并返回容器ID;
- -v /opt/logs:/logs 挂载目录,将容器中的目录映射到宿主机中,格式为宿主机目录:容器中的目录
- -p 80:80 指定端口映射,格式为:主机(宿主)端口:容器端口
- -e username=”ritchie” 设置环境变量;
- –env-file .env 使用.env文件设置环境变量
- –name nginx1.18 为容器指定一个名称;
- –link mysql:mysql 添加链接到另一个容器;
标准化自动打包、自动部署流程
本规范仅专注于如何打包python容器,如果需要结合jenkins自动化部署流程,则需要参照以下步骤
添加docker.sh文件
需要在项目根目录添加docker.sh文件,参照如下:
设置镜像名称BUILD_IMAGE_NAME
不需要设置tag,统一使用构建时间生成,构建成功后保存在.docker_build_version文件中
根据项目设置run()函数容器的映射端口
1 |
|
赋予docker.sh执行权限
1 | sudo chmod a+x docker.sh |
设置dockerhub相关环境变量
这些环境变量在docker.sh中会用到,并且所有docker打包发布相关操作都会用到,因此强烈建议直接配置到/etc/profile
1 | # docker仓库相关信息 |
docker.sh使用方法
查看使用方法
1 | ./docker.sh |
构建镜像
1 | ./docker.sh build |
运行镜像
1 | ./docker.sh run |
推送镜像
1 | ./docker.sh push |
标记为最新版本
1 | ./docker.sh tag-latest |
推送最新版本
1 | ./docker.sh push-latest |
标记为生产版本
1 | ./docker.sh tag-prod |
推送生产版本
1 | ./docker.sh push-prod |
标记为生产最新版本
1 | ./docker.sh tag-prod-latest |
推送生产最新版本
1 | ./docker.sh push-prod-latest |
执行流水线作业
build(如果已经构建不会重新构建)->push->tag-latest->push-latest
1 | ./docker.sh pipeline |
执行生产流水线作业
build(如果已经构建不会重新构建)->tag-prod>push-prod->tag-latest->push-latest
1 | ./docker.sh pipeline-prod |
执行全部流水线作业
build(如果已经构建不会重新构建)->push->tag-latest->push-latest->tag-prod>push-prod->tag-latest->push-latest
1 | ./docker.sh pipeline-all |
执行流水线作业(强制重新构建镜像)
build(每次都重新构建镜像)->push->tag-latest->push-latest
1 | ./docker.sh pipeline-rebuild |
执行生产流水线作业(强制重新构建镜像)
build(每次都重新构建镜像)->tag-prod>push-prod->tag-latest->push-latest
1 | ./docker.sh pipeline-prod-rebuild |
执行全部流水线作业(强制重新构建镜像)
build(每次都重新构建镜像)->push->tag-latest->push-latest->tag-prod>push-prod->tag-latest->push-latest
1 | ./docker.sh pipeline-all-rebuild |
项目相关环境变量配置
在项目根目录下添加.env文件(用于设置环境变量,更多环境变量请根据项目进行设置)
.env
1 | dev、test、prod |
docker-compose.yml中环境变量的优先级
需要区分两种环境变量,一种指传递到容器内部的环境变量,一种指docker-compose.yml文件中通过${}符号引用用于设置docker-compose的环境变量。
前者的优先级从低到高如下:
- docker-compose.yml中声明env_file
- docker-compose.yml声明environment
后者的优先级从低到高如下:
同一目录下放一个.env文件
在/etc/profile或者在shell中通过export设置环境变量
注意,存在.env文件在前者和后者都使用的情况,此种情况各论各即可
添加docker-compose.yml文件
在项目根目录下添加docker-compose.yml文件
docker-compose.yml
设置镜像名称(格式:项目代号,形如xxx-yyy-zzz,例如aglaia-ui-re)
容器名称与镜像名称保持一致
主机名称与镜像名称保持一致
根据项目设置容器的映射端口
大部分基底容器默认不支持中文,为了保持统一只设置时区为Asia/Shanghai,语言方面以英语作为默认语言
1 | version: "3.5" |
docker-compose.yaml使用方法
该文件主要用于部署配合Jenkins自动化部署使用
将docker-compose.yml上传到服务器的”/docker/compose/<项目代号>/“目录下
启动容器
前台
1 | docker-compose up |
启动容器
后台
1 | docker-compose up -d |
销毁容器
1 | docker-compose down |
更新镜像
1 | docker-compose pull |
查看日志
查看最后500行日志
1 | docker-compose logs --tail 500 |
查看最后500行日志(滚动刷新)
1 | docker-compose logs --tail 500 -f |