本文中涉及的源码基于docker 1.0版本系统。 本文中涉及的测试环境基于ubuntu server 14.04及redhat6.5。
容器管理是docker的主要功能之一,包括以下管理功能:
ContainerExport
ContainerCreate
ContainerStop
ContainerRestart
ContainerStart
ContainerKill
ContainerPause
ContainerUnpause
ContainerWait
ContainerResize
ContainerCommit
ContainerDestroy
ContainerCopy
ContainerAttach
ContainerLogs
ContainerChanges
ContainerTop
本文主要介绍一些重要的管理操作,向ContainerExport、ContainerRestart等这种不太重要的暂不介绍。
type Container struct {
sync.Mutex
root string // Path to the "home" of the container, including metadata.
basefs string // Path to the graphdriver mountpoint
ID string
Created time.Time
Path string
Args []string
Config *runconfig.Config
State State
Image string
NetworkSettings *NetworkSettings
ResolvConfPath string
HostnamePath string
HostsPath string
Name string
Driver string
ExecDriver string
command *execdriver.Command
stdout *utils.WriteBroadcaster
stderr *utils.WriteBroadcaster
stdin io.ReadCloser
stdinPipe io.WriteCloser
daemon *Daemon
MountLabel, ProcessLabel string
waitLock chan struct{}
Volumes map[string]string
// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
// Easier than migrating older container configs :)
VolumesRW map[string]bool
hostConfig *runconfig.HostConfig
activeLinks map[string]*links.Link
}
查找容器使用的Image
检查Image的层数,如果层数大于124层则创建失败。
合并并校验配置信息。
创建container,即创建一个Container类型的对象并设置相应成员变量。
创建容器的rootfs。
以aufs为例
先创建两个目录:
/var/lib/docker/aufs/mnt/容器id-init
/var/lib/docker/aufs/diff/容器id-init
创建/var/lib/docker/aufs/layers/容器id-init文件,并在文件中写入各上级ImageID。
在目录[/var/lib/docker/aufs/mnt/容器id-init]上逐层挂载上级Image的文件系统。
在目录[/var/lib/docker/aufs/mnt/容器id-init]创建初始化层,即创建当前容器要使用的基本目录和文件,包括以下内容:
* /dev/pts目录
* /dev/shm目录
* /proc目录
* /sys目录
* /.dockerinit文件
* /.dockerenv文件
* /etc/resolv.conf文件
* /etc/hosts文件
* /etc/hostname文件
* /dev/console文件
* /etc/mtab文件
在创建目录[/var/lib/docker/aufs/mnt/容器id],注意,此时没有mount文件系统。
减少目录[/var/lib/docker/aufs/mnt/容器id-init]的引用计数。
将container的JSON描述文件写入磁盘。
注册container。 在daemon的containers中加入刚创建的container。
准备环境变量。
设置DNS
主要是设置容器对象的ResolvConfPath的值。
如果采用主机网络模式,则直接使用主机的resolv.conf文件
如果容器启动命令或docker daemon设置了dns,则根据设置内容生成resolv.conf文件
关于网络模式请参考Docker之网络模式
mount文件系统
主要是调用graphdriver的Get函数来mount文件系统。
关于graphdriver请参考Docker之graphdriver
初始化网络
根据容器启动命令中配置的网络模式设置容器的Hostname、Domainname、HostsPath、ResolvConfPath。
关于网络模式请参考Docker之网络模式
检查Daemon设置
准备volumes
设置容器链接
根据容器启动命令中配置的link参数设置容器的链接。主要是根据配置生成相应的环境变量。
设置工作目录
创建环境变量
准备启动命令
根据配置信息设置容器对象对应command(execdriver.Command)
设置volumes的在容器中的mount信息
准备stdout和stderr对应的日志文件
启动容器
最终调用docker使用的execdriver的Run函数。
关于execdriver请参考Docker之execdriver
最终调用docker使用的execdriver的Parse函数来挂起容器中的进程。关于execdriver请参考Docker之execdriver
最终是通过cgroup的freezer控制的,即向freezer.state文件中接入FROZEN。