Docker打包python项目踩坑

由于时效问题,该文某些代码、技术可能已经过期,请注意!!!本文最后更新于:1 年前

Docker踩坑

报错信息

ERROR: No .egg-info directory found in /tmp/pip-pip-egg-info-lsnfgjec

  • requirements.txt信息如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    colorama==0.4.4
    Flask==2.1.3
    Flask_Cors==3.0.10
    Flask_Executor==1.0.0
    Flask_SocketIO==5.3.1
    numpy==1.22.4
    pandas==1.3.5
    ProDy==2.3.1
    redis==3.5.3
    toml==0.10.2
    ulid==1.1
    ulid_py==1.1.0
    Werkzeug==2.2.0
    yagmail==0.15.293
  • Dockerfile信息如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    FROM python:3.9-slim

    WORKDIR /frontend
    COPY requirements.txt requirements.txt

    #RUN python -m pip install --quiet --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
    RUN python -m pip install -r requirements.txt

    ADD . .

    CMD ["python", "fapp.py"]
    在以上两个文件的基础下build镜像
    1
    docker build -t frontend:v1 .
    成功,,,报错。网上扒了好多信息大部分说是pip版本较低需要升级等等,测试了好多次,依然报错。不过build的时候发现一直卡在ProDy这个模块,于是想着就单独安装这一个模块试试。在各种尝试下发现是ProDy模块的版本问题,真的是巨坑。

成功编译

  • requirements.txt信息如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    colorama==0.4.4
    Flask==2.1.3
    Flask_Cors==3.0.10
    Flask_Executor==1.0.0
    Flask_SocketIO==5.3.1
    numpy==1.22.4
    pandas==1.3.5
    ProDy==2.4.0 # 升级到最新版本
    redis==3.5.3
    toml==0.10.2
    ulid==1.1
    ulid_py==1.1.0
    Werkzeug==2.2.0
    yagmail==0.15.293
  • Dockerfile信息如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    FROM python:3.9-slim

    WORKDIR /frontend
    COPY requirements.txt requirements.txt

    RUN apt update && \
    apt install -y gcc g++

    #RUN python -m pip install --quiet --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
    RUN python -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn

    #ADD . .
    COPY . .

    #CMD ["python", "fapp.py"]
    ENTRYPOINT ["python", "fapp.py"] # ENTRYPOINT 指定了容器启动时要运行的命令,而 CMD 则是指定运行这个命令时的默认参数。默认参数可通过docker run命令后的参数来覆盖它
    在以上两个文件的基础下build镜像,测试中发现安装prody需要gcc和g++
    1
    docker build -t frontend:v1 .

运行容器

  • 获取镜像的详细信息
    1
    docker inspect 镜像ID号
  • 交互式运行
    1
    docker run -it -p 5001:5001 frontend:v1
  • 交互式进入镜像
    1
    docker run -it -p 5001:5001 frontend:v1 bash
  • 分离模式下运行 docker 容器
    1
    docker run -d -p 5001:5001 --name saas frontend:v1
  • 查看运行容器的ip
    1
    docker inspect a7a17666fdd9 | grep -i ipaddress      # inspect后为容器id或容器name
  • 进入已经运行的容器
    1
    docker exec -it a7a17666fdd9 bash        # 参数 -it 后为容器id, 另外使用attach也可进入,不过exit的时候容器会停止,而exec不会
  • 挂载数据卷,若添加多个数据卷,继续添加 -v 参数即可
    1
    docker run -it -p 5001:5001 --net=host --name saas -v /share/saas/frontend:/frontend frontend:v1

容器连接宿主机redis

Docker启动容器的网络模式如下

  • Host : 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
  • Container : 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围
  • None : 该模式关闭了容器的网络功能
  • Bridge : 默认为该模式,此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信
    使用host模式启动容器,以方便连接宿主机redis服务
    1
    docker run -d -p 5001:5001 --net=host --name saas frontend:v1

docker常用命令

  • 列出所有容器ID,包括停止的
    1
    docker ps -aq
  • 停止所有的container
    1
    docker stop $(docker ps -aq)
  • 删除所有container
    1
    docker rm $(docker ps -aq)
  • 删除tag为none的镜像
    1
    docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
  • 将镜像保存为本地文件
    1
    docker save -o 存储文件名 镜像ID号
  • 恢复镜像
    1
    docker load -i 存储文件名

常用 Dockerfile 操作指令

  • ARG—— 定义创建镜像过程中使用的变量 ,唯一一个可以在 FROM 之前定义 。
  • FROM——基于某个镜像, FROM前面只能有一个或多个ARG指令 。
  • MAINTAINER(已弃用) —— 镜像维护者姓名或邮箱地址 。
  • VOLUME —— 指定容器挂载点到宿主机自动生成的目录或其他容器
  • RUN——执行镜像里的命令,跟在 liunx 执行命令一样,只需要在前面加上 RUN 关键词就行。
  • COPY——复制本地(宿主机)上的文件到镜像。
  • ADD——复制并解压(宿主机)上的压缩文件到镜像。
  • ENV——设置环境变量。
  • WORKDIR —— 为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录 。
  • USER —— 为 RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户。
  • EXPOSE —— 声明容器的服务端口(仅仅是声明) 。
  • CMD—— 容器启动后执行的命令 ,多个 CMD 只会执行最后一个,跟 ENTRYPOINT 的区别是,CMD 可以作为 ENTRYPOINT 的参数,且会被 yaml 文件里的 command 覆盖。
  • ENTRYPOINT—— 容器启动后执行的命令 ,多个只会执行最后一个。
  • HEALTHCHECH —— 健康检查 。
  • ONBUILD——它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
  • LABEL——LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式 ,替换 MAINTAINER。

参考:
https://mp.weixin.qq.com/s/fDBvrQl3P5wT9nP-hpQfcA
https://zhuanlan.zhihu.com/p/430989391
https://www.cnblogs.com/orion-orion/p/16268011.html
http://www.xiaomaidong.com/?p=1148
https://mp.weixin.qq.com/s/jA3VZG068FlMGJbesj_MWA