• dockerfile制作-pytoch+深度学习环境版


    你好你好!
    以下内容仅为当前认识,可能有不足之处,欢迎讨论!



    文档内容

    分为docker是什么,docker有哪些常用命令,docker制作过程,docker制作过程中出现的问题。

    资料路线推荐:①黑马程序员;②相关知乎介绍;③该文档。

    黑马程序员:大致看几节课,了解是什么东西。以及对应文字笔记

    ②相关知乎介绍:别人的安装过程。参考1结合参考2参考3选看。看几篇了解过程后再构建就行。

    其他相关链接:

    ③该文档:调整合适的python版本,基础镜像版本,requirements文件中的pip包。

    docker相关术语

    docker这项技术,包括专业术语(目前我遇到的用到的)有:镜像,容器,SSH,ubuntu,cudatoolkit,/devel,

    镜像可以看作类,容器看作实例 | 对象。这两个概念与python/java/c++中的类对象一致。

    SSH—这个没理解,百度的话自己看吧……

    Ubuntu系统——简单理解,运行起来快。

    cudatoolkit——能够跑深度学习的环境。

    devel——通过添加编译器工具链、调试工具、头文件和静态库来扩展运行时映像。

    runtime——通过添加cuda工具包中的所有共享库扩展基本映像。

    base——从cuda9.0开始,包含部署预构建cuda应用程序的最低限度。

    docker的英文翻译为码头工人。我理解为一种技术。这个工人包括运行深度学习模型的所有技能(环境),所以,现在如果自己是女娲,自己要根据不同的深度学习环境来造出不同的"人"——docker镜像

    docker常用命令

    • 查看镜像有多少docker images

    • 对镜像进行更名docker tag 原镜像:原tag 目标仓库/目标镜像:目标-tag

    • 通过dockerfile新建一个镜像:dockerbuild -t 仓库名/镜像名:tag名

    • 保存镜像:docker save -o 保存文件名称.后缀(一般用tar) 仓库名/镜像名:tag

    • 加载他人的镜像:docker load -i 导入的文件

    容器常用命令

    根据已有镜像创建对应容器:docker run --it --gpus all --name 容器名 仓库名/镜像名:tag名

    参数说明:

    --it,交互式地启动容器。

    --gpus,gpu数量为多少,我只用过all。

    --name,指定容器名称。

    根据dockerfile创建容器

    我的是Windows系统,安装了wsl虚拟子系统——Ubuntu18.04LTS。

    使用设置默认命令后,在wsl中输出即可进入Ubuntu子系统。由于我之前就进入了mnt文件夹,所以直接显示如此。另外,mnt文件夹是Windows系统的文件目录,所以要创建docker镜像,直接进入dockerfile文件夹中即可。

    image-20240401210442689

    注意,如果Windows系统可以在命令行中运行nvidia-smi,那子系统就不需要安装cudatoolkit,否则徒增空间。

    dokerfile文件内容

    内容包括cudatoolkit,Ubuntu系统,jupyter,ssh相关服务,requirements.txt包,senteval

    from nvidia/cuda:11.0.3-cudnn8-devel-ubuntu18.04
    
    # 安装ssh相关组件
    
    RUN apt-get clean && apt-get update && \
        apt-get install -y openssh-client openssh-server && \
        ssh-keygen -A && \
        cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new && \
        echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config.new && \
        mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config && \
        cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new && \
        echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.new && \
        mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config
    
    COPY start.sh /start.sh
    RUN chmod +x /start.sh
    CMD ["/start.sh"]
    
    # 升级apt-get
    RUN apt-get update && apt-get install -y --no-install-recommends apt-utils
    
    # 下载依赖并安装所有依赖
    RUN apt-get install -y build-essential libncurses5-dev libgdbm-dev libnss3-dev \
        libssl-dev libreadline-dev libffi-dev zlib1g-dev libsqlite3-dev
        
        
    # 下载并安装Python3.7
    WORKDIR /home/inspur/image_components/python
    
    RUN if [ -e /usr/bin/python ]; then rm /usr/bin/python; fi && \
        ln -s /usr/local/bin/python3.7 /usr/bin/python
    
    RUN apt-get update && \
        apt-get install -y wget build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev && \
        wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz && \
        tar -zxvf Python-3.7.12.tgz && \
        cd Python-3.7.12 && \
        ./configure --enable-optimizations && \
        make -j $(nproc) && \
        make altinstall && \
        ln -sf /usr/local/bin/python3.7 /usr/bin/python && \
        /usr/local/bin/python3.7 -m pip install --upgrade pip
    
    
    # 将SentEval文件夹复制到镜像中
    COPY SentEval /app/SentEval
    
    # 切换到SentEval目录并安装
    WORKDIR /app/SentEval
    RUN python setup.py install
    
    
    # 安装Jupyter
    RUN pip install jupyterlab==3.2.5
    
    # 配置Jupyter
    WORKDIR /home/inspur/image_components/jupyter_configure
    RUN wget https://raw.githubusercontent.com/Winowang/jupyter_gpu/master/jupyter_notebook_config.py && \
        wget https://raw.githubusercontent.com/Winowang/jupyter_gpu/master/custom.js && \
        mkdir /etc/jupyter && \
        cp -rf /home/inspur/image_components/jupyter_configure/* /etc/jupyter
        
    
    # 设置工作目录
    WORKDIR /app
    
    # 复制 requirements.txt 到容器内
    COPY requirements.txt .
    
    # 安装 Python 包
    RUN pip install --no-cache-dir -r requirements.txt
    
    
    # 可以在此执行更多的配置或安装步骤
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    解析下这个dockerfile做了什么。

    第1行,需要看清楚自己的cuda&torch版本,这个GitHub较为详细。可以参考。找好后,在docker官网找到对应tag下载Ubuntu+cudatoolkit基础环境。

    第3-17行,安装ssh及其服务。

    第19-42行,就是下载安装python。

    第45-50行,因为这个包没办法通过requirements.txt下载,只能离线下载,所以这是我额外的操作,如果没有这个要求可以忽略。

    第53-61行,安装jupyter,看服务器环境,我的平台上没有,所以需要安装jupyter及其服务。

    第65-71行,安装特定深度学习环境下的python包。也可以离线安装——把torch-wheel包放在dockerfile目录下,用离线安装命令就可以。

    dockerfile编写好后,直接进入wls的Linux窗口,有个mnt的文件夹,是本地电脑的目录。就能够通过build命令本地文件安装镜像了。

    执行docker build -t {images-name} . 就可以了,如下:

    image-20240330214244532

    docker问题:

    遇到问题:

    ①ssh配置问题

    原来的dockerfile文件内容是:

    # 安装ssh相关组件
    RUN apt-clean && apt-get update && \
        apt-get install -y openssh-client openssh-server && \
        ssh-keygen -A && \
        cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new && \
        echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config.new && \
        mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config && \
        cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new && \
        echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.new && \
        mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config && \
        /usr/sbin/sshd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    报错为:

    dockerfile:4
    --------------------
       3 |     # 安装ssh相关组件
       4 | >>> RUN apt-get clean && apt-get update && \
       5 | >>>     apt-get install -y openssh-client openssh-server && \
       6 | >>>     ssh-keygen -A && \
       7 | >>>     cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new && \
       8 | >>>     echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config.new && \
       9 | >>>     mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config && \
      10 | >>>     cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new && \
      11 | >>>     echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.new && \
      12 | >>>     mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config && \
      13 | >>>     /usr/sbin/sshd
      14 |
    --------------------
    ERROR: failed to solve: 
    process "/bin/sh -c apt-get clean && apt-get update &&     apt-get install -y openssh-client openssh-server &&     ssh-keygen -A &&     cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new &&     echo \"    StrictHostKeyChecking no\" >> /etc/ssh/ssh_config.new &&     mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config &&     cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new &&     echo \"PermitRootLogin yes\" >> /etc/ssh/sshd_config.new &&     mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config &&     /usr/sbin/sshd" 
    did not complete successfully: exit code: 255
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这个问题我是真看不懂,所以直接问GPT了……给出的问题以及解决方法如下:

    出现此错误表明在执行RUN指令时遇到了问题,导致整个命令未能成功完成。这个错误可能由多种原因引起,但考虑到错误消息中提及的内容,我们可以针对性地分析几个可能的原因和解决方法:

    可能的原因和解决方法

    1. SSH服务不能在Docker构建过程中启动: 在Dockerfile的构建过程中直接启动sshd服务(使用/usr/sbin/sshd命令)可能会失败,因为Docker构建过程不支持后台服务运行。构建过程主要用于设置环境和安装依赖,而不是运行服务。

      解决方法:不要在构建过程中启动sshd服务。相反,配置一个入口脚本,该脚本在容器启动时执行必要的初始化操作(如生成SSH密钥和启动sshd服务)。然后,使用CMDENTRYPOINT指令在Dockerfile的末尾调用这个脚本。

    2. 引用错误: 错误提示中显示的双引号被转义(\"),这可能是由于在Dockerfile或者某些编辑器中不正确地处理引号所导致的。

      解决方法:确保使用正确的引号,不需要在Dockerfile中额外转义双引号。

    3. 权限问题: 直接执行/usr/sbin/sshd可能由于权限不足而失败。

      解决方法:确保容器具有执行所需操作的权限。一种常见做法是使用USER指令切换到合适的用户,或者确保容器以足够权限运行相关命令。

    示例修改

    为了解决这个问题,您可以将启动SSH服务的部分移除出构建过程,改为在容器启动时执行。以下是修改后的一部分Dockerfile示例和一个入口脚本示例:

    修改后的Dockerfile示例:
    DockerfileCopy code...
    RUN apt-get clean && apt-get update && \
        apt-get install -y openssh-client openssh-server && \
        ssh-keygen -A && \
        cat /etc/ssh/ssh_config | grep -v StrictHostKeyChecking > /etc/ssh/ssh_config.new && \
        echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config.new && \
        mv -f /etc/ssh/ssh_config.new /etc/ssh/ssh_config && \
        cat /etc/ssh/sshd_config | grep -v PermitRootLogin > /etc/ssh/sshd_config.new && \
        echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.new && \
        mv -f /etc/ssh/sshd_config.new /etc/ssh/sshd_config
    
    COPY start.sh /start.sh
    RUN chmod +x /start.sh
    CMD ["/start.sh"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    start.sh脚本示例:
    bashCopy code#!/bin/bash
    
    # 启动SSH服务
    /usr/sbin/sshd -D
    
    • 1
    • 2
    • 3
    • 4

    确保start.sh脚本在Docker容器的文件系统中的适当位置,且具有执行权限(如示例中所示)。这样,当容器启动时,它将执行start.sh脚本,该脚本负责启动SSH服务。

    通过这种方式,您可以避免在构建过程中直接启动服务的问题,同时确保容器启动后服务正常运行。

    ②python安装包问题

    报错为:

    1517.0 Looking in links: /tmp/tmpfu9f5ef7
    1517.0 Processing /tmp/tmpfu9f5ef7/setuptools-47.1.0-py3-none-any.whl
    1517.0 Processing /tmp/tmpfu9f5ef7/pip-20.1.1-py2.py3-none-any.whl
    1517.1 Installing collected packages: setuptools, pip
    1517.9 Successfully installed pip-20.1.1 setuptools-47.1.0
    1517.9 rm: cannot remove '/usr/bin/python': No such file or directory
    ------
    dockerfile:30
    --------------------
      29 |     WORKDIR /home/inspur/image_components/python
      30 | >>> RUN apt-get update && \
      31 | >>>     apt-get install -y wget build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev && \
      32 | >>>     wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz && \
      33 | >>>     tar -zxvf Python-3.7.12.tgz && \
      34 | >>>     cd Python-3.7.12 && \
      35 | >>>     ./configure --enable-optimizations && \
      36 | >>>     make -j $(nproc) && \
      37 | >>>     make altinstall && \
      38 | >>>     rm /usr/bin/python && \
      39 | >>>     ln -s /usr/local/bin/python3.7 /usr/bin/python && \
      40 | >>>     ln -s /usr/local/bin/pip3 /usr/bin/pip && \
      41 | >>>     wget https://bootstrap.pypa.io/get-pip.py && \
      42 | >>>     python3.7 get-pip.py
      43 |
    --------------------
    ERROR: failed to solve: process "/bin/sh -c apt-get update &&     apt-get install -y wget build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev &&     wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz &&     tar -zxvf Python-3.7.12.tgz &&     cd Python-3.7.12 &&     ./configure --enable-optimizations &&     make -j $(nproc) &&     make altinstall &&     rm /usr/bin/python &&     ln -s /usr/local/bin/python3.7 /usr/bin/python &&     ln -s /usr/local/bin/pip3 /usr/bin/pip &&     wget https://bootstrap.pypa.io/get-pip.py &&     python3.7 get-pip.py" did not complete successfully: exit code: 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    可以看到在第6行,显示没有该文件或文件夹,对应到dockerfile中为第38行rm /usr/bin/python,询问GPT,给的原因分析为:

    错误提示显示,在尝试删除/usr/bin/python时遇到问题,因为没有找到这个文件。这个问题发生在您尝试安装Python 3.7、移除现有的Python链接并创建新链接到安装的Python 3.7版本的过程中。这个错误可能意味着在尝试删除/usr/bin/python之前,该文件并不存在。

    可能的原因和解决方法

    原因1:预安装的Python不存在

    在某些基于Ubuntu的镜像中,/usr/bin/python可能默认不存在,尤其是在一些更新的Ubuntu版本中(如18.04及以上),它们可能不包含Python 2,而是包含Python 3,且命名为python3

    解决方法:在尝试删除/usr/bin/python之前,先检查该文件是否存在。如果目的是确保python命令指向Python 3.7,可以改用更安全的方法来创建链接,只在文件存在时才删除它。例如:

    DockerfileCopy codeRUN if [ -e /usr/bin/python ]; then rm /usr/bin/python; fi && \
        ln -s /usr/local/bin/python3.7 /usr/bin/python
    
    • 1
    • 2

    或者,简化这个过程,直接创建一个新链接,如果旧的链接不存在,这个命令也不会出错:

    DockerfileCopy code
    RUN ln -sf /usr/local/bin/python3.7 /usr/bin/python
    
    • 1
    • 2
    原因2:安装Python 3.7后不需要手动更新pip

    安装Python 3.7时使用make altinstall避免覆盖默认的python命令,这是推荐的做法。但之后的步骤尝试手动更新pip可能是不必要的,因为altinstall安装的Python版本已包含了pip(假设是较新的Python版本)。

    解决方法:可以省略手动安装pip的步骤,因为每个Python安装通常都会包含pip。如果确实需要更新pip,可以考虑使用Python自带的pip来更新:

    DockerfileCopy code
    RUN /usr/local/bin/python3.7 -m pip install --upgrade pip
    
    • 1
    • 2

    修改后的Dockerfile示例

    结合以上建议,修改相关部分如下:

    DockerfileCopy codeRUN apt-get update && \
        apt-get install -y wget build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev && \
        wget https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz && \
        tar -zxvf Python-3.7.12.tgz && \
        cd Python-3.7.12 && \
        ./configure --enable-optimizations && \
        make -j $(nproc) && \
        make altinstall && \
        ln -sf /usr/local/bin/python3.7 /usr/bin/python && \
        /usr/local/bin/python3.7 -m pip install --upgrade pip
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这样修改后,应该能够解决构建过程中遇到的错误,并确保Python 3.7成功安装且python命令链接到正确的Python版本。

    可以看到,第9-10行替换为原来的38-41行。原先命令的意思是:

    修改后命令的意思是:

    nvidia-smi无法识别。导致torch无法使用。

    启动命令不正确,需要加上--gpus all的参数创建容器。启动容器后,就可以正常执行nvidia-smi的命令,打开python后,torch.cuda.is_available()的命令也能显示true。

    ④默认启动为Ubuntu

    使用wsl -d Ubuntu可以进入虚拟环境中。通过管理员权限在powershell中可以设置将wsl2的默认系统设置为Ubuntu:wslconfig /setdefault Ubuntu

    在开始学习时自己的问题

    Windows下的Ubuntu和docker是什么关系?因为在Ubuntu中没法使用docker命令。

    😵问题:如何下载指定版本的包?下载指定版本的包下载错了怎么办?目录是哪里的目录?入口需要写什么?

    可以通过深度学习环境先导出requirements.txt,再加入到dockerfile同一目录中,在dockerfile中pip安装。

    😵如何下载指定的包?

    ①在创建镜像时,就声明需要下载哪些包及其对应版本。本文档中的dockefile就是该操作。

    ②在原有镜像基础上,生成容器后,在容器中下载包,下载完成后将其打包成新的镜像。需要额外操作。

    😵下载指定版本的包错了怎么办?

    用本地文件导入试试。以及pypi.org找到指定包。

    😵目录是哪里的目录?

    Ubuntu可以直接在mnt目录下进入本地目录。

    😵入口需要写什么?

    这个没找到……答案

    相关资料


    以上是我的学习笔记,希望对你有所帮助!
    如有不当之处欢迎指出!谢谢!

    学吧,学无止境,太深了

  • 相关阅读:
    域名扫描工具subDomainBrute源码分析
    索引+sql练习优化
    卷积神经网络(原理与代码实现)
    MATLAB图像处理入门
    微信小程序父组件向子组件传参,子组件样式无效问题处理
    EasyPoi导出复杂Excel
    算法题Day71
    vue从地址栏输入路径后path和导航按钮不匹配问题
    电力系统IEEE14节点系统同步模型(Simulink)
    【C++】一次rustdesk-server编译记录
  • 原文地址:https://blog.csdn.net/weixin_44498989/article/details/137247170