Docker,系统影分身之术

目录

  1. Docker安装
    1.1. Windows
    1.2. Ubuntu
  2. Docker容器的使用
    2.1. 启动一个新的容器
    2.2. 挂起运行的程序
    2.3. 重启被挂起的程序
    2.4. 终止容器运行
    2.5. 重新运行已有容器
  3. Docker资源的管理
    3.1. 管理镜像资源
    3.2. 管理容器资源
    3.3. 管理网络资源
    3.4. 创建自己的镜像
  4. References

正文

在我电脑上没问题啊!

It works on my machine

如果你看懂了上面这句话,说明我们是同道中人。写程序有四种痛:

  1. 起早摸黑写好了代码,在自己的电脑上运行的好好,但是到了另一台电脑上各种问题层出不穷,软件越复杂依赖越多,头就越大;
  2. 想干一件大事,辛历尽千辛万苦配置好了环境,换了电脑又要从头再来。或者某天无意对电脑做了小小的改动,环境崩了;
  3. 想研究个新技术或者学个新技能,仅仅是搭建环境已经竭尽全力,你还不能确定有没有遗漏;
  4. 头发越来越少。

幸运的是,除了第四点,前三点已经有了解决方案,它就是Docker —— 容器化技术。它可以通过容器来构建、运行和分发应用程序。借用Java的口号就是:一次配置,到处运行。

或许你会问,既然已经有了虚拟机,为什么还要搞出个容器?容器化其实就是一种虚拟化技术,与传统虚拟机相比,它有着轻量、独立、可伸缩、可移植以及灵活等特点。容器直接运行于内核之上,多个容器共用系统的内核,直接通过内核获取系统资源,用多少取多少;而虚拟机则通过一个管理程序来获取宿主系统的资源,运行在其上的程序有着自己的内核,就算你跑的是个Hello World,它也占用这很大一块资源。拿吃饭打个比方,容器是按点的菜收钱:你点多少菜付多少钱;虚拟机是按人头收钱,只要你人在那,就算你只喝了一口水也照样收你这么多钱。它的区别如图1所示。

Fig 1 Container vs VM

当然,我不止一次说过,工具是不分优劣的。某种特定场合下,某个工具更合适,仅此而已。“杀鸡焉用牛刀”,说的也不是那种刀比另一种刀更好。这篇文章的主要目的是介绍Docker的用法。

0. Docker简介

Docker引擎由客户端(Client)、守护进程(Daemon)和注册表(Register)三部分组成,如图2所示。用户通过客户端发送命令来管理Docker的资源,包括镜像、容器、网络等(镜像和容器的关系就类似于程序和进程的诶关系);守护进程接收客户端以及API发过来命令来操纵容器,从而实现镜像、容器、网络等资源的管理;而注册表就是一个仓库,放着各种各样的镜像。因此,使用Docker主要就是使用Docker客户端命令。

Fig 2 Docker's architecture

Docker客户端的命令,可以大致分为三部分,每个部分又可以接着细分:

  1. Docker安装;
  2. Docker容器的使用;
  3. Docker资源的管理;

1. Docker安装

安装原本说是没有什么好说的,但是由于在Windows 10上Docker和VirtualBox不能共存,因此还是简单介绍介绍下。

1.1. Windows

  1. 首先,在Windows下,首先要打开Hyper-V选项,打开方式为:【控制面板】=>【程序】=>【程序和功能】=>【启用或关闭Windows功能】,然后勾选Hyper-V及其子选项;

Fig 3 Windows configuration

  1. 接下来,就直接到官网下载安装Windows版本即可。

值得注意的是,Docker和VirtualBox不能共存,因此你只能二选一。安装了Docker后,回头你再想用VirtualBox可能会遇到VT-x is not available (VERR_VMX_NO_VMX)这个错误,解决方法如下:

  1. 以管理员身份打开命令提示符;
  2. 输入bcdedit回车,你看到的应该看到hypervisorlaunchtype的值是auto
  3. 输入bcdedit /set hypervisorlaunchtype off并回车;
  4. 重启电脑。

1.2. Ubuntu

在Ubuntu下安装Docker,依次输入以下命令即可:

# Commands for install docker on Ubuntu,if command fail, consult [https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
 
# x86_64 / amd64
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
 
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
 
# Test
sudo docker run hello-world

2. Docker容器的使用

Docker使用可分为以下三个部分:

  1. 启动新容器;
  2. 挂起一个容器;
  3. 重启被挂起的容器;
  4. 停止容器;
  5. 重新启动已有容器

这里只列举一些常用的,以及一般场景下够用的命令。

2.1. 启动一个新的容器

启动一个新容器的命令为docker run,常用命令大致如下:

docker run -it -v <host dir>:<container dir> -w/<container dir> --name <your container name> --rm <your docker image name>

-it表示启动一个交互式的容器,也就是你可以在命令行输入命令进行交互;
-v将本地目录和容器中的一个目录做映射,这样在容器中就能直接访问该目录下的内容;
-w指定容器启动后的工作目录;
--name用于个这个容器分配一个名字,方便表明该容器的目的以及后续管理;
--rm表示当容器退出后自动删除。
例如:

docker run -it -v `pwd`/docker:/workspace -w/workspace --name ubuntu:16.04 ubuntu:16.04

上面命令中通过ubuntu:16.04这个镜像创建了一个名叫ubuntu:16.04的容器可交互的。使用docker run的时候,如果本地没有指定的镜像,Docker会尝试从远程注册表(仓库)中寻找,找到后拉取(pull)到本地再创建。

2.2. 挂起运行的程序

docker pause CONTAINER [CONTAINER...]

2.3. 重启被挂起的程序

docker unpause CONTAINER [CONTAINER...]

2.4. 终止容器运行

如果是交互式的容器,直接输入exit便退出了容器。如果是非交互式的容器,通过以下命令:

docker stop <container id or name>

有时候容器运行了很久,我都不记得容器名字和ID了,怎么办?可以通过以下命令获取所有容器信息:

docker container ls -a

2.5. 重新运行已有容器

# -i , optional, starting interactive
docker start -i <container id or name>

3. Docker资源的管理

Docker的镜像和容器的关系,就类似于程序和进程的关系。镜像是一个只读文件,它里面包含了如何创建一个容器的指令和模板;而容器就是一个镜像的实例。镜像和容器都是Docker引擎管理的重要资源,此外,还有网络资源、集群资源、插件和磁盘资源等。这里只介绍简单使用场景下常用的一些管理命令:

  1. 管理镜像资源;
  2. 管理容器资源;
  3. 管理网络资源;
  4. 创建自己的镜像。

其实管理Docker资源的命令和我们一般使用的Linux命令很类似,基本命令构成为docker <resources type> <linux/git command><resources type>可以是imagecontainernetwork等,而<linux/git command>则可以是lsrmcommit等。例如:

# list local images
docker image ls -a
# remove local images
docker image rm <image id/name>
docker container ls -a 
docker container rm <container id>

实际使用过程中,也可以类似Linux中man COMMAD去查看某个命令用法一样,可以使用直接使用`docker 查看具体命令的用法,例如:

$ docker network

Usage:  docker network COMMAND

Manage Docker networks

Options:
      --help   Print usage

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

3.1. 管理镜像资源

  1. 远程镜像搜索;
  2. 拉取镜像到本地;
  3. 本地镜像查看;
  4. 本地镜像移除。

我们使用Docker的时候,首先,可以向看看本地有没有我们想要的镜像:

docker images # or docker image ls -a

如果本地没有,可以使用以下命令搜索注册表上有没有我们想要的:

docker search [OPTIONS] TERM
# 例如:docker search ubuntu

搜索出来所有可用的镜像后选择自己想要的,拉取到本地:

docer pull <image name>
# 例如:docker pull ubuntu:16.04

其实,当我们直接使用docker run的时候,docker run就是首先执行上面三步。

当有些镜像我们不再需要了,我们可以删除

docker image rm <image id/name>

3.2. 管理容器资源

与镜像资源类似,对容器的管理也是类似的:

  1. 查看已有容器;
  2. 删除已有容器;
  3. 查看某个容器详细信息;
  4. 容器的创建、暂停、重新运行等。

查看容器:

docker container ls -a

通过列出的容器,可以获取到容器的ID或者名字,进而可以删除容器:

docker container rm <container id/name>

或者,查看容器的详细信息:

docker container inspect <container id/name>

而对于容器的创建、重启等操作前面已经介绍过了。

3.3. 管理网络资源

网络资源,其实就是专门给容器使用虚拟网络设备。默认情况下会有个一个名字是brigde的路由器,所有容器如果未经指定都会链接到上面,组成一个局域网。对网络资源的管理可以使用以下命令:
查看已有的网络资源:

docker network ls

查看某个网络资源的详细信息:

docker network inspect <network id/name>

网络资源的创建和删除:

docker network create
docket network rm <network id/name>

网络的链接和断开:

docker network connect <network> <container>
docker network disconnect <network> <container>

3.4. 创建自己的镜像

Docker相比于虚拟机的优势,主要就是它能够很轻易的分享,或者说转移已经配置好的环境,并且体积相对于整个虚拟可以小很多。这个是怎么实现的呢?主要有两种方法:

  1. 将已有容器打包成镜像,然后推到远程仓库;
  2. 在已有的镜像基础上,通过Dockerfile中的命令创建一个新的镜像。

从已有容器打包可以使用以下命令:

docker container commit --author <author name> -m <new image description> <container id/name> <image name>

例如,我运行了一个Ubuntu16.04的容器,并为它配置了adb(Android Debug Bridge)环境。为了能在别的机器上使用Ubuntu16.04的时候可以不用再配置adb,我将它打包成了一个新的镜像,命令和结果显示如下:

zhou@zhou:~$ docker container commit --author SunnyZhou -m 'Add adb' dbc7bdb56f2a ubuntu_with_adb:16.04
sha256:de247093e26e4e91eb4470d14067cdde094bddb46c063964ff254967282de113
zhou@zhou:~$ docker images
REPOSITORY                                     TAG                 IMAGE ID            CREATED             SIZE
ubuntu_with_adb                                16.04               de247093e26e        11 seconds ago      128MB
ubuntu                                         16.04               77be327e4b63        2 months ago        124MB

第二种方法是通过Dockerfile来创建新的容器,一个简单的例子是,还是创建一个带adb的Ubuntu16.04:
首先编写Dockerfile(完整的Dockerfile命令参看文末参考文档):

FROM ubuntu:16.04                                                           
COPY platform-tools/adb /sbin/adb

然后使用docker build来创建:

zhou@zhou:~/docker$ vi Dockerfile
zhou@zhou:~/docker$ docker build . --tag ubuntu-adb:16.04Sending build context to Docker daemon  26.95MB
Step 1/2 : FROM ubuntu:16.04
 ---> 77be327e4b63
Step 2/2 : COPY platform-tools/adb /sbin/adb
 ---> 1a5e2b476d20
Successfully built 1a5e2b476d20
Successfully tagged ubuntu-adb:16.04

这篇文章知识Docker的一篇概览,也是我日常使用Docker最多的命令。完整的命令请参看参考文档。

公众号二维码

首发于个人微信公众号TensorBoy。微信扫描上方二维码或者微信搜索TensorBoy并关注,及时获取更多最新文章!
C++ | Python | 推理引擎 | AI框架源码,有一起玩耍的么?

References

[1] https://docs.docker.com/engine/reference/commandline/docker/
[2] https://docs.docker.com/get-started/overview/
[3] https://docs.docker.com/docker-for-windows/install/
[4] https://docs.docker.com/engine/reference/builder/#usage
[5] https://github.com/docker/labs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章