docker实在是解决跨平台问题的神器,但在实际使用中仍有一个缺点。一个docker使用的最佳实践是,使用专门的镜像完成专门的任务。这就使得我们会在电脑上存储和使用数十个镜像。基于linux的镜像,如ubuntu等,普遍有超过100M的大小,安装python环境后能超过300M。由此带来的存储和网络传输负担甚至超过了docker跨平台带来的好处。
但幸运的是,一个特殊的linux镜像——alpine linux,只有4M大小,这就给大幅降低镜像大小带来了可能。具体的方法是:1、 使用alpine linux代替ubuntu等镜像。2、将镜像分成构建镜像和部署镜像,只在构建镜像上安装编程环境,使用gcc和pyinstaller生成可执行文件后,将这些小文件复制进原始的部署镜像中。使用这种方式生成的python部署镜像,只有不到20M。
alpine linux与经常使用的ubuntu镜像有较大的不同。
ubuntu使用apt包管理,apt install xxx来安装库;alpine使用apk包管理,apk add xxx来安装库。
安装python时,ubuntu是apt install python3 python3-pip;alpine则是apk add python3 python3-dev。
安装gcc时,alpine是apk add gcc,但是编译时会提示stdio.h不存在,这时需要apk add libc-dev。
使用pyinstaller时,alpine和ubuntu等主流系统有较大不同。alpine使用musl来代替glibc,所以pyinstaller的bootloader也要做相应更改。https://github.com/six8/pyinstaller-alpine是一个可用的基础构建镜像,在它的Dockerfile的基础上去掉entrypoint,就可以作为一个容易分发的编程环境。
在构建镜像上编译好的程序,使用docker cp复制到构建镜像,就可以submit了。保持构建镜像和部署镜像都基于同一个基础镜像,可以保证可执行文件的通用性。例如在ubuntu16.04下使用gcc编译的out文件,直接复制到alpine下不可执行。但是在pyinstaller-alpine下gcc编译的out文件,直接复制到alpine下是可以执行的。