Python项目镜像瘦身实践

3,212 阅读3分钟

这是我参与更文挑战的第27天,活动详情查看: 更文挑战

背景

之前做的一个Python项目使用Docker部署,研究了一下如何对镜像进行瘦身,把笔记整理汇总一下

Python项目瘦身

基于Python做的FastText预测,而FastText底层依赖于C++的.so动态库,所以在通过pip安装fasttext时,需要使用gcc来编译

方式1: 直接使用python:latest

直接拉取python:latest,它包含完整的pip环境和GCC编译环境,可以正常构建镜像和部署,但唯一的问题就是image的体积太大,最后生成的image有1.5G

方式2: 多阶段构建python:3.7.7和python:alpine3.11

python:alpine3.11是python官方镜像中最小的,第一个阶段使用python:3.7.7编译web.py和fasttext,然后第二个构建阶段将site-package目录下的文件都拷贝到python:alpine3.11中,但问题是alpine版本的C++动态库环境缺少很多,即使是从python:3.7.7中把stdc++.so等库拷贝过来,但是仍然会有动态库中找不到symbol的问题,猜测应该是alpine这个版本的兼容性上有问题

方式3: 多阶段构建python:3.7.7-slim

Dockerfile中使用两个阶段分别做编译和生成最终镜像,两个阶段都使用python:3.7.7-slim

但第一个阶段编译失败,原因是fasttext要求支持C++11,但是slim版本无法编译通过,所以这种方法行不通

在开发和测试阶段,推荐使用原生基础镜像,虽然尺寸比较大,但用起来就像你主机上安装的Ubuntu一样,而且能访问该操作系统里有的所有二进制程序。

方式4: 多阶段构建python3.7.7和python:3.7.7-slim

python:3.7.7-slim这个镜像包含python环境和完整的gcc环境,可以完美解决瘦身问题

# 第一个阶段基于python做构建
FROM python:3.7.7 as builder

# 安装web.py,fasttext,然后删除临时文件(下面直接拷贝site-packages,避免冗余)
RUN pip install web.py==0.51 && pip install fasttext && find /usr/local/lib -name '*.pyc' -delete

# 第二个阶段基于slim做构建
FROM python:3.7.7-slim

# 拷贝编译好的库
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages

RUN mkdir /apps

COPY predict.py /apps
#COPY model.bin /apps

WORKDIR /apps

CMD ["python", "/apps/predict.py", "9999"]

镜像瘦身笔记

  1. 每个RUN语句都会创建一个新层,所以多个RUN语句使用&&来串联起来执行
# 使用&&串联起来,只会创建一个layer
RUN apt-get update && apt-get install vim
  1. 使用多阶段构建,将第一个阶段编译好的文件直接拷贝到第二个阶段
# 第一个阶段编译和安装环境
FROM node:8 as build

WORKDIR /app
COPY package.json index.js ./
RUN npm install

# 第二个阶段将编译好的文件拷贝过来
FROM node:8

COPY --from=build /app /
EXPOSE 3000
CMD ["index.js"]
  1. 使用Distroless移除容器中的所有累赘

Google开源出来了它使用的Distroless镜像,它只包含应用程序及其运行时依赖。不包含包管理器、Shell以及其他标准Linux发行版中能找到的其他程序,但需要翻墙才能下载下来对应的镜像

FROM node:8 as build

WORKDIR /app
COPY package.json index.js ./
RUN npm install

FROM gcr.io/distroless/nodejs

COPY --from=build /app /
EXPOSE 3000
CMD ["index.js"]
  1. 使用Alpine作为更小的基础镜像

Alpine Linux是一个基于musl libc和busybox、面向安全的轻量级Linux发行版,可以基于这个版本做业务镜像,它甚至比Distroless镜像还要小

注意,Alpine镜像没有bash,但有sh

FROM node:8 as build

WORKDIR /app
COPY package.json index.js ./
RUN npm install

FROM node:8-alpine

COPY --from=build /app /
EXPOSE 3000
CMD ["npm", "start"]