/sbin/init
检查docker可执行文件的绝对路径是否在/sbin/init目录下已经存在
如果在,则设置docker容器启动之前的环境:
设置环境变量
设置网络
根据参数中的网关IP添加网关路由
设置uid/gid
根据参数中的username或者uid,调用系统调用设置uid和gid,切换用户
exec执行docker程序
如果不存在则根据参入的命令行参数选择启动docker deamon还是执行docker cli的命令调用
-d daemon
主要是创建一个server对象, 然后通过这个server创建tcp服务端,创建server实质就是创建runtime对象,runtime对象中封装了所有docker daemon运行时所需要的所有的信息,在创建runtime时,首先会在 /var/lib/docker目录下创建对应的文件:containers,graph文件夹,然后创建对应的镜像tag存储对象,通过名为lxcbr0的卡的网络创建网络管理,最后创建dockerhub的认证对象AuthConfig。
创建runtime
只支持amd64,在/var/lib/docker创建runtime
containers
创建目录,权限0700
graph
创建目录,权限0700
repositories
创建或读入文件
关键数据结构:
1 | type TagStore struct { |
如果存在/var/lib/docker/repositories文件(json格式),则读入文件内容到TagStore中,否则将TagStore内容写入到/var/lib/docker/repositories文件,权限为0600。
从lxcbr0网桥接口创建网络管理器
通过指定名为lxcbr0的网络接口来实现网络管理,一个网络管理的实例包括:网桥名字,ip网络,ip分配器,端口分配器,端口映射器。实例化一个网络管理时,要将这些属性全部赋值,ip分配器是一个ip地址的channel,里面的ip地址是通过lxcbr0接口的ip 和对应的网关mask计算得到的子网ip。端口分配器是一个存放了指定范围49153~65535个int的channel,端口映射器是设置和清除iptable的方法集合。
根据网络接口获取IPv4地址(net.IPNet)
根据IPv4地址创建IP分配器(利用了net.IPNet),通过网卡lxcbr0的第一个ip和网关mask得到这个网卡下的所有子网ip,并且封装成一个ip分配器
1 | 根据IPv4计算网络地址范围(首IP-末IP),取首IP |
创建port分配器,端口范围地址为[49153,65535]
1 | 阻塞写入所有port到分配器port队列 |
创建PortMapper,端口映射器通过设置iptables规则来处理将外部端口映射到容器。它跟踪所有映射,并能够随意取消映射。
1 | 删除docker规则链 |
读取认证文件
仓库地址为 https://registry.docker.io ,文件路径为/var/lib/docker/.dockercfg,包括两个字段:auth = basic auth值、email = email值
创建runtime数据结构
1 | root: /var/lib/docker |
恢复容器
读取/var/lib/docker/containers目录,实际就是所有之前运行过的容器的目录,目录名为对应容器的id,对于每一个文件夹:
1 | 每个文件夹都有一个config.json文件,将其读入到Container数据结构中,实例化一个container对象,包括容器id |
创建tcp服务端
在127.0.0.1:4242上启动tcp监听,接受tcp的请求,为每个请求开启一个单独的协程处理请求,如果有请求到来则进行处理。处理过程为:获取请求中的参数然后调用call,call根据参数是否有值来执行不同方法,如果没有参数,则执行runtime的help方法;如果有参数,进行参数的处理,处理逻辑:获取第二个参数,作为docker后的命令,然后获取命令之后的所有参数,整条命令进行日志打印输出,之后再通过cmd命令和反射技术找到对应的cmd所对应的方法,最后将参数传入方法,执行cmd对应的方法,结果返回connect中。
connect在此作为io.Writer类型参数,命令结果将写入到其中。
关于lxcbr0
安装lxc之后,就会有lxcbr0网络接口。
几个参考链接:
github lxc
lxc官网
LXC-Linux Containers介绍
Linux 容器的建立和简单管理
Enable LXC neworking in Debian Jessie, Fedora 21 and others
lxc安装
Centos7在Base repo上没有可用的lxc,因此需要先安装epel仓库。
1 | yum -y install epel-release |
利用brctl工具来创建网桥lxcbr0,利用dnsmasq工具提供dhcp服务。
1 | vim /etc/systemd/system/lxc-net.service |
添加
1 | [Unit] |
1 | vim /etc/systemd/system/lxc-dhcp.service |
添加
1 | [Unit] |
1 | systemctl enable lxc-net.service |
查看是否存在逻辑(虚拟)网桥接口
1 | brctl show |
如果已经存在可以用以下命令删除
1 | brctl delbr +网桥名 |
command
1 | TODO... |