docker run -it redis /bin/bash。执行这个命令运行一个redis容器,以交互模式运行容器,为容器重新分配一个伪输入终端,并执行/bin/bash。这个命令背后都做了什么?
- 1.如果本机没有redis镜像,则会从你配置的镜像仓库里面拉取一个redis的latest版本的镜像,跟运行了
docker pull redis
效果一样。 - 2.创建容器。跟运行
docker create
一样。 - 3.给容器分配一个读写文件系统作为该容器的
final layer(最底层)
,容器可以在它的文件系统创建和修改文件。 - 4.Docker为容器创建了一套网络接口,给容器分配一个ip。默认情况下,容器可以通过默认网络连通到外部网络。
- 5.Docker启动容器并执行
/bin/bash
。因为启动时指定了-it
参数,我们可以使用当前终端与docker客户端进行输入输出交互。 - 6.运行exit可以退出容器,但是此时容器并没有被删除,我们可以再次运行它或者删除它。
可以发现,容器的内核版本是跟宿主机一样的,不同的是容器的主机名是独立的,它默认用容器ID做主机名。我们运行ps -ef
可以发现容器进程是隔离的,容器里面看不到宿主机的进程,而且它自己有PID为1的进程。此外,网络也是隔离的,它有独立于宿主机的IP。文件系统也是隔离的,容器有自己的系统和软件目录,修改容器内的文件并不影响宿主机对应目录的文件。
root@stretch:/home/vagrant# uname -r 4.9.0-6-amd64
root@stretch:/home/vagrant# docker run -it --name demo alpine /bin/ash
/ # uname -r ## 容器内
4.9.0-6-amd64
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 /bin/ash
7 root 0:00 ps -ef
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
这些隔离机制并不是Docker新开发的技术,而是依托Linux 以及一些已有的技术实现的,主要包括:
- Linux Namespaces:Namespaces用于环境隔离,用于进程(PID)、网络(NET)、挂载点(MNT)、UTS、IPC等隔离。
- Linux Control Groups(CGroups):用于限制容器使用的资源,包括内存,CPU等。
- Union File Systems:UnionFS把多个目录结合成一个目录,对外使用,最上层目录为读写层(通常只有1个),下面可以有一个或多个只读层,见容器和镜像分层图。Docker支持OverlayFS,AUFS、DeviceMapper、btrfs等联合文件系统。