生产镜像制作(小而快的镜像制作)

困境:平台上有几十个服务组件,每个个组件都是依托docker环境运行的,对外部署时,需要打包所有镜像实行部署,由于镜像多且镜像大,对部署来说拷贝转移数据的难度增加,为了降低部署的成本加快部署速度,我们决定对生产环境下的镜像进行重新制作,以达到镜像体积尽可能小的目标。以下会列出一个项目生产镜像制作的步骤以及docker镜像制作的一些推荐的操作。

1.生产镜像的制作

1.1镜像制作的步骤概览

1. 去官网找runtime镜像(runtime镜像只包含必须的包比devel镜像体积小)
 https://hub.docker.com/search?q=
3. 进容器测试需要打包项目运行情况,记录镜像缺少的包环境
4. 编写Dockerfile在runtime镜像的基础上构建镜像

1.2 生产镜像制作实例

1. 查看当前生产镜像服务器的目标环境(主要目标环境的CUDA版本)

nvidia-smi

在这里插入图片描述

2. 去dockerhub官网找项目依赖的pytorch的官方镜像

搜索pytorch找到官方项目(一般是star最多的名字最相似的),点击tag页面
在这里插入图片描述
在资产项目中我们使用的是
在这里插入图片描述

细心的小伙伴们可能以及注意到该镜像的cuda是11.0,而目标服务器的版本是11.3
这里涉及到一个兼容规则,一般有有向下兼容的特点,目标服务器的cuda版本是11.3它理论上支持任何版本小于11.3的镜像,但是这类基础软件有时候也存在大版本不兼容的情况,因此我们需要尽可能的选择大版本相同,小版本小于等于目标服务器的镜像。同理pytoch的版本也是一样比如开发时使用的是pytoch1.6。在选择生产镜像时pytroch版本时高于1.6即可,pytorch的向前兼容性还是比较好的。
在目标服务器上下载该镜像(点击右边复制按钮,可复制下载)

docker pull pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime

在目标服务器上查看下载镜像

docker image ls | grep cuda11.0

在这里插入图片描述

3. 缺失包安装

  1. 创建并进入容器(–rm 会在退出容器时删除该容器)
docker run --runtime=nvidia -it --rm --name ydq_image_test -v /data:/data pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime /bin/bash 
  1. 查看容器内包含的包,如果你知道项目使用到得包直接使用pip intall 安装包即可,如果不知道继续往下看
    在这里插入图片描述

  2. 在容器内运行你的项目,查看项目报错的得知所缺少的包,并且在开发环境中查看该包的版本

#这里查看是 wheel包的版本
pip show wheel

在这里插入图片描述

  1. 将缺少的包和版本,新建requirements.txt并记录
PyMuPDF==1.18.14
starlette==0.14.2
matplotlib==3.3.3
uvicorn==0.14.0
scipy==1.5.2
fastapi==0.66.0
pdfminer3k==1.3.4
cos-python-sdk-v5==1.9.14
joblib==0.17.0
xlrd==1.2.0
pandas==1.1.4
opencv-python==4.4.0.46
ConcurrentLogHandler==0.9.1

4.Dcokerfile编写

如果你对Dockerfile编写的一些命令不熟悉可以参考
Dockerfile的编写和命令
切换目录到requirements.txt所在目录,新建Dockerfile

#以刚刚下载的镜像为基础镜像
FROM pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
ENV LANG C.UTF-8
ENV DEBIAN_FRONTEND noninteractive
LABEL maintainer="[email protected]"
# 更新时区
ENV TZ=Asia/Shanghai
#将依赖包列表拷贝到镜像
ADD requirements.txt /workspace
WORKDIR /workspace
#安装依赖包
RUN /opt/conda/bin/pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ \
	&& apt update \
    && apt install -y tzdata \
    && ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
	&& apt install -y libglib2.0-dev \
	&& apt install -y libgl1-mesa-glx \
	&& apt autoremove

5.以编写好的Dockerfile构建新镜像

构建镜像

#ydq_test:v1修改成你需要的镜像名称:版本
docker build -t ydq_test:v2 . 

至此镜像制作完成,你可以进入新制作的镜像中验证代码运行情况

docker run --runtime=nvidia -it --rm --name ydq_image_test -v /data:/data ydq_test:v2 /bin/bash 

2.生产镜像的制作的推荐操作

  • (1) 关键字使用大写

  • (2) FROM镜像,指定明确的Tag,不允许使用latest

  • (3) 将上下文依赖命令放在同一个RUN命令下,减少镜像层数

  • (4) 优化Dockerfile命令顺序,将不变的放在前面

  • (5) 使用WORKDIR指定工作目录,避免绝对路径扩散

  • (6) 优先使用COPY,ADD支持远程下载,会存在安全隐患

  • (7) 避免直接在镜像中设置默认密码

  • (8) 镜像中不要安装sshd

  • (9) 对于需要访问的目录文件执行相关命令修改权限

  • (10) 使用Label命令为镜像设置元数据

  • (11) 清理临时文件,如yum install后需要执行yum clean all -y

  • (12) 禁止使用ENV和ARG传递敏感信息,因为这些信息会被通过docker image
    history看到

  • (13) 优先使用CMD/ENTRYPOINT指令的EXEC格式设置镜像的默认执行程序,
    使得应用进程PID为1,这样对容器内应用管理相对简单,1号进程退出后整个容
    器也就退出了。

  • (14) 禁用ROOT用户运行应用,为应用创建用户与用户组,应用运行用户的
    Shell设置为/sbin/nologin

  • (15) 应用程序部署WORKDIR为/opt/应用程序名称,子目录如下:
    应用程序名称
    |----bin
    |----程序二进制或者启动脚本之类
    |----conf
    |----log
    |----业务访问日志access.log
    |----业务程序运行日志

  • (16) 对于有持久性需求的应用程序,需要添加Volumes声明

  • (17) 对于Web类应用程序,统一Expose端口使用80

  • (18) 运行程序的基础镜像采用ubuntu 20.04版本

  • (19) 程序的启动命令需要加入到Entrypoint指令中,采用Exec格式

  • (20) 镜像选择release版,通过dockerfile生成镜像,不要使用docker commit 生成(没有docker分层的记录)

  • (21) 清除安装包缓存

  • (21) 多个RUN可以合并到一层

猜你喜欢

转载自blog.csdn.net/qq_21768483/article/details/124838851