文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
1. 概述
- 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
- 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的 独立的命名空间。镜像使用的是分层存储,容器也是如此。
- 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会 随容器删除而丢失。
- 按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持 无状态化。
- 所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
- 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, 使用数据卷后,容器可以随意删除、重新 run,数据却不会丢失。
Namespaces
- 命名空间(namespaces)是 Linux 提供的用于分离进程树、网络接口、挂载点以及进程间通信等资源的方法。
- 在日常使用 Linux 时,并没有运行多个完全分离的服务器的需要,如果在服务器上启动了多个服务,这些服务其实会相互影响,每一个服务都能看到其他服务的进程,也可以访问宿主机器上的任意文件。
- Docker 通过 Linux 的 Namespaces 对不同的容器实现了隔离。
- Linux 的命名空间机制提供了以下七种不同的命名空间,包括 CLONE_NEWCGROUP、CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER 和 CLONE_NEWUTS,通过这七个选项能在创建新的进程时设置新进程应该在哪些资源上与宿主机器进行隔离。
进程
- 进程是 Linux 以及现在操作系统中非常重要的概念,它表示一个正在执行的程序,也是在现代分时系统中的一个任务单元。
- 在每一个 Unix 的操作系统上,都能够通过 ps 命令打印出当前操作系统中正在执行的进程。
[root@localhost sdcvm-engine-containers]# docker exec -ti `docker ps -a | grep sdcvm-postgres | awk '{ print $1 }'` /bin/bash
bash-4.2# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 May13 ? 00:00:00 /bin/bash /start-postgres.sh
root 8 1 0 May13 ? 00:00:42 /usr/bin/python2 /usr/bin/supervisord -n
root 15 0 1 10:42 ? 00:00:00 /bin/bash
root 22 15 0 10:42 ? 00:00:00 ps -ef
- Docker 容器成功的将容器内的进程与宿主机器中的进程进行了隔离,容器中的进程列表非常的干净。
- Docker 容器内部的任意进程都对宿主机器的进程一无所知。
2. 原理
- Docker 容器的文件系统可以说大部分由 Docker 镜像来提供。
镜像分层
- Dockerfile 中的每一条命令,都在 Docker 镜像中以一个独立镜像层的形式存在,在构建镜像时通过减少镜像层是一个不错的控制体积的办法。
- Docker 容器的文件系统中不仅包含 Docker 镜像,还包含顶上的两层,这两层不属于 Docker 镜像的结构,是 Docker 为 Docker 容器新建的内容。
- 这两层分别为 Docker 容器的初始层( Init Layer ) 与可读写层( Read-Write Layer ) 。
- 初始层中大多是初始化容器环境时,与容器相关的环境信息,如容器主机名、主机 host 信息以及域名服务文件等。
- 可读写层,是 Docker 容器内的进程拥有读写权限的文件层,其他层对进程而言都是只读的( Read-Only )。
- AUFS 文件系统下 ,可读写层用到了 写时复制( Copy-on-Write )的技术。
- 数据卷的文件也会挂载到可读写层 , 虽然 Docker 容器在可读写层可以看到数据卷的内容,但那仅仅是挂载点,真实内容位于宿主机上。
2.1 Chroot
- 在 Linux 系统中,系统默认的目录就都是以 / 也就是根目录开头的,chroot 的使用能够改变当前的系统根目录结构,通过改变当前系统的根目录,能够限制用户的权利,在新的根目录下并不能够访问旧系统根目录的结构跟文件,也就建立了一个与原系统完全隔离的目录结构。
默认目录结构
- 经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下。
2.2 CGroups
- 通过 Linux 的命名空间为新创建的进程隔离了文件系统、网络并与宿主机器之间的进程相互隔离,但是命名空间并不能够为我们提供物理资源上的隔离,比如 CPU 或者内存,如果在同一台机器上运行了多个对彼此以及宿主机器一无所知的『容器』,这些容器却共同占用了宿主机器的物理资源。
资源共享
- 如果其中的某一个容器正在执行 CPU 密集型的任务,那么就会影响其他容器中任务的性能与执行效率,导致多个容器相互影响并且抢占资源。
-
Control Groups(简称 CGroups)的作用就是能够隔离宿主机器上的物理资源,例如 CPU、内存、磁盘 I/O 和网络带宽。
- 每一个 CGroup 都是一组被相同的标准和参数限制的进程,不同的 CGroup 之间是有层级关系的,它们之间可以从父类继承一些用于限制资源使用的标准和参数。
继承关系
- 在 CGroup 中,所有的任务就是一个系统的一个进程,而 CGroup 就是一组按照某种标准划分的进程,在 CGroup 这种机制中,所有的资源控制都是以 CGroup 作为单位实现的,每一个进程都可以随时加入一个 CGroup 也可以随时退出一个 CGroup。
- Linux 使用文件系统来实现 CGroup,可以直接使用 lssubsys 命令查看当前的 CGroup 中有哪些子系统。
[root@localhost sdcvm-engine-containers]# lssubsys -m
cpuset /sys/fs/cgroup/cpuset
cpu,cpuacct /sys/fs/cgroup/cpu,cpuacct
memory /sys/fs/cgroup/memory
devices /sys/fs/cgroup/devices
freezer /sys/fs/cgroup/freezer
net_cls,net_prio /sys/fs/cgroup/net_cls,net_prio
blkio /sys/fs/cgroup/blkio
perf_event /sys/fs/cgroup/perf_event
hugetlb /sys/fs/cgroup/hugetlb
pids /sys/fs/cgroup/pids
- 之所以将上面的 cpuset、cpu 等称作子系统,是因为它们能够为对应的控制组分配资源并限制资源的使用。
- 每一个 CGroup 下面都有一个 tasks 文件,其中存储着属于分组的线程 TID 列表。
- cgroup.procs 文件,其中存储着属于分组的进程 PID 列表,仅包括多线程进程的线程 leader 的 TID,这点与 tasks 不同。
- 作为负责 cpu 的子系统,cpu.cfs_quota_us 文件中的内容能够对 CPU 的使用作出限制。
[root@localhost cpu]# cat tasks
1
2
3
5
7
8
9
10
11
12
......
- 如果在 Linux 上安装了 Docker,会发现所有子系统的目录下都有一个名为 docker.service 的文件夹。
[root@localhost docker.service]# pwd
/sys/fs/cgroup/cpu/system.slice/docker.service
[root@localhost docker.service]# ll
total 0
-rw-r--r--. 1 root root 0 May 9 13:40 cgroup.clone_children
--w--w--w-. 1 root root 0 May 9 13:40 cgroup.event_control
-rw-r--r--. 1 root root 0 May 9 13:40 cgroup.procs
-r--r--r--. 1 root root 0 May 9 13:40 cpuacct.stat
-rw-r--r--. 1 root root 0 May 9 13:40 cpuacct.usage
-r--r--r--. 1 root root 0 May 9 13:40 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 May 9 13:40 cpu.cfs_period_us
-rw-r--r--. 1 root root 0 May 9 13:40 cpu.cfs_quota_us
-rw-r--r--. 1 root root 0 May 9 13:40 cpu.rt_period_us
-rw-r--r--. 1 root root 0 May 9 13:40 cpu.rt_runtime_us
-rw-r--r--. 1 root root 0 May 9 13:40 cpu.shares
-r--r--r--. 1 root root 0 May 9 13:40 cpu.stat
-rw-r--r--. 1 root root 0 May 9 13:40 notify_on_release
-rw-r--r--. 1 root root 0 May 9 13:40 tasks
- 运行容器,就会增加一个 docker-<容器 ID>.scope 的文件夹。
- 93517129873be... 就是容器 ID。
[root@localhost docker-93517129873be37967bdb1446eb9c12223bb6bb708cfc22cc3c7644cbb0bf02f.scope]# pwd
/sys/fs/cgroup/cpu/system.slice/docker-93517129873be37967bdb1446eb9c12223bb6bb708cfc22cc3c7644cbb0bf02f.scope
[root@localhost docker-93517129873be37967bdb1446eb9c12223bb6bb708cfc22cc3c7644cbb0bf02f.scope]# ll
total 0
-rw-r--r--. 1 root root 0 May 14 19:24 cgroup.clone_children
--w--w--w-. 1 root root 0 May 14 19:24 cgroup.event_control
-rw-r--r--. 1 root root 0 May 14 19:24 cgroup.procs
-r--r--r--. 1 root root 0 May 14 19:24 cpuacct.stat
-rw-r--r--. 1 root root 0 May 14 19:24 cpuacct.usage
-r--r--r--. 1 root root 0 May 14 19:24 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 May 14 19:24 cpu.cfs_period_us
-rw-r--r--. 1 root root 0 May 14 19:24 cpu.cfs_quota_us
-rw-r--r--. 1 root root 0 May 14 19:24 cpu.rt_period_us
-rw-r--r--. 1 root root 0 May 14 19:24 cpu.rt_runtime_us
-rw-r--r--. 1 root root 0 May 14 19:24 cpu.shares
-r--r--r--. 1 root root 0 May 14 19:24 cpu.stat
-rw-r--r--. 1 root root 0 May 14 19:24 notify_on_release
-rw-r--r--. 1 root root 0 May 14 19:24 tasks
- Docker 会为容器创建一个与容器标识符相同的 CGroup。
CGroup 上下级关系
- 想要控制 Docker 某个容器的资源使用率就可以在该容器对应的 docker-<容器 ID>.scope 这个子控制组并且改变对应文件的内容,也可以直接在程序运行时就使用参数,让 Docker 进程去改变相应文件中的内容。
[root@localhost ]# docker run -it -d --cpu-quota=50000 busybox
- 当使用 Docker 关闭掉正在运行的容器时,Docker 的子控制组对应的文件夹也会被 Docker 进程移除,Docker 在使用 CGroup 时其实也只是做了一些创建文件夹改变文件内容的文件操作,不过 CGroup 的使用也确实解决了限制子容器资源占用的问题,系统管理员能够为多个容器合理的分配资源并且不会出现多个容器互相抢占资源的问题。
CGroup 特点
- 在 cgroups 中,任务就是系统的一个进程。
- 控制族群(control group)是一组按照某种标准划分的进程。Cgroups 中的资源控制都是以控制族群为单位实现。
- 一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。
- 一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制。
- 控制族群可以组织成层级(hierarchy)的形式,既一颗控制族群树。
- 控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性。
- 一个子系统(subsytem)就是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的一个控制器。
- 子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。
aufs
- UnionFS 是一种为 Linux 操作系统设计的用于把多个文件系统『联合』到同一个挂载点的文件系统服务。
- aufs 即 Advanced UnionFS 是 UnionFS 的升级版,能够提供更优秀的性能和效率。
- aufs 作为联合文件系统,它能够将不同文件夹中的层联合(Union)到了同一个文件夹中,这些文件夹在 aufs 中称作分支,整个『联合』的过程被称为联合挂载(Union Mount)。
- 每一个镜像层或者容器层都是 /var/lib/docker/ 目录下的一个子文件夹。
- 每一个镜像层都是建立在另一个镜像层之上的,同时所有的镜像层都是只读的,只有每个容器最顶层的容器层才可以被用户直接读写,所有的容器都建立在一些底层服务(Kernel)上,包括命名空间、控制组、rootfs 等等,这种容器的组装方式提供了非常大的灵活性,只读的镜像层通过共享也能够减少磁盘的占用。
- aufs 是 Docker 使用的存储驱动的一种,除了 aufs 之外,Docker 还支持了不同的存储驱动,包括 aufs、devicemapper、overlay2、zfs 和 vfs 等等,在最新的 Docker 中,overlay2 取代了 aufs 成为了推荐的存储驱动,但是在没有 overlay2 驱动的机器上仍然会使用 aufs 作为 Docker 的默认驱动。
overlay2
- Docker 默认的存储目录是 /var/lib/docker。
[root@localhost docker]# pwd
/var/lib/docker
[root@localhost docker]# ll
total 8
drwx------. 3 root root 78 May 14 19:24 containers
drwx------. 3 root root 22 May 7 18:26 image
drwxr-x---. 3 root root 19 May 7 18:26 network
drwx------. 20 root root 4096 May 14 19:24 overlay2
drwx------. 4 root root 32 May 7 18:26 plugins
drwx------. 2 root root 6 May 7 18:26 swarm
drwx------. 3 root root 37 May 13 13:45 tmp
drwx------. 2 root root 6 May 7 18:26 trust
drwx------. 27 root root 4096 May 13 13:45 volumes
- 是可以在 daemon.json 配置文件中修改存储驱动的。
{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
- 其中 image 目录中存放的是存储的元数据。
- 因为镜像(image)是由多个镜像层(layer)组合而成的,镜像层(layer)是一个共享的层,可能会有多个镜像(image)会指向某个镜像层(layer)。因此 image 目录下又分为了 imagedb 和 layerdb 目录。
[root@localhost docker]# tree -L 3 image/
image/
└── overlay2
├── distribution
├── imagedb
│ ├── content
│ └── metadata
├── layerdb
│ ├── mounts
│ ├── sha256
│ └── tmp
└── repositories.json
9 directories, 1 file
- image 目录下按每个存储驱动的名字创建一个目录,这里为 overlay2。
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sdcvm-postgres latest 9b4a60d30e64 47 hours ago 445 MB
sdcos sdcos7 9df994b93bcf 5 weeks ago 350 MB
- 通过 docker images 查看到 postgres 的镜像 ID 为 9b4a60d30e64,在 imagedb 目录下查找。
[root@localhost sha256]# pwd
/var/lib/docker/image/overlay2/imagedb/content/sha256
[root@localhost sha256]# ll | grep 9b4a60d30e64
-rw-------. 1 root root 6316 May 13 13:45 9b4a60d30e64b8c7c48e436c38cefe7dabb6bd92aea95e8453c2a2c6754cf4d5
- 文件中包含了镜像与镜像层的对应关系。
-
从上到下是从镜像层的底层到镜像层的顶层。522eaa81ad19c... 是最底层。
......
"rootfs":{"type":"layers","diff_ids":
[
"sha256:522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743",
"sha256:bba9c8b6f7bf7db18623881d535ed612033daecada485fbc1443f676ebe681d9",
"sha256:e5f61ba5d0872fea5d70e0edf94d5dd204017bc31dc00698425de060f394b963",
......
]}
......
[root@localhost 522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743]# pwd
/var/lib/docker/image/overlay2/layerdb/sha256/522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743
[root@localhost 522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743]# ll
total 740
-rw-r--r--. 1 root root 64 May 7 18:27 cache-id
-rw-r--r--. 1 root root 71 May 7 18:27 diff
-rw-r--r--. 1 root root 9 May 7 18:27 size
-rw-r--r--. 1 root root 741803 May 7 18:27 tar-split.json.gz
[root@localhost 522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743]# cat cache-id
7c217baf83ec2dd3b91d18813f638a90c38683ce9890d4195ce7557fbd2c1005[root@localhost 522eaa81ad19cff9d9d64c7511c6288dc9695306f3e4f496d0cbd3379f31b743]#
- 最终可以查找到对应的 rootfs。
- 最底层只有 diff 和 link 文件,高层还包含 lower、merged、work 等目录。
- link 文件内容是 l 目录里面的缩写链接名,实际就是对应 diff 目录。
- diff 目录是容器的可读可写层,初始为空。
[root@localhost overlay2]# pwd
/var/lib/docker/overlay2
[root@localhost overlay2]# ll | grep 7c217baf83ec2dd3b91d18813f638a90c38683ce9890d4195ce7557fbd2c1005
drwx------. 3 root root 30 May 7 18:27 7c217baf83ec2dd3b91d18813f638a90c38683ce9890d4195ce7557fbd2c1005
[root@localhost overlay2]# cd 7c217baf83ec2dd3b91d18813f638a90c38683ce9890d4195ce7557fbd2c1005/
[root@localhost 7c217baf83ec2dd3b91d18813f638a90c38683ce9890d4195ce7557fbd2c1005]# ll
total 4
drwxr-xr-x. 17 root root 224 May 7 18:27 diff
-rw-r--r--. 1 root root 26 May 7 18:27 link
[root@localhost 1067c0c749b276951102faf9b44b0cc6b3bc061d1560d739e95cc719368e9401]# ll
total 8
drwxr-xr-x. 3 root root 17 May 13 13:45 diff
-rw-r--r--. 1 root root 26 May 13 13:45 link
-rw-r--r--. 1 root root 115 May 13 13:45 lower
drwx------. 2 root root 6 May 13 13:45 merged
drwx------. 2 root root 6 May 13 13:45 work
merged、容器层(upperdir)、镜像层(lowerdir)之间的关系
merged、容器层(upperdir)、镜像层(lowerdir)之间的关系
- 如果 upperdir 和 lowerdir 有同名文件时会使用 upperdir 的文件。
- 读文件的时候,文件不在 upperdir 则从 lowerdir 读,
- 写文件的时候,不在 uppderdir 在 lowerdir,则从 lowerdir 里面拷贝到 upperdir,不管文件多大,拷贝完再写,删除或者重命名镜像层的文件都只是在容器层生成 whiteout 文件标志。
- overlay2 支持多个容器访问相同文件时公用 page cache,在拷贝和修改的时候 overlay2 比 aufs 更快,因为 aufs 的层级多搜索会有延迟,而 overlay2 会有缓存机制。
- 优化方面可以用 ssd,频繁的 I/O 操作,可以通过挂载 Volumes 来做,绕过存储驱动,可以多个容器共享数据,持久化数据。
3. 容器基础操作
- Linux 的 命名空间 和 控制组 分别解决了不同资源隔离的问题,前者解决了进程、网络以及文件系统的隔离,后者实现了 CPU、内存等资源的隔离。
操作 |
说明 |
attach |
依附到正在运行的容器。 |
cp |
本地文件系统与容器之间的文件或目录复制。 |
create |
创建一个新的容器。 |
diff |
检查容器差异。 |
events |
实时获得服务端事件。 |
exec |
在一个运行的容器里运行命令。 |
export |
导出容器的文件系统到一个归档文件。 |
kill |
杀掉一个运行中的容器。 |
logs |
获取容器的日志。 |
pause |
暂停容器内部所有进程。 |
port |
输出容器的端口信息。 |
ps |
显示容器列表。 |
rename |
重命令一个容器。 |
restart |
重启容器。 |
rm |
删除一个容器。 |
run |
运行一个容器。 |
start |
启动一个或多个非运行状态的容器。 |
stats |
实时显示容器的资源使用情况。 |
stop |
停止正在运行的容器。 |
top |
显示容器内正在运行的进程。 |
unpause |
恢复容器内部所有进程。 |
update |
更新一个或多个容器配置。 |
wait |
阻塞直到容器停止,然后打印退出码。 |
3.1 依附容器(docker attach)
- 命令格式:docker attach [OPTIONS] CONTAINER。
- 允许使用容器 ID 或名称附加到正在运行的容器,查看其正在进行的输出或以交互方式控制它。
- 可以同时连接上同一个容器来共享屏幕(与 screen 命令的 attach 类似)。
- 使用 Ctrl + C 或者 exit 命令退出容器,会使容器停止。可以使用 Ctrl + P,然后使用 Ctrl + Q 退出容器的虚拟终端。
- 官方不推荐 attach 开启了交互模式(使用 -t 参数的容器)的容器,docker attach 的主要功能为查看信息。
操作 |
说明 |
--detach-keys="" |
覆盖键序列分离容器。可以是一个单独的字符 [a-z],也可以是 Ctrl-<value>,<value> 可以是 [a-z]、@、^、[、, 或者 _。 |
--help |
打印帮助信息。 |
--no-stdin=true|false |
不附加输入操作。默认为 false。 |
--sig-proxy=true|false |
代理所有接受到的信号到进程中(仅限非 TTY 模式),SIGCHLD、SIGKILL 和 SIGSTOP 是非代理的,默认为 true。 |
3.2 复制(docker cp)
- 命令格式:
-
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-。
-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH。
- 本地文件系统与容器之间的文件或目录复制。
参数 |
说明 |
-L, --follow-link |
保持源目标中的链接。 |
-a, --archive |
存档模式(复制所有 uid/gid 信息)。 |
--help |
帮助信息。 |
[root@localhost ~]# docker cp sharp_ptolemy:/tmp/foo/myfile.txt /test //从容器到本地
[root@localhost ~]# docker cp /config/. myappcontainer:/etc/my-app.d //从本地到容器
3.3 创建容器(docker create)
docker create
- 命令格式:docker create [OPTIONS] IMAGE [COMMAND] [ARG...]。
- docker create 命令为指定的镜像(image)添加了一个可读写层,构成了一个新的容器,这个容器并没有运行。
- 创建的容器处于 Created 状态,可以用 docker start 启动。
添加一个可读写层
常用参数 |
说明 |
-i, --interactive=false |
打开 STDIN,用于控制台交互,通常与 -t 同时使用。 |
-t, --tty=false |
为容器重新分配一个伪输入终端,通常与 -i 同时使用,默认为 false。 |
-u, --user="" |
指定容器的用户。(用户名或者 UID) |
-a, --attach=[] |
登录容器(必须是以 docker run -d 启动的容器),可以选择 STDIN、STDOUT 或者 STDERR。 |
-w, --workdir="" |
指定容器的工作目录。 |
-c, --cpu-shares=0 |
设置容器 CPU 权重,在 CPU 共享场景中使用。 |
-e, --env=[] |
指定环境变量,容器中可以使用该环境变量。 |
-m, --memory="" |
指定容器的内存上限。 |
-P, --publish-all=false |
将所有公开端口发布到随机端口。 |
-p, --publish=[] |
指定容器暴露的端口,默认为 [],端口映射,格式为:主机(宿主)端口:容器端口 |
-h, --hostname="" |
指定容器的主机名。 |
-v, --volume=[] |
给容器挂载存储卷,挂载到容器的某个目录。 |
--volumes-from=[] |
给容器挂载其他容器上的卷,挂载到容器的某个目录。 |
--cap-add=[] |
添加权限。 |
--cap-drop=[] |
删除权限。 |
--cidfile="" |
运行容器后,在指定文件中写入容器 PID 值,一种典型的监控系统用法。 |
--cpuset="" |
设置容器可以使用的 CPU,此参数可以用来容器独占 CPU。 |
--device=[] |
添加主机设备给容器,相当于设备直通。 |
--dns=[] |
指定容器的 dns 服务器。 |
--dns-search=[] |
指定容器的 dns 搜索域名,写入到容器的 /etc/resolv.conf 文件。 |
--entrypoint="" |
覆盖 image 的入口点。 |
--env-file=[] |
指定环境变量文件,文件格式为每行一个环境变量。 |
--expose=[] |
指定容器暴露的端口,即修改镜像的暴露端口。 |
--link=[] |
指定容器间的关联,使用其他容器的 IP、env 等信息。 |
--lxc-conf=[] |
指定容器的配置文件,只有在指定 --exec-driver=lxc 时使用。 |
--name="" |
指定容器名字,后续可以通过名字进行容器管理,links 特性需要使用名字。 |
--net="bridge" |
容器网络设置(bridge:使用 docker daemon 指定的网桥、host:容器使用主机的网络、container:NAME_or_ID:使用其他容器的网络,共享 IP 和 PORT 等网络资源、none:容器使用自己的网络(类似 --net=bridge),但是不进行配置。) |
--privileged=false |
指定容器是否为特权容器,特权容器拥有所有的 capabilities。 |
--restart="no" |
指定容器停止后的重启策略,no:容器退出时不重启、on-failure:容器故障退出(返回值非零)时重启、always:容器退出时总是重启。 |
--rm=false |
指定容器停止后自动删除容器(不支持以 docker run -d 启动的容器)。 |
--sig-proxy=true |
设置由代理接受并处理信号,但是 SIGCHLD、SIGSTOP 和 SIGKILL 不能被代理。 |
--help |
帮助信息。 |
-l, --label list |
在容器上设置元数据(默认值为[])。 |
[root@localhost ~]# docker create --name myrunoob nginx:latest
09b93464c2f75b7b69f83d56a9cfc23ceb50a48a9db7652ee4c27e3e2cb1961f
3.4 容器变化(docker diff)
- 命令格式:docker diff CONTAINER。
- 检查容器文件系统上的更改,并支持快速的共享环境。
- A(Add)增加。
- D(Delete)删除。
- C(Change)修改。
- 可以使用完整或缩短的容器 ID 或使用 docker run --name 选项设置的容器名称。
[root@localhost ~]# docker diff 1fdfd1f54c1b
C /dev
C /dev/console
C /dev/core
C /dev/stdout
C /dev/fd
C /dev/ptmx
C /dev/stderr
C /dev/stdin
C /run
A /run/nginx.pid
C /var/lib/nginx/tmp
A /var/lib/nginx/tmp/client_body
A /var/lib/nginx/tmp/fastcgi
A /var/lib/nginx/tmp/proxy
A /var/lib/nginx/tmp/scgi
A /var/lib/nginx/tmp/uwsgi
C /var/log/nginx
A /var/log/nginx/access.log
A /var/log/nginx/error.log
- docker diff 的运行与容器状态无关,只显示文件差异。
3.5 容器事件(docker events)
- 命令格式:docker events [OPTIONS]
- 实时的输出 Docker 服务端事件、包括容器的创建、启动、关闭等。
参数 |
说明 |
-f, --filter filter |
根据条件过滤事件。 |
--format string |
使用给定的模板格式化输出。 |
--help |
帮助信息。 |
--since string |
从指定的时间戳后显示所有事件。 |
--until string |
流水时间显示到指定的时间为止。 |
filter
- 容器(container=<name or id>)
- 事件(event=<event action>)
- 镜像(image=<tag or id>)
- 插件(试验性的)(plugin=<name or id>)
- 标签 (label=<key> or label=<key>=<value>)
- 类型 (type=<container or image or volume or network or daemon>)
- 存储卷(volume=<name or id>)
- 网络(network=<name or id>)
- 守护进程(daemon=<name or id>)
[root@localhost ~]# docker events --since '2015-01-28'
2015-01-28T20:25:38.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) create
2015-01-28T20:25:38.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:39.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) create
2015-01-28T20:25:39.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:40.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
2015-01-28T20:25:42.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
2015-01-28T20:25:46.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
[root@localhost ~]# docker events --filter 'type=container' --format 'Type={{.Type}} Status={{.Status}} ID={{.ID}}'
Type=container Status=create ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
Type=container Status=attach ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
Type=container Status=start ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
Type=container Status=resize ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
Type=container Status=die ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
Type=container Status=destroy ID=2ee349dac409e97974ce8d01b70d250b85e0ba8189299c126a87812311951e26
3.6 进入容器(docker exec)
docker exec
- 命令格式:docker exec [OPTIONS] CONTAINER COMMAND [ARG...]。
- 在一个运行的容器中执行命令。
- 使用 docker exec 启动的命令仅在容器的主进程(pid 1)运行时运行,如果容器重新启动,则不会重新启动。
- 如果容器暂停,那么 docker exec 命令将等待容器取消暂停,然后再运行。
- 每个 docker exec 都会分配一个不同的 tty 给用户,所以不会冲突。
参数 |
说明 |
-d, --detach |
分离模式,在后台运行。默认 false。 |
--detach-keys string |
覆盖键序列分离容器。可以是一个单独的字符 [a-z],也可以是 Ctrl-<value>,<value> 可以是 [a-z]、@、^、[、, 或者 _。 |
-e, --env=[] |
指定环境变量,容器中可以使用该环境变量。 |
--help |
帮助信息。 |
-i, --interactive |
即使没有附加也保持 STDIN 打开。 |
--privileged |
授予命令扩展权限。默认 false。 |
-t, --tty |
分配一个伪终端。 |
-u, --user="" |
指定容器的用户。(用户名或者 UID) |
[root@localhost ~]# docker exec -i -t mynginx /bin/bash
root@b1a0703e41e7:/#
3.7 导出容器(docker export)
docker export
- 命令格式:docker export [OPTIONS] CONTAINER。
- 导出本地存储的容器为一个 tar 包档案文件。
- 使用完整或缩短的容器 ID 或容器名称导出容器文件系统的内容。输出被导出到 STDOUT,并可以重定向到 tar 文件。
参数 |
说明 |
-o, --output string |
将输出内容写到文件,而不是 STDOUT。 |
--help |
帮助信息。 |
[root@localhost ~]# docker export angry_bell > angry_bell.tar
[root@localhost ~]# docker export --output=angry_bell-latest.tar angry_bell
3.8 杀掉运行容器(docker kill)
docker kill
- 命令格式:docker kill [OPTIONS] CONTAINER [CONTAINER...]。
- 杀掉一个运行中的容器。
- 使用命令可以停止一个无响应的容器。
-
stop 与 kill 的区别在于 docker stop 命令给 容器中的进程 发送 SIGTERM 信号,默认行为会导致容器退出,容器内程序可以捕获该信号自行处理,当然也可以选择忽略。docker kill 命令是给 容器进程 发送 SIGTERM 信号,该信号将会使容器必然退出。
参数 |
说明 |
--help |
帮助信息。 |
-s, --signal="KILL" |
指定发送信号,默认为 KILL。 |
[root@localhost ~]# docker kill -s KILL mynginx
mynginx
[root@localhost ~]# docker kill --signal=SIGHUP my_container
[root@localhost ~]# docker kill --signal=HUP my_container
[root@localhost ~]# docker kill --signal=1 my_container
3.9 查看容器日志(docker logs)
- 命令格式:docker logs [OPTIONS] CONTAINER。
- 获取容器的日志。
- docker logs 命令批处理检索执行时容器存在的任何日志。不保证与 Docker 运行结合时的执行顺序(运行 docker logs 时可能没有生成任何日志)。
参数 |
说明 |
--help |
帮助信息。 |
--details=true|false |
显示详细日志信息。 |
-f, --follow=true|false |
跟踪日志输出(持续输出),默认 false。 |
--since="" |
显示某个开始时间的所有日志。 |
-t, --timestamps=true|false |
显示时间戳,默认 false。 |
--tail="all" |
仅列出最新 N 条容器日志,默认 all。 |
[root@localhost ~]# docker logs -f mynginx
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
2016/07/10 16:53:33 [error] 5#5: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.239.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.239.130", referrer: "http://192.168.239.130/"
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.239.130/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
192.168.239.1 - - [10/Jul/2016:16:53:59 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
...
3.10 暂停容器(docker pause)
docker pause
- 命令格式:docker pause [OPTIONS] CONTAINER [CONTAINER...]。
- 暂停容器中所有的进程。
- 通过 docker stats 查看资源使用情况不变。
- 通过 docker logs 查看日志无进一步输出。
- 该命令使用了 cgroup 中的 freezer 顺序暂停了容器里的所有进程。
[root@localhost ~]# docker pause db01
3.11 查看端口信息(docker port)
- 命令格式:docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]]。
- 列出指定的容器的端口映射,或者查找将 PRIVATE_PORT NAT 到面向公众的端口。
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b650456536c7 busybox:latest top 54 minutes ago Up 54 minutes 0.0.0.0:1234->9876/tcp, 0.0.0.0:4321->7890/tcp test
[root@localhost ~]# docker port test
7890/tcp -> 0.0.0.0:4321
9876/tcp -> 0.0.0.0:1234
[root@localhost ~]# docker port test 7890/tcp
0.0.0.0:4321
[root@localhost ~]# docker port test 7890
0.0.0.0:4321
3.12 查看本地容器信息(docker ps)
docker ps
- 命令格式:docker ps [OPTIONS]
- 列出容器(默认只列出了运行状态的容器)。
参数 |
说明 |
-a, --all=true|false |
列出所有容器。默认为 false,只列出了正在运行的容器。 |
-f, --filter=[] |
根据条件过滤事件。 |
--format="TEMPLATE" |
使用给定的模板格式化输出。 |
-l, --latest=true|false |
仅显示最新创建的容器(包括所有状态),默认为 false。 |
-n=-1 |
显示最近创建的 N 个容器(包括所有状态)。 |
--no-trunc=true|false |
不截断输出,默认为 false。 |
-q, --quiet=true|false |
静默输出,只显示容器编号。 |
-s, --size=true|false |
显示总的文件大小。 |
--help |
帮助信息。 |
filter
- 退出码(exited=<int> an exit code of <int>)
- 标签 (label=<key> or label=<key>=<value>)
- 状态(status=created|restarting|running|paused|exited|dead)
- 容器名称(name=<string> a container's name)
- 容器 ID(id=<ID> a container's ID)
- 任务容器(is-task=true|false)
- 过滤出指定容器之前的容器(<container-name>|<container-id>)
- 过滤出指定容器之后的容器(<container-name>|<container-id>)
- 过滤出指定镜像或后代创建的容器(<image-name>[:tag]|<image-id>| ⟨image@digest⟩)
- 存储卷(<volume-name>|<mount-point-destination>)
- 网络(<network-name>|<network-id>)
- 运行健康状况(starting|healthy|unhealthy|none)
format
- 使用模板打印容器信息,可以打印的信息包含有。
- ID(容器 ID)
- Image(镜像 ID)
- Command(引用命令)
- CreatedAt(容器的创建时间)
- RunningFor(容器启动后经过的时间)
- Ports(暴露的端口)
- Status(容器状态)
- Size(容器磁盘的大小)
- Names(容器的名称)
- Labels(分配给容器的所有标签)
- Label(容器标记,例如 {{.Label "com.docker.swarm.cpu"}})
- Mounts(容器挂载卷名称)
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c4bb11dfdb3 hello-world "/hello" 2 hours ago Exited (0) 2 hours ago eloquent_minsky
acbc7fa4cb8c hello-world "/hello" 12 days ago Exited (0) 12 days ago sleepy_mccarthy
f77dbc06cf99 hello-world "/hello" 12 days ago Exited (0) 12 days ago amazing_cori
d2a233491403 hello-world "/hello" 12 days ago Exited (0) 12 days ago sleepy_allen
2567131e0130 hello-world "/hello" 12 days ago Exited (0) 12 days ago competent_turing
[root@localhost ~]# docker ps -a -q
1c4bb11dfdb3
acbc7fa4cb8c
f77dbc06cf99
d2a233491403
2567131e0130
3.13 重命名容器(docker rename)
- 命令格式:docker rename CONTAINER NEW_NAME。
- 重命名容器,容器可以是运行的、暂停的、停止的状态。镜像重命名使用 docker tag。
[root@localhost ~]# docker rename my_container my_new_container
3.14 重启容器(docker restart)
- 命令格式:docker restart [OPTIONS] CONTAINER [CONTAINER...]。
- 是重启一个或多个容器,不是重启 docker 服务。
参数 |
说明 |
--help |
帮助信息。 |
-t, --time=10 |
kill 容器之前尝试停止的秒数(宽限期),一旦容器 kill,将重新启动,默认为 10 秒。 |
[root@localhost ~]# docker restart my_container
3.15 删除容器(docker rm)
docker rm
- 命令格式:docker rm [OPTIONS] CONTAINER [CONTAINER...]。
- 删除一个或多个容器,无 -f 参数,只能删除非运行状态容器。
参数 |
说明 |
--help |
帮助信息。 |
-f, --force=true|false |
强制删除一个正在运行的容器(使用 SIGKILL),默认为 false。 |
-l, --link=true|false |
删除容器间的关联,而不删除基础容器。默认为 false。 |
-v, --volumes=true|false |
删除与容器关联的卷(默认删除容器不会删除卷),默认为 false。 |
[root@localhost ~]# docker rm /redis
[root@localhost ~]# docker rm --link /webapp/redis
[root@localhost ~]# docker rm --force redis
[root@localhost ~]# docker rm $(docker ps -a -q)
[root@localhost ~]# docker rm -v redis
3.16 运行容器(docker run)
docker run
- 命令格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]。
- 运行一个新的容器,参数与 create 类似,包含了上述 docker create 中的参数。
- docker run 命令先是利用镜像创建了一个容器,然后运行这个容器。
- 后台运行需要增加 -d 参数,容器启动后返回唯一的容器 ID。
docker run 命令流程
常用参数 |
说明 |
-d, --detach=false |
后台运行容器,并返回容器 ID。 |
--read-only=true|false |
将容器的根文件系统安装为只读。 |
[root@localhost ~]# docker run --read-only --tmpfs /run --tmpfs /tmp -i -t fedora /bin/bash
退出状态
- Docker 运行的退出代码提供了有关容器为什么运行失败或为什么退出的信息。
- 当 Docker 用非零代码运行 exit 时,exit 代码遵循 chroot 标准。
退出码 |
说明 |
125 |
错误发生在 Docker 守护进程本身。 |
126 |
容器命令执行失败(例如没有权限)。 |
127 |
容器命令不能找到。 |
- 意外退出策略,可以通过 --restart 参数设置。
3.17 启动容器(docker start)
docker start
- 命令格式:docker start [OPTIONS] CONTAINER [CONTAINER...]。
- 启动一个或多个已经被停止的容器。
- docker start 命令为容器文件系统创建了一个进程隔离空间,并且每一个容器只能够有一个进程隔离空间。
参数 |
说明 |
--help |
帮助信息。 |
-a, --attach=true|false |
附加容器的 STDOUT、STDERR 和转发的所有信号到进程中。默认为 false。 |
--detach-keys="" |
覆盖键序列分离容器。可以是一个单独的字符 [a-z],也可以是 Ctrl-<value>,<value> 可以是 [a-z]、@、^、[、, 或者 _。 |
-i, --interactive=false |
即使没有附加也保持 STDIN 打开。默认为 false。 |
--checkpoint |
从此检查点还原。 |
--checkpoint-dir |
使用自定义检查点存储目录。 |
[root@localhost ~]# docker start my_container
- 添加 -a 参数显示 STDOUT、STDERR 信息,添加 -i 显示 STDIN 信息。
3.18 查看容器状态(docker stats)
- 命令格式:docker stats [OPTIONS] [CONTAINER...]。
- 显示一个或多个容器的资源使用统计信息的实时流。
参数 |
说明 |
--help |
帮助信息。 |
--all , -a |
显示所有容器状态信息(默认只显示运行状态)。 |
--no-stream=true|false |
禁用流式处理状态并只拉取第一个返回,默认为 false。 |
--format="TEMPLATE" |
使用给定的模板格式化输出。 |
--no-trunc |
显示完整的描述。 |
- 使用 --no-stream 可以只查看某一时刻的状态,输出结束后自动返回可交互的 shell 界面。
format
- 使用模板打印状态信息,可以打印的信息包含有。
- Container(容器 ID 和名称)
- Name(容器名称)
- ID(容器 ID)
- CPUPerc(CPU 百分率)
- MemUsage(内存使用)
- NetIO (网络 IO)
- BlockIO (块 IO)
- MemPerc(内存百分率(在 Windows 上不可用))
- PIDs(PID(在 Windows 上不可用))
[root@localhost ~]# docker stats
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
1285939c1fd3 0.07% 796 KiB / 64 MiB 1.21% 788 B / 648 B 3.568 MB / 512 KB
9c76f7834ae2 0.07% 2.746 MiB / 64 MiB 4.29% 1.266 KB / 648 B 12.4 MB / 0 B
d1ea048f04e4 0.03% 4.583 MiB / 64 MiB 6.30% 2.854 KB / 648 B 27.7 MB / 0 B
3.19 停止容器(docker stop)
docker stop
- 命令格式:docker stop [OPTIONS] CONTAINER [CONTAINER...]。
- 停止一个或多个运行中的容器。
- 先会向容器发送正常停止信号(先发送 SIGTERM 信号,宽限期后发送 SIGKILL 信号),而 docker kill 强制终止进程(直接发送 SIGKILL 信号)。
参数 |
说明 |
--help |
帮助信息。 |
-t, --time=10 |
在 kill 容器之前等待容器停止的秒数(宽限期)。默认值为 10 秒。 |
[root@localhost ~]# docker stop my_container
3.20 查看容器进程(docker top)
- 命令格式:docker top [OPTIONS] CONTAINER [ps OPTIONS]
- 查看容器中运行的进程信息,支持 ps 命令参数。
[root@localhost ~]# docker top 8601afda2b -x
PID TTY STAT TIME COMMAND
16623 ? Ss 0:00 sleep 99999
3.21 恢复容器(docker unpause)
- 命令格式:docker unpause [OPTIONS] CONTAINER [CONTAINER...]。
- 恢复容器中所有的进程。
- 该命令使用了 cgroup 中的 freezer 顺序恢复了容器里的所有进程。
[root@localhost ~]# docker unpause db01
3.22 更新容器(docker update)
- 命令格式:docker update [OPTIONS] CONTAINER [CONTAINER...]。
- 更新一个或多个容器的配置,大部分参数与 docker run 一致。
参数 |
说明 |
--help |
帮助信息。 |
--blkio-weight=0 |
块 IO 权重,范围 10~1000。 |
--cpu-shares=0 |
CPU 共享。 |
--cpu-period=0 |
限制 CPU CFS(完全公平调度程序)周期。限制容器的 CPU 使用。这个标志告诉内核将容器的 CPU 使用限制在指定的时间段内。 |
--cpu-quota=0 |
限制 CPU CFS 配额。 |
--cpu-rt-period=0 |
以微秒为单位限制 CPU 的实时周期,限制容器的实时CPU使用。这个标志告诉内核将容器的实时 CPU 使用限制在指定的时间段内。 |
--cpu-rt-runtime=0 |
以微秒为单位限制 CPU 实时运行时间,限制容器的实时 CPU 使用。此标志告诉内核限制给定 CPU 周期内实时任务可能消耗的时间量。跨容器的所有运行时的总和不能超过分配给父 cgroup 的额度。 |
--cpuset-cpus="" |
允许执行的 CPU(0-3、0、1)。 |
--cpuset-mems="" |
允许执行的内存节点(mems)(0-3、0、1)。仅对 NUMA 系统有效。 |
--kernel-memory="" |
内核内存限制(格式:<number>[<unit>],单位可以为 b,k,m 和 g)。 |
-m, --memory="" |
内存限制(格式:<number>[<unit>],单位可以为 b,k,m 和 g)。 |
--memory-reservation="" |
内存软限制(格式:<number>[<unit>],单位可以为 b,k,m 和 g)。 |
--memory-swap="" |
总内存限制(内存 + 交换)。 |
--restart="" |
容器退出时要应用的重新启动策略(no(不重启)、on-failure[:max-retry](失败时:最大重试数)、always(始终重启)、unless-stopped(除非停止))。 |
[root@localhost ~]# docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
[root@localhost ~]# docker update --kernel-memory 80M test
[root@localhost ~]# docker update --restart=on-failure:3 abebf7571666 hopeful_morse
-
--restart 添加该参数时不会立刻修改容器,而是在未来容器重启时生效。
--memory
- 内存应该小于已经设置的交换内存限制。如果要更新的内存限制大于已设置的交换内存限制,应该同时更新交换内存限制。
- 如果不设置交换内存 Docker 创建/运行的限制,只有内存限制,交换内存是双倍的内存限制。
3.23 设置等待(docker wait)
- 命令格式:docker wait [OPTIONS] CONTAINER [CONTAINER...]。
- 阻塞运行直到容器停止,然后打印出它的退出代码。
[root@localhost ~]# docker run -d fedora sleep 99
079b83f558a2bc52ecad6b2a5de13622d584e6bb1aea058c11b36511e85e7622
[root@localhost ~]# docker wait 079b83f558a2bc
0
网友评论