Docker 相关概念

2018-07-26 17:34 更新

docker 是一套 Linux 的 LXC 管理工具.

LXC (Linux Containers) 的概念类似于虚拟机, 但是形式上有区别. 虚拟机更像是提供"机器环境", 而 LXC 则是提供"运行环境". 单看概念它们的区别有些微妙, 但是 LXC 的特点就是, 同样是提供一套完全隔离的操作系统环境, 它很快, 超级快.

在使用上, 概念上的区别就是, 用虚拟机, 可能更多是想, 做一个电脑, 让它跑起来, 然后再说让这台电脑干什么事.

而 docker 的使用, 则是做一个环境(一组进程, 还有虚拟的设备等), 用环境来运行一个命令. 环境-命令 是一体的(一个容器), 命令一旦执行完成, 那么一个容器实例的任务就结束了. 所以如果我们想让一个容器像一台电脑那样, 通常我们给它一个像 /usr/bin/sshd -D 这样的命令, 这个容器像一台电脑, 是因为这个命令一直"没有执行完成"的效果.

虚拟机的使用, 一个镜像就是一个安装好的系统. 而 docker 中, 镜像更像是一张安装光盘(刻盘后不能更改), 容器才是安装好的系统. 这种两层式结构相较于传统的"快照"机制, 要好用得多. (如何从真正的系统安装 ISO 镜像得到 docker 镜像, 我现在也不清楚怎么做)

更具体一些, 使用 docker , 就是在指定的环境中执行一条命令, 比如:

docker run ubuntu:14.04 /bin/bash

意思就是, 在 ubuntu:14.04 这个环境中, 执行 /bin/bash 这条命令. 当然, 这条命令显然是瞬间就执行完了的. 如果和这个命令立即有交互, 那么需要一些参数:

docker run -t -i ubuntu:14.04 /bin/bash

-t 是分配一个虚拟终端, -i 是获取当前的输入. 这样你可以立即使用一个终端来和这个环境交互了.

虽然终端是正常使用电脑最常用的交互方式, 不过真实使用 docker 的场景中, 会这样用的机会不会很多的. 通常是直接执行我们要做的事, 比如运行一个服务, 或者执行一系列的计算.

使用 nc 来作一个例子:

docker run -t ubuntu:14.04 nc -l 8000

加上 -t 是因为需要一个终端来显示输出, 否则 nc 的标准输出就没地方去了.

docker 安装之后, 会自动在系统中作一个网桥配置, run 出来的每个容器实例, 都会分配一个桥接的 IP 地址. 上面的命令执行之后, 已经有容器在运行了, 并且在其中, nc 正监听着 8000 端口. 我们要接上去试试, 首先需要找到这个容器实例的 IP 地址.

先看当前运行着的实例列表:

docker ps

你先看到下面的信息:

CONTAINER ID  IMAGE         COMMAND     CREATED        STATUS        PORTS  NAMES
e1d0c9193025  ubuntu:14.04  nc -l 8000  5 seconds ago  Up 4 seconds         silly_curie

记下 ID , 不需要全部, 前面几位就可以了, 然后查看指定容器实例的细节:

docker inspect e1d0

会输出一串 json 字符串, 里面会有这样一节:

"NetworkSettings": {
    "Bridge": "docker0",
    "Gateway": "172.17.42.1",
    "IPAddress": "172.17.0.82",
    "IPPrefixLen": 16,
    "PortMapping": null,
    "Ports": {}
},

可以看到, 容器的 IP 是 172.17.0.82 , 上面的网关 IP 172.17.42.1 就是你"实体机"的.

在实体机使用 telnet 连上去:

telnet 172.17.0.82 8000

现在能看到效果了.

^] 然后 quit 退出, nc 那边结束执行, 命令执行完, 之前的那个容器实例也就关闭了. 你使用 docker ps 看不到. 但是使用:

docker ps -a

就能看到所有的容器实例. 在这里列出的实例是真实存在的, 只是当前并没有运行起来而已. 你可以随时让其中的实例再运行起来:

docker start e1d0c9193025

这样你又可以 telnet , 只是没地方看输出.

回顾上面的过程, 提出两个概念, 镜像 和 容器 .

镜像 指上面的 ubuntu:14.04 这种, 嗯, 这种环境, 这种系统. 后面会讲如何做一个自己的 镜像 .

容器 是在具体的 镜像 上 run 具体的命令, 得到的一个"绑定状态". run 命令执行时的一些参数(比如和实体机的端口映射), 也是"状态"的一部分, run 过之后就不能更改了.

它们的关系, 有些像编程语言中的  和 实例 . run 时的命令就像是类实例化时的参数. 后面会提到, 你可以删除 容器 , 也可以删除 镜像 . 当你想删除 镜像 , 但是使用它的 容器 还存在时, 你会得到操作失败的提示.

 有继承关系, 得利于 AUFS 这些的层级文件系统, 镜像 的构建也是这种层层封装的结果.


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号