Docker
Last updated
Was this helpful?
Last updated
Was this helpful?
Docker 是一个开源的应用容器引擎,可以视为一个轻量级的虚拟机。它是做什么的呢?它可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的操作系统,比如 Linux/Windows/Mac 的机器上。说白了就是把一个特定的环境封装起来,如果我们要部署不同的模型,他们有的是需要python2有的需要python3,有的用tf1.x有的用tf2.x,那就需要好几套环境来进行部署,全都装在一个机器里太乱了。所以干脆搞一个集装箱式的东西,每一个集装箱里面装了一套环境(比如py2+tf1.x,或者py3+tf2.x),集装箱里面的环境与外界是独立的,然后把模型部署到这个集装箱里,整个机器的环境就不乱了。
那虚拟机也可以起到同样的作用,为什么不用虚拟机呢?因为相比之下Docker能灵活的分配资源。一个虚拟机占的资源(CPU、内存等)在他被创造出来时候就设定好的,哪怕这个虚拟机啥也不干,这些资源也不能被其他程序利用,这就造成了资源浪费。而Docker可以根据实际消耗来分配不同镜像所占的资源。
Docker的安装比较简单,因为我是Win10系统,所以讲讲Win10是怎么安装Docker的。
我们要下载的是Docker Desktop for Windows。Docker Desktop for Windows 支持 64 位版本的 Windows 10 Pro,且必须开启 Hyper-V(若版本为 v1903 及以上则无需开启 Hyper-V),或者 64 位版本的 Windows 10 Home v1903 及以上版本。我的系统是64位的Win10家庭版,版本号是1909。所以满足要求。
去官网下载Docker Desktop for Windows.exe。然后双击文件开始安装。安装完成后提示重启,根据指示重启即可。
重启之后又跳出一个框提醒我升级WSL2内核,点击其中的链接下载wsl_update_x64.msi,双击安装。再重启。Docker就自动运行起来了(默认是开机自启动的)。
启动之后任务栏就会出现一个鲸鱼图标。而且会有一个界面教你怎么简单使用。
安装完 Docker 后,不仅可以通过图形界面打开并运行 Docker,而且可以通过命令行来进行 Docker 相关的操作。
打开命令行,输入docker —version
查看版本。如果可以看到版本说明你的Docker已经安装好了。
参考https://yeasy.gitbook.io/docker_practice/install/centos
现在我们就可以使用Docker啦,来看一些常用命令吧~
docker重启``sudo service docker restart`
几个概念
镜像(Image):类似虚拟机镜像。
容器(Container):类似linux系统环境,运行和隔离应用。容器从镜像启动的时候,docker会在镜像的最上一层创建一个可写层,镜像本身是只读的,保持不变。
仓库(Repository):是集中存放镜像的地方。
Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。
查看本地镜像docker image ls
REPOSITORY表示镜像的仓库源,TAG是镜像的标签,IMAGE ID 是镜像ID,然后是创建时间和镜像大小。因为我之前拉取过几个镜像,所以这里会有。
查看镜像docker images
删除镜像docker rmi <your-image-id>
清理临时的、没有被使用的镜像文件docker image prune
拉取镜像的命令是docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
。
具体的选项可以通过 docker pull --help
命令看到
Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]
。默认地址是 Docker Hub(docker.io
)。
仓库名:这里的仓库名是两段式名称,即 <用户名>/<软件名>
。对于 Docker Hub,如果不给出用户名,则默认为 library
,也就是官方镜像。
标签常用于对应软件的各个版本。如果不给出标签,将以 latest
作为默认标签。
比如要拉取TensorFlow官方专用的最新的稳定版的Docker镜像,命令就是docker pull tensorflow/tensorflow:latest
。运行后就会拉取镜像到本地。
再比例拉取TensorFlow serving的GPU版本:docker pull tensorflow/serving:1.14.0-gpu
删除镜像的命令docker image rm [选项] <镜像1> [<镜像2> ...]
<镜像>
可以是镜像长 ID
、 镜像短 ID
(一般取前3个字符以上,只要足够区分于别的镜像就可以)、镜像名
(也就是 <仓库名>:<标签>
) 或者 镜像摘要
。
镜像摘要默认不显示,需要用docker image ls --digests
查询。
举例说明删除镜像的方法:
要删除镜像docker101tutorial,可以用docker image rm c90
,或者docker image rm docker101tutorial
。一般用镜像短ID比较多,因为方便O(∩_∩)O~
查找镜像的地方
官⽅镜像库docker_hub: https://hub.docker.com/
例如cuda相关镜像:https://hub.docker.com/r/nvidia/cuda/
镜像构建
使⽤Dockerfile构建镜像docker build -t [image_name:tag] [上下⽂路径]
例如:docker build -t antispam/server:test1 .
由运⾏中的容器构建镜像(不推荐)docker commit -m"message"-a"author" [CONTAINER ID] [给新的镜像命名]
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited
)的容器重新启动。
基于镜像新建一个容器并启动:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
举例:docker run -it --name {name} -v local_dir:container_dir image:tag
OPTIONS部分参数说明:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-e: 设置环境变量
--gpus:指定想要使⽤的gpu,例如--gpus '"device=1,2"'
-i: 以交互模式运行容器,通常与 -t 同时使用;
--mount: 表示将文件系统挂载附加到容器。例如--mount type=bind,source=/src/webapp,target=/opt/webapp
source: 指定要运行部署的模型地址, 也就是挂载的源,这个是在宿主机上的servable模型目录(pb格式模型而不是checkpoint模型)
target: 这个是要挂载的目标位置,也就是挂载到docker容器中的哪个位置,这是docker容器中的目录,模型默认挂在/models/目录下,如果改变路径会出现找不到model的错误
--name: 指定容器name,后续使用比用container_id更方便。例如--name=mydemo
-P: 随机端口映射,容器内部端口随机 映射到主机的端口,让外部可访问容器
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口,例如-p 8080:8080
--restart:容器退出时重新启动策略以应用。可以设置为--restart=always
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--rm:退出时自动删除容器,一般在临时调试时用
-v: 绑定挂载卷
容器是否会⻓久运⾏,和 docker run 或者Dockerfile中CMD指定要执⾏的命令有关,和 -d 参数⽆关。
如果想⻓久运⾏⼀个没有指定任何命令的镜像,可以使⽤如下命令:docker run -dit image:tag
-it 相当于设置了⼀个可以和容器内部交互的伪终端,便于调试和使用。
当利用 docker run
来创建容器时,Docker 在后台运行的标准操作包括:
检查本地是否存在指定的镜像,不存在就从 registry 下载
利用镜像创建并启动一个容器
分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
从地址池配置一个 ip 地址给容器
执行用户指定的应用程序
执行完毕后容器被终止
例如:运行一个临时容器,使用后自动终止docker run -it --rm image:tag /bin/bash
在容器内部时,可以使⽤ exit 命令或 Ctrl+d 退出。
例如新建一个tensorflow的jupyter notebook的容器:docker run -it -p 8888:8888 tensorflow/tensorflow:latest-jupyter
,就会开始拉取相关镜像并启动容器
运行起来后命令行里可以看到一个http://127.0.0.1:8888/开头的url,复制该url在浏览器中打开,进入tensorflow-tutorials文件夹即可看到下面的内容。
现在就可以尽情地玩啦~都不用自己安装配置TensorFlow的环境,非常方便有木有!而且 docker 的运行与你的主系统是隔离的,如果把它“玩坏了”,再重新拉取全新的镜像就好。
启动/停止容器docker container start/stop $container_id或$container_name
查看所有运行容器docker ps
或者docker container ls
(前者是老命令,建议用后者)
还可以用来查找:docker container ps | grep "tensorflow/serving"
查看全部容器docker ps -a
或者docker container ls -a
杀死指定容器docker container kill $container_id
删除指定容器docker container rm $container_id
查看运行容器的日志docker container logs -f $container_id
删除所有处于终⽌状态的容器docker container prune
查看运⾏的容器的cpu占⽤及内存占⽤docker container stats $container_id
使⽤exec命令进⼊⼀个运⾏中的容器docker exec -it $container_id bash
更新容器参数docker update --restart=always [容器名]
拷⻉外部数据到容器中docker cp /src_path container_id:/dst_path_in_container
拷⻉容器中的数据到外部docker cp container_id:/src_path_in_container /dst_path
示例: docker cp 4b3f8de49dff:/usr/local/tomcat/logs/catalina.out /opt
docker gpu工具安装:https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-centos-7-8
Nvidia Container Toolkit,该工具使Docker 的容器能与主机的Nvidia显卡进行interact.
比如nvidia-tensorflow安装命令在:https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow
注意cuda版本和tf版本:https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/rel_21-12.html#rel_21-12
注意宿主机的cuda版本要比docker的cuda版本高(最好高好几个,比如宿主机是cuda11.3,docker可以安装11.0)
宿主机(物理主机)的Nvidia GPU 驱动 必须大于 CUDA Toolkit要求的 Nvida GPU 驱动版本。
即使Docker的CUDA和主机无关,但是Docker和宿主机的驱动有关
nvidia-docker run --rm -it -e NVIDIA_VISIBLE_DEVICES=1,2 --shm-size=1g --ulimit memlock=-1 --mount type=bind,src=$PWD,dst=/gpt-neox gpt-neox
nvidia-docker run --user 0 --rm -it -e NVIDIA_VISIBLE_DEVICES=1,2 --shm-size=1g --ulimit memlock=-1 --mount type=bind,src=$PWD,dst=/gpt-neox gpt-neox
比如使用tf2 gpu:
-it
means run in interactive mode
--rm
will delete the container when finished
-v
is the mounting directory
local_dir
is the directory or file from your host system (absolute path) that you want to access from inside your container. container_dir
is the target directory when you are inside your container.
参考资料
容器-->镜像转化
进入容器docker exec -it <container id> or <name> bash
pip安装包,exit退出容器
基于安装的包创建一个新的镜像**docker commit <container id> <new docker name>
**
docker commit 的弊端:
如果是安装软件包、编译构建,那会有大量的无关内容被添加进来,如果不小心清理,将会导致镜像极为臃肿。
此外,使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的。虽然 docker diff 或许可以告诉得到一些线索,但是远远不到可以确保生成一致镜像的地步。这种黑箱镜像的后期维护工作是非常痛苦的。
而且,镜像所使用的分层存储,除当前层外,之前的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用 docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。
docker commit的优点:
操作简单,易上手
docker build的方式生成新镜像的前提条件是有一个旧的基础镜像,在此基础上通过docker build 命令执行dockerfile 文件从而生成一个新的镜像,不同于docker commit,是镜像--> 镜像的转化。
现在,假设需求是将之前的镜像hub.c.163.com/library/centos:7.3.1611 作为基础镜像,通过dockerfile 文件的编写,执行,生成一个新的镜像,镜像名称为centos-vim:v2.0,。
新建一个空文件夹,名称任意,只需要为空就好。假设名称为 make_vim 这个文件夹,进入这个文件夹,编写文件,文件名称为 centos-vimv2.0
centos-vim2.0 的内容如下:
另一个例子:
FROM
nvcr.io/nvidia/tensorflow:21.05-tf1-py3
例子
build命令`sudo docker build --ssh github=~/.ssh/id_ed25519 -t image_gen:v1.1 .
运行build 命令,生成新镜像centos-vim:v2.0
docker build -f ./centos-vimv2.0 -t centos-vim:v2.0 .
注意,是在 make_vim 这个文件夹下执行此命令,命令最后是有一个点的。
docker run -itd --name centos5 centos-vim:v2.0
传入参数:docker build --build-arg ARG1="" --build-arg ARG2="" -t xxx:xxx .
其中参数是在dockerfile里面定义的,比如ARG username=$ARG1
5,当然了,在dockerfile里,加入了清理yum安装痕迹命令,因此,镜像要比commit 方式小一些。仅仅做一个小示例,因此dockerfile的很多功能没有演示,比如:复制宿主机的文件和文件夹到镜像内部,cmd ,entrypoint ,add,copy,export,workdir等等并没有使用。docker build -t 后面接的是新镜像的tag,-f 后面接的是dockerfile文件的名称,如果dockerfile的名称是Dockerfile,那么,可以省略-f以及其以后的内容,也就是不指定,docker会自动优先使用名称叫Dockerfile的文件构建新镜像。
Dockerfile的优点:
能够自由灵活的与宿主机联系,比如,某些配置文件在宿主机验证并使用过后很好用,那么,可以将文件copy到镜像中,(这个动作是写在dockerfile里),add 远程主机的配置文件到镜像中,定义onbuild动作等等各种灵活的功能。docker commit不能做到这些事情,因为是在一个封闭的在运行中的容器中,无法做复制拷贝宿主机文件的事情。
dockerfile本身就是一个比较详细的构建文档,有这个文档就可以清楚的知道新构建的镜像经历了怎样的变化。没有黑箱操作的困扰了,后期的维护更为方便了。
后期可扩展性强,一个文件就可以在哪都可以运行镜像了。(前提有网,有安装docker环境)
Dockerfile的缺点:编写不容易,因为需要对脚本这些比较了解,有Linux基础的人才可以编写出好用的dockerfile,上手难度大。
docker commit 和docker build (实战使用以及区别)
docker镜像的版本(bullseye、buster、slim、alphine)
https://blog.csdn.net/m0_46090675/article/details/121846718
https://dzone.com/articles/clone-code-into-containers-how
id
查看当前用户(宿主机和容器都可以看,同一个uid表示同一个用户)
如果两个不一样,可能会导致容器内没有权限,需要在docker run后面加参数—user uid
,例如—user 1000
https://github.com/yeasy/docker_practice
Docker教程推荐
https://yeasy.gitbooks.io/docker_practice/content/introduction/
https://www.cnblogs.com/bethal/p/5942369.html
https://www.cnblogs.com/xiaobaiskill/p/12203575.html
Win下迁移到其它盘:https://www.cnblogs.com/xhznl/p/13184398.html
查看日志等:https://nkcoder.github.io/posts/docker/docker-container-status/
(注意文件夹路径,docker/docker了)