0%

Docker学习笔记

1. 介绍 Docker 和 Conda

Conda

Conda 是一个开源的包管理器和环境管理器,主要用于安装和管理来自于 Python 和 R 的软件包和环境。使用 Conda 的主要场景包括:

  • 科学计算:Conda 特别适合于科学计算和数据科学领域,因为它可以轻松管理具有复杂依赖关系的包。
  • 版本和环境管理:如果您需要在同一台机器上维护多个隔离的 Python/R 环境,Conda 是一个很好的选择。它可以帮助您避免不同项目间的依赖冲突。
  • 跨平台:Conda 支持多平台(Windows、macOS、Linux),适合于需要在不同操作系统上进行开发和测试的场景。

Docker

Docker 是一个开源的容器化平台,用于自动化应用程序的部署。它包装软件及其依赖项到一个标准化的单元中,用于软件开发。使用 Docker 的主要场景包括:

  • 应用程序的打包和部署:当您需要在不同的环境中一致地部署应用程序时,Docker 是一个理想的选择。它通过容器来确保应用程序在不同的系统和平台上表现一致。
  • 微服务架构:对于采用微服务架构的系统,Docker 提供了隔离、快速部署和伸缩性,非常适合于管理和部署微服务。
  • CI/CD 流程:Docker 可以很好地集成到持续集成和持续部署(CI/CD)的流程中,实现自动化测试和部署。

为什么用 Docker?

  • Docker提供了更高级别的隔离(操作系统级别),而 Conda 提供了较低级别(Python/R 环境级别)的隔离。
  • 适合部署深度学习环境:服务器CUDA版本不允许升级或降级时,使用Docker可以解决。只要宿主机的 NVIDIA 驱动与容器内部的 CUDA 版本兼容即可正常运行使用GPU的docker容器。
  • 思路:在Windows上搭建基础镜像,连进容器配置环境,通过docker commit保存镜像,再通过docker save导出,迁移到服务器上。
  • 应用部署需求:有些应用需要在Docker部署,比如coffee AI。
  • 镜像共享:网络问题,有了镜像就可以共享给其他人,不需要其他人再下载。

容器和镜像

  • 镜像(Image)容器(Container) 的关系,就像是面向对象程序设计中的类和实例一样。
  • 镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

Dockerfile

Docker 可以通过读取 Dockerfile 创建一个镜像,Dockerfile 是一个文本文档,其中包含用户可以在命令行上调用和组合镜像的所有命令。常见命令包括:

  • FROM:Dockerfile 必须从 From 开始,它为容器设置最基础的镜像。
  • WORKDIR:设置工作目录,为后面的 RUN 等指令设置工作目录。
  • RUN:运行指令。
  • COPY:把 Dockerfile 所在目录的一些文件拷贝到工作空间。
  • EXPOSE:声明容器运行时需要监听的端口号,使用 docker run 命令的 -p 参数来将容器端口映射到宿主机上。例如 -p 8080:80,表示将容器的 80 端口映射到宿主机的 8080 端口上。
  • HEALTHCHECK:告诉 Docker 如何测试容器以检查它是否仍在工作。
  • ENTRYPOINT:配置容器,里面包括了可以 run 的 py 文件,也包括了 run 指令,可以让容器创建时去运行某些指令。

写 Dockerfile 的注意事项

  1. FROM 的镜像可以选择更基础的镜像。
  2. pip 后面增加 --no-cache-dir,减少缓存。
  3. 在同一个 RUN 里不同的命令经常用 && 来连接,这是一种常见的做法,主要有以下几个原因:
    1. 减少图层:Dockerfile 中的每个 RUN 指令都会创建一个新的图层。通过使用 && 将多个命令连接在一起,可以减少生成的图层的数量,这样做的好处是创建更小、更简洁的镜像,并且可能提高构建速度。
    2. 确保所有命令都成功执行:当使用 && 时,如果一个命令失败(返回非零退出状态),整个 RUN 指令将失败并停止执行。这是一种保护措施,以确保不会在部分更新的或不一致的状态下构建镜像。
    3. 清洁和优化:通过在一个 RUN 指令中连接多个命令,您可以在完成必要的安装和配置后立即进行清理(例如,删除临时文件或清除缓存)。这有助于保持镜像的大小尽可能小。
  4. apt install 后面加上 rm -rf /var/lib/apt/lists/* 来清理安装后的无用文件。

2. 常用指令

查看docker所有命令

1
docker commond --help

镜像操作

查看所有镜像

1
docker images

下载镜像,Tag表示版本,有些镜像的版本显示latest,为最新版本

1
docker pull 镜像名:TAG

使用国内源来拉取镜像,将registry.docker-cn.com填写到镜像名前。

  1. Docker中国区官方镜像:https://registry.docker-cn.com
  2. 网易:http://hub-mirror.c.163.com
  3. ustc:https://docker.mirrors.ustc.edu.cn
  4. 中国科技大学:https://docker.mirrors.ustc.edu.cn
  5. 阿里云容器 生成自己的加速地址:登录:cr.console.aliyun.com

windows 可以直接在设置里填入加速的地址。

1
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}

删除镜像,删除指定本地镜像 -f 表示强制删除

1
docker rmi -f 镜像ID或者镜像名:TAG

获取镜像的元信息,获取镜像的详细信息,包括存放地址等等

1
docker inspect 镜像ID或者镜像名:TAG

从本地的压缩包里导入镜像

1
docker load < 压缩包所在路径

使用 Dockerfile 构建镜像

1
docker build -t test:v1.0 .

如果 Dockerfile 文件不在当前目录中,或者 Dockerfile 文件的名称不是 Dockerfile,则可以使用 -f 参数来指定 Dockerfile 文件的路径和名称。

容器操作

运行容器

1
2
3
4
5
6
7
docker run --name 容器名 -i -t -p 主机端口:容器端口 -d -v 主机目录:容器目录:ro 镜像ID或镜像名:TAG
# --name 指定容器名,可自定义,不指定自动命名
# -i 以交互模式运行容器
# -t 分配一个伪终端,即命令行,通常-it组合来使用
# -p 指定映射端口,讲主机端口映射到容器内的端口
# -d 后台运行容器
# -v 指定挂载主机目录到容器目录,默认为rw读写模式,ro表示只读

容器列表

1
2
3
4
5
docker ps -a -q
# docker ps查看正在运行的容器
# -a 查看所有容器(运行中、未运行)
# -q 只查看容器的ID
# -as 查看容器占用存储空间

启动容器

1
docker start 容器ID或容器名

停止容器

1
docker stop 容器ID或容器名

删除容器

1
2
3
4
docker rm -f 容器ID或容器名
# -f 表示强制删除

docker container prune # 删除所有没有运行的容器,谨慎操作

进入运行容器

1
2
3
4
5
docker exec -it 容器ID或者容器名 /bin/bash
# 进入正在运行的容器并且开启交互模式终端
# /bin/bash是固有写法,作用是因为docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动
bash。
# 也可以用docker exec在运行中的容器执行命令

查看容器使用的资源

docker stats 命令会每隔 1 秒钟刷新一次输出的内容直到按下 ctrl + c
输出的主要内容:

  • [CONTAINER]:以短格式显示容器的 ID。
  • [NAME]:容器名称
  • [CPU %]:CPU 的使用情况。
  • [MEM USAGE / LIMIT]:当前使用的内存和最大可以使用的内存。
  • [MEM %]:以百分比的形式显示内存使用情况。
  • [NET I/O]:网络 I/O 数据。
  • [BLOCK I/O]:磁盘 I/O 数据。
  • [PIDS]:PID 号。
1
2
docker stats
docker stats --no-stream # 只显示一次资源情况,不实时跟踪

3. CentOS8安装Docker

部署环境:

  • Linux:Linux 操作系统,以 CentOS Stream 8 为例。
  • Docker:容器管理,以Docker CE 24.0.7为例。

安装

卸载旧版本

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

卸载后将保留 /var/lib/docker 的内容(镜像、容器、存储卷和网络等),也删除。

1
rm -rf /var/lib/docker

更新 yum 源

1
yum makecache

设置 Docker 仓库

1
2
3
4
5
sudo yum install -y yum-utils

sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

安装 docker-ce

1
yum install docker-ce docker-ce-cli containerd.io

查看 Docker 版本

1
docker -v

启动 Docker

1
systemctl start docker

检查docker是否安装成功,打印出:Hello from Docker! 说明安装成功。

1
docker run hello-world

设置 Docker 开机自启动

1
systemctl enable docker

4. Ubuntu20.04安装Docker

自动安装

在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 --mirror 选项使用国内源进行安装:

1
2
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。

安装 NVIDIA Docker

但是上面的脚本没有安装 NVIDIA Docker 支持, 如果运行需要GPU的容器会报如下错误:

1
2
root@dell:~# docker run -it --rm --gpus all --net host -v /home/dell/lqm/aigc/Diffusion/Difftraj chengdu:/difftraj difftraj:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04
docker: Error response from daemon: could not select device driverwith capabilities: [gpu]

如果要在 Docker 容器中使用 NVIDIA GPU 需要安装 NVIDIA Docker 支持,即 nvidia-docker,我们还需要进行如下操作:

  1. 确保nvidia驱动和docker安装好,下面两行命令能够成功输出。
1
2
nvcc --version
docker
  1. 添加 NVIDIA Docker 仓库:
  • 对于 Ubuntu/Debian 系统,运行以下命令:
1
2
3
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
  • 对于 RHEL/CentOS 系统,运行以下命令:
1
2
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
  1. 安装 NVIDIA Docker:
  • 更新包管理器的索引并安装 NVIDIA Docker 包:
    • 对于 Ubuntu/Debian:
1
2
sudo apt-get update
sudo apt-get install -y nvidia-docker2
- 对于 RHEL/CentOS:
1
2
sudo yum clean expire-cache
sudo yum install -y nvidia-docker2
  1. 重新启动 Docker 服务:
  • 安装完成后,您需要重启 Docker 服务来应用更改:
1
sudo systemctl restart docker
  1. 验证安装
  • 运行一个测试容器以验证 NVIDIA Docker 是否安装正确:
1
docker run --rm --gpus all nvidia/cuda:11.0.3-base nvidia-smi
  • 这个命令会运行一个具有 CUDA 支持的容器,并在容器内执行 nvidia-smi。如果一切正常,将看到 GPU 的信息。

手动安装

首先卸载旧版本,确保卸载任何冲突的软件包(也就是旧版本的Docker组件)。Ubuntu在apt仓库中提供了Docker软件包的非官方分发版,该版本由Ubuntu负责维护和发行,必须先卸载这些软件包,然后才能安装Docker Engine的官方版本。

1
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

卸载了这四个包:

  • docker.io
  • docker-compose
  • docker-doc
  • podman-docker

添加 Docker 官方仓库的 GPG key

1
2
3
4
5
6
7
sudo install -m 0755 -d /etc/apt/keyrings

apt install curl

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

sudo chmod a+r /etc/apt/keyrings/docker.gpg

apt 安装 Docker Engine

1
2
3
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

配置 Docker 仓库

1
2
3
4
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

接着安装 NVIDIA Docker,见自动安装部分


5. Windows安装Docker Desktop

Win10

下载:https://docs.docker.com/desktop/install/windows-install/

参考:https://zhuanlan.zhihu.com/p/441965046

Win11-家庭版

安装问题

  • Docker desktop第一次启动一直在转圈,显示starting the Docker Engine

可能原因

  1. 没有Hyper-V内置虚拟机,需要手动安装

https://www.baiyunxitong.com/bangzhu/6775.html

  1. 还需要安装wsl(适用于linux的windows子系统)

https://zhuanlan.zhihu.com/p/667495068

以管理员的身份打开CMD或PowerShell运行以下命令

1
netsh winsock reset

更新 WSL

1
wsl --update

在控制面板-程序-启用或关闭windows功能勾选上以下三个内容

Docker Desktop 设置容器资源限制

有时候Docker容器里的大模型会出现爆内存等问题,可能是容器资源设置了限制。


6. 制作Docker镜像

6.1 根据已有镜像使用docker commit构建

这一方法的核心是docker commit

  • docker commit可以从容器创建一个新的镜像。
  • 通过对运行中的容器进行更改,然后使用 docker commit 命令,可以将容器的当前状态保存为新镜像。
  • 这种方法适用于快速的实验,但不推荐用于生产环境,因为:
    • docker commit不会明确记录构建过程,缺乏可重复性和透明性,会产生所谓的黑箱镜像。
    • 在容器中执行命令,会有很多文件被改动或添加。安装软件包、编译构建,那会有大量的无关内容被添加进来,将会导致镜像极为臃肿。
    • 简单的Python训练环境,可以用这个方法图方便,快速构建镜像。

思路:

  1. 先拉取已有的镜像。
  2. 使用镜像运行容器后,在容器内安装项目需要的Python依赖。
  3. 将整个容器通过docker commit指令制作成镜像。
  4. 导出镜像,在服务器上导入。

拉取已有镜像

官方Pytorch镜像:https://github.com/pytorch/pytorch#docker-image

也可以从docker hub里找到官方Pytorch镜像:https://hub.docker.com/r/pytorch/pytorch/tags

同样的pytorch和cuda版本会有两种镜像,分别是 develruntime 镜像,区别如下:

devel 镜像:

  • 用途:devel(开发)镜像包含了编译和运行 CUDA 应用所需的所有依赖,包括编译器和开发工具。
  • 适用场景:如果您需要编译使用 CUDA 的自定义操作或者需要编译整个 PyTorch 源代码,那么 devel 镜像是必需的。
  • 大小:由于包含更多的开发工具和库,devel 镜像通常比 runtime 镜像大很多。

runtime 镜像:

  • 用途:runtime(运行时)镜像仅包含运行基于 CUDA 的应用程序所必需的库和工具。
  • 适用场景:如果您只需要运行已经编译好的 CUDA 应用程序,而不需要进行额外的编译或开发工作,runtime 镜像就足够了。
  • 大小:相较于 devel 镜像,runtime 镜像更小,因为它不包含额外的编译工具和库。
-------------本文结束感谢您的阅读-------------