下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。



容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。

主要优势为:

2、安装

官方网站提供了 Mac, Linux 和 Windows 版本的安装教程。我们只要跟着官方文档即可,这里不再赘述。


不过需要提一下 Kitematic 这个图形化工具(官方给出的定义是 Visual Docker Container Management on Mac & Windows),对于熟悉和了解 Docker 是很好的帮助,大家可以体验一下。


守护进程

运行 Docker 守护进程时,可以用 -H 来改变绑定接口的方式,比如 

sudo /usr/bin/docker -d -H tcp://0.0.0.0:2375

如果不想每次都输入这么长的命令,需要加入以下环境变量 

export DOCKER_HOST="tcp://0.0.0.0:2375"

图形用户界面

虽然我们可以用命令来控制 docker,但是如果能有一个 web 管理界面,操作什么的会方便很多,比较常见的有

3、基本概念

基本概念主要有三个:

另外 Docker 采用的是客户端/服务器架构,客户端只需要向 Docker 服务器或守护进程发出请求即可完成各类操作。那么问题来了,我们能用 Docker 来做什么呢?我们可以:

Docker 可以提供的隔离有:

4、常用命令

一个简单的例子

接下来我们用一个简单的例子来体验下 docker

5、容器介绍

容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。

启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器(对于初级应用来说后者更方便)。

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

可以利用 docker start 命令,直接将一个已经终止的容器启动运行。

6、运行容器

现在,我们来创建一个 ubuntu:14.04 的容器 

docker run ubuntu:14.04 /bin/echo 'Hello wdx!'

(结果如下图所示)

可以看到正确输出了我们的 “Hello wdx!”

接下来,我们用 docker run -t -i ubuntu:14.04 /bin/bash 可以启动一个 bash 终端用来交互。参数的意思是:

我们可以输入一些命令来测试

容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。我们用 ps 或 top 在伪终端中查看进程信息,可以看到只有我们运行的进程,没有其他花里胡哨的(上图后一条命令)

试一试如下命令

(细心的同学可能会发现这里的输出暗藏玄机)

操作完成后,输入 exit 便可以退出这个 ubuntu 容器。退出之后这个容器依然存在,我们可以用 docker ps -l来看看:

每个容器有一个 Container ID 和 Name,我们一般就是通过这俩来定位一个容器的。


7、镜像

我们可以使用 docker pull 命令从仓库中获取所需要的镜像。比如说 

sudo docker pull ubuntu:12.04

相当于 

sudo docker pull registry.hub.docker.com/ubuntu:12.04

即从注册服务器 registry.hub.docker.com中的 ubuntu 仓库来下载标记为12.04 的镜像。

如果想从其他仓库注册服务器下载,需要输入完成的地址,例如:

sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04

下载完成之后就可以使用该镜像了,比如下面的语句就会创建容器,其中运行 bash

sudo docker run -t -i ubuntu:12.04 /bin/bash

可以使用 dokcer images 来显示本地已有的镜像,如下

具体字段的意思一目了然,这里不再赘述。然后我们来运行官方例子 whalesay 镜像。


8、运行镜像

打开浏览器,进入 Docker Hub

搜索 whalesay 这个镜像,就可以看到结果,点进去可以看到详细内容(基于 Ubuntu)

然后我们来运行一下,使用命令 

docker run docker/whalesay cowsay boo

其中 cowsay 是要运行的命令,后面的 boo 是参数。

Docker 会先在本地查找有没有镜像,如果没有就从仓库中下载,具体的运行结果是:

也可以让鲸鱼说不同的话,比如:


9、制作镜像

如果想要制作自己的镜像,需要自己写 Dockerfile。具体步骤如下

  1. 创建一个文件夹 mkdir wdxtub; cd wdxtub,构造镜像所需的所有东西都会放在这个文件夹中

  2. 创建一个名为 Dockerfile 的文件 gedit Dockerfile

  3. 添加句话 FROM docker/whalesay:latest,表示我们的镜像以 whalesay 为基础

  4. 添加需要运行的命令,如 RUN apt-get -y update && apt-get install -y fortunesfortunes 这个程序会输出名言警句)

  5. 通过 CMD 指定镜像载入之后需要执行的命令,如 CMD /usr/games/fortune -a | cowsay

  6. 保存并关闭 Dockerfile

  7. 使用 sudo docker build -t wdx-whale . 来构造镜像,简单来说就是用 Dockerfile 中的内容按步骤构造

  8. 使用 docker images 应该就可以看到我们新创建的镜像

然后我们就可以运行一下看看 

docker run wdx-whale

还有更贱的(感觉可以玩一天)

如果想要把自己的镜像上传到网上,就需要注册一个 Docker Hub 帐号,然后点击 Create Repository,这里我创建了一个名为 wdxtub/demo 的公用仓库。

接下来我们需要打上 tag,目前 docker images 的情况是:

记住我们的 IMAGE ID 26ac9649d7da。用以下命令打 tag

docker tag 26ac9649d7da wdxtub/wdx-whale:latest

然后再 docker images 一次:

然后用这个命令登录 

docker login --username=yourhubusername --email=yourmail@company.com

对于我来说就是 

docker login --username=wdxtub --email=dacrocodilee@gmail.com

成功之后大概是这样:

然后就可以 push 上去了 docker push wdxtub/wdx-whale,像下面这样

为了测试 pull 自己的镜像,我们先把本地上的 whale 镜像删掉:

docker rmi -f wdxtub/wdx-whale; docker rmi -f wdx-whale

(如果有其他的用不着的也都删掉),后剩下(上课要用的镜像):

接着来运行一下 

docker run wdxtub/wdx-whale


10、管理镜像

我们可以把镜像导出到本地文件,使用 docker save 命令即可,比如针对我现在有的镜像 wdxtub/wdx-whale(id:26ac9649d7da),可以这样:

docker save -o wdx-local-whale.tar wdxtub/wdx-whale

如果要载入的话,使用下面的命令即可(会载入相关的元数据信息)

docker load --input wdx-local-whale.tar# 或者docker load < wdx-local-whale.tar

在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器.

sudo docker rmi $(docker images -q -f "dangling=true")

镜像的实现原理

Docker 镜像是怎么实现增量的修改和维护的?每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。

通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。Docker 在 AUFS 上构建的容器也是利用了类似的原理。


11、容器启动

举个例子,

后台运行

更多的时候,需要让 Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。

下面举两个例子来说明一下。

如果不使用 -d 参数运行容器 

docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" 

容器会把输出的结果(STDOUT)打印到宿主机上面

如果使用了 -d 参数运行容器 

docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

则显示是这样:

使用 docker logs containerid 可以查看输出,如:

使用 -d 参数启动后会返回一个的 id,也可以通过 docker ps 命令来查看容器信息。容器是否会长久运行,是和docker run指定的命令有关,和 -d 参数无关

在使用 -d 参数时,容器启动后会进入后台。某些时候需要进入容器进行操作,有很多种方法,包括使用 docker attach 命令或 nsenter 工具等。


12、终止与重新启动

使用 docker stop containerid 来终止容器。终止状态的容器可以用 docker ps -a 命令看到。

另外,docker restart containerid 命令会将一个运行态的容器终止,然后再重新启动它。


13、导入导出与删除

如果要导出本地某个容器,可以使用 docker export containerid 命令。

可以使用 docker import 从容器快照文件中再导入为镜像,例如

cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0# 也可以通过指定 URL 或者某个目录来导入,例如docker import http://example.com/exampleimage.tgz example/imagerepo

用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。

可以使用 docker rm 来删除一个处于终止状态的容器。如果要删除一个运行中的容器,可以添加 -f 参数。Docker 会发送 SIGKILL 信号给容器。

用 docker ps -a 命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用 docker rm $(docker ps -a -q) 可以全部清理掉。

注意:这个命令其实会试图删除所有的包括还在运行中的容器,不过就像上面提过的docker rm 默认并不会删除运行中的容器。


14、仓库

仓库(Repository)是集中存放镜像的地方。

一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址dl.dockerpool.com/ubuntu 来说,dl.dockerpool.com 是注册服务器地址,ubuntu是仓库名。

作者:小土刀,责任编辑:帝都羊

https://wdxtub.com/2017/05/01/docker-guide/


相关文章