Docker介绍

最近由于实验室项目多次需要用到docker,现在算是大致了解docker了,确实是一个相当好用的工具。这里打算把docker的应用场景、基本用法做一个总结。不过因为才接触没多久,必然会有理解错误的地方。

docker能解决什么

想象下面几个场景(其中几个就是我之前实际遇到的场景):

场景1

你们作为一个外包团队,给某公司(甲方)做了一个web应用。这个web应用包含相当多的依赖库,并且对各个库的版本十分敏感,一个不对,可能就会各种报错。现在你们已经把这个web应用开发完毕并且本地测试完毕,将要交付。

其中一个(naive的)选择就是把软件包拷给对方,然后告诉对方需要的依赖库和版本,让对方自己配置、部署。但是很可能对方没有相关的技术人员,不懂怎么配置依赖,从而出现各种问题。

那么此时就可以将软件包和软件包运行需要的所有依赖全部配置好,打包成一个docker image交给对方。那么只要保证部署的服务器上安装有docker,通过load imagerun image两步命令即可一键成功部署。通过这种方式交付的docker image中已经包含有各种依赖包,因此就不需要部署人员再配置环境了,并且由于打包好的docker image已经通过了本地的部署测试,那么将整体转移到新的服务器中也必然能部署成功。

场景2

你计划开发一个个人博客,并且部署在线上。但是部署的服务器有一定的使用期限,比如3年后需要收回。因此你希望在服务器到期后,将你的博客整体迁移到另一台服务器中。但是你又担心在迁移的过程中会发生数据丢失的情况。

那么这种情况下,就可以使用docker来部署服务。在迁移时,只需要将原先运行中(那个时刻)的docker容器导出,就可以迁移到新的服务器上,在原先运行的基础上继续运行,而不会丢失任何已经持久化了的数据。并且不需要重新再配置环境,整个过程相当便捷、友好。

场景3

你实验室的GPU服务器上安装的cuda版本为9.0,但是你要跑一个程序,它需要的cuda环境是cuda-10.0(9.0会冲突并报错)。

此时一种方法是:你可以联系服务器管理员,要求将服务器的cuda版本升级为10.0。但是这么做一是很麻烦,需要联系管理员重新配置环境;二是有潜在的风险,可能会影响到在服务器上运行的其他程序:它们原本兼容cuda9.0,运行得好好的,但由于你突然把cuda升级到了10.0,就不兼容报错了。

因此一种更好的做法就是使用docker,在docker里面配置好cuda10.0的环境,把需要跑的程序放到docker里面去跑。因为docker容器和外部的宿主机是完全隔离的,就不会影响到在服务器(宿主机)上运行的其他程序了。

docker是什么

我的直观理解:docker就相当于是运行在宿主机上的一个虚拟机。使用这个虚拟机能够将外部(宿主机)的环境隔离开来从而创建一个新的、专为应用定制的环境。同时docker还提供了许多方便的功能,能够十分方便地:a) 对docker容器做更改、提交成新的镜像;b) 将docker镜像打包成一个文件进行移植;c) 将docker镜像上传到云端(docker hub);d) 从云端应用其他人已经创建好了的docker镜像。

docker的基本概念和常用命令

容器(container)和镜像(image)

容器和镜像是docker中的两个基本概念。镜像是静态的,持久化了的,类似于我们装系统时候使用的windows10的镜像。而容器可以理解为是动态的,是启动后处于运行或终止状态的虚拟机。通过相同的一个镜像可以创建多个容器,正如一份相同的windows10镜像可以为多台计算机安装操作系统一样。你可以通过docker container ls(或docker ps)和docker image ls(或docker images)分别查看当前的容器和镜像列表。

标签(tag)

镜像的标签就相当于为镜像取的一个名字(别名)。如果你新创建了一个镜像,但是没有给它打标签,那么你只能用IMAGE ID(镜像的sha256码)来表示这个镜像。但一般我们创建的镜像都是有实际的需求、含义的(这个镜像用来做啥?),所以为了好记,可以为镜像加上标签。

标签的格式是:[REPOSITORY]:[TAG],例如某个版本的pytorch镜像的tag可能是:pytorch:1.0.1-cuda10.0-cudnn7-devel

Docker Hub

Docker Hub,链接为https://hub.docker.com/,是docker官方提供的一个存放镜像的云端。用户可以再里面搜索一些第三方公司官方发布的docker镜像(例如tensorflow、pytorch、python的各个版本的image),也可以把自己创建的镜像传到上面。

常用命令

  • docker image ls: 查看所有镜像
  • docker container ls: 查看所有容器
  • docker run --workdir /app --expose 5000 --publish 80:5000 [IMAGE ID] /bin/bash start.sh: 通过镜像启动容器,运行命令为/bin/bash start.sh,将其工作目录设置为/app,开放容器的5000端口,将5000端口映射到宿主机的80端口。
  • docker exec -it [CONTAINER ID] /bin/bash: 通过bash进入到某个docker容器中
  • docker tag [IMAGE ID] [REPOSITORY]:[TAG]: 为某一个容器打标记
  • docker save -o [OUTPUT FILE] [IMAGE ID]: 将镜像导出成文件
  • docker load -i [INPUT FILE]: 将文件加载为镜像
  • docker commit -m [MESSAGE] [CONTAINER ID] [REPOSITORY]:[TAG]: 将容器提交为新的镜像
  • docker login: 登陆docker hub
  • docker pull [REPOSITORY]:[TAG]: 从docker hub拉取镜像到本地
  • docker push [REPOSITORY]:[TAG]: 将本地的镜像推送到docker hub上

nvidia-docker

如果需要在docker容器中使用到GPU(CUDA、CUDNN)的一些命令时,需要把docker [COMMAND]替换成nvidia-docker [COMMAND]。它本质上是在原生docker上提供的一层封装,使得docker容器中能够适配GPU资源(这部分我还不太懂,没有深究)。

Author: yym6472
Link: https://yym6472.github.io/2019/04/04/Docker介绍/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.