最近的工作和学习需要我使用docker,浅浅的学了一下,记录在这:下载docker镜像,用docker打包我的项目和环境,让docker使用宿主机器的GPU环境,将数据挂载在docker容器内,保存一个新的镜像等。最后加一个我的docker重启小妙招。
我想说:docker下载你真是害人不浅!(虽然如果下好了确实也挺好用的!),好了还是言归正传:
什么是 Docker?
Docker 使用容器技术,将应用程序及其所有依赖项(如库、配置文件等)打包到一个轻量级、可移植的容器中。这些容器能够在各种环境中快速部署和运行,无需担心环境差异。
安装docker我这里不写了,因为我没安装过,我是用的机器本来就有docker。
拉取docker镜像
使用以下命令从 Docker Hub 或其他注册表中拉取镜像:
docker pull <镜像名称>:<标签>
这里因为网络的原因十分的坑,我是使用了一个docker的镜像源才拉成功几个镜像的,这里分享一下:https://docker.1ms.run,不过这东西似乎很容易过期,用的时候再找吧。添加镜像源需要你进入修改本地的/etc/docker/daemon.json
文件,在"registry-mirrors"
字段内添加镜像的地址,如:
{"registry-mirrors": ["https://docker.1ms.run"]}
然后重启docker:
systemctl daemon-reload
systemctl restart docker
再使用docker pull
的方法拉取镜像就好了(现实远没有这么简单。。。)拉取镜像成功后,可通过docker images
查看本地已有那些镜像,通过docker rmi <镜像ID或名称>
可删除镜像 。
镜像和容器的区别
上面说了镜像的拉取,删除,查看,下面说容器操作,首先说说镜像和容器的区别:
-
Docker 镜像是一个只读的模板,用于创建容器。它包含运行应用程序所需的所有内容,如操作系统环境(如 Linux 文件系统)、应用程序文件和依赖项。、配置文件和启动命令等
-
容器是基于镜像运行的实例。它是一个轻量级的、独立的运行环境,可以看作是镜像的动态副本。
还是很容易的懂的,跑个例子就都懂了,好,下面说容器常见指令:
通过docker ps
查看运行中的容器,通过docker stop <容器ID或名称>
停止容器。
- 下面是如何运行一个容器:
docker run --name test -idt docker.1ms.run/continuumio/miniconda3
这里的test
是我定义的容器名,docker.1ms.run/continuumio/miniconda3
是使用的镜像名,参数 -idt 是为了启动一个后台运行的交互式容器,同时保留终端分配支持,此参数还有选择,见个人偏好。这样启动容器后,可执行docker exec -it <容器ID/名字> /bin/bash
进入该容器。
- docker cp 用于在本地主机和容器之间复制文件或目录:
1) 从容器中复制文件到主机
假设容器名称是 my-container,容器内的路径是 /app/data.txt,复制到主机的 /home/user 目录:
docker cp my-container:/app/data.txt /home/user/
2) 从主机复制文件到容器
将主机上的文件 /home/user/config.json 复制到容器 my-container 的 /app/ 目录:
docker cp /home/user/config.json my-container:/app/
比如我这次是下面了一个conda环境的镜像,然后将本地的一个conda的虚拟环境上传到容器中,我使用了以下指令将我的环境copy过去,然后再进入容器里,conda env list
就可以看见llama_factory环境了,地址在/opt/conda/envs/llama_factory
,这里有一个注意点,就是pip
的设置,本地的/home/user/.conda/envs/llama_factory/bin/pip
里设置了pip
使用的地址是#!/home/user/.conda/envs/llama_factory/bin/python
,所以复制到容器还是这样,因此要在容器里打开对应的/opt/conda/envs/llama_factory/bin/pip
改一下pip
使用的地址为#!//opt/conda/envs/llama_factory/bin/python
。
docker cp /home/user/.conda/envs/llama_factory my-container:/opt/conda/envs
- 让 Docker 容器使用本地 GPU 环境
要让 Docker 容器使用本地 GPU 环境,需要本地安装 NVIDIA 提供的 NVIDIA Container Toolkit,当然你本地的机器必须有显卡。有一个网站可以提供安装的简便方法,亲测可用:NVIDIA Container 运行时库
我是centos系统,所以用yum安装,亲测飞快!
然后在启动容器时使用加上--gpus
参数即可,如下:
docker run --gpus all <镜像名称>
--gpus all
是指让容器使用宿主机的所有 GPU。如果需要指定 GPU,例如 GPU ID 为 0,可执行docker run --gpus '"device=0"' <镜像名称>
。
- 本地数据挂载在容器上
在 docker 中,挂载本地数据到容器可以通过 数据卷(Volumes) 或 绑定挂载(Bind Mounts) 实现。这样,主机上的目录或文件可以映射到容器中,达到共享数据的目的。我这里使用的是绑定挂载 (Bind Mounts),直接将主机上的文件或目录挂载到容器中的文件系统位置,使用起来灵活且简单。
docker run -v <主机路径>:<容器路径> <镜像>
如将主机的 /home/user/data 目录挂载到容器的 /app/data 目录:
docker run -v /home/user/data:/app/data my-image
我有一个将本地文件夹挂载在容器上,并使用本地GPU环境的启动容器指令:
docker run --gpus all -d --name container_name -v ./home/user/data:/app/data my-image tail -f /dev/null
这里的 tail -f /dev/null
是一个保持容器运行的“占位命令”,可防止容器在启动后立即退出。
- 创建镜像并保存成压缩包
docker commit
用于 创建镜像,它将一个容器的当前状态保存为一个新的镜像。可以理解为从正在运行的容器中“拍照”并生成新的镜像。
docker commit <容器ID> <新镜像名称>:<标签>
docker save
用于将 Docker 镜像导出为 一个 tar 文件,通常用于备份、分享或迁移镜像。生成的 tar 文件包含镜像的所有层信息,可以传输给其他机器并在其上加载。
docker save -o <tar文件名>.tar <镜像名称>:<标签>
- 最后,说一个docker重启小妙招
下面的指令顺序执行,缺一不可
systemctl stop firewalld.service
rm -rf /var/lib/docker/network
systemctl stop docker
systemctl stop docker.socket
systemctl start docker# if start not successsystemctl reset-failed docker.servicesystemctl start dockersystemctl start firewalld.service
iptables-restore < /etc/iptables/rules.v4
iptables -S
docker ps -a