原创是我码字的基本原则 docker想必大家都是耳熟能详的,本人工作中也经常会用到,感觉docker的成功不是没有道理的。由于本人的好奇心很重,所以接触到一个东西,一定要看一下源代码,或者至少要自己明白这里面是如何实现的,今天我就说一下我看docker源码之后所明白的一点点东西,希望对大家有帮助。 docker的基本命令大家都很熟悉,比如: 今天我主要说一下docker中容器创建的过程。这两个是我们对容器操作的最常用的命令,docker run 命令是创建并启动容器,docker create 是创建但是不启动容器。创建容器对于docker来说是一次请求,而启动容器是另外一个请求,如果我们执行docker run 命令其实和先发送一个创建容器的请求,再发送一个启动容器的请求是一样的。本质都是两个post。 今天不演示发送请求的代码,如果感兴趣可以看我之前的文章,有说过使用docker编译启动sever的文章。今天和大家分享一下docker内部如何接收请求的。 先看一下docker一共有多少的路由: 这些是关于容器的所有的接口,我们创建容器用的是 /containers/create 接口。r.postContainersCreate 方法是容器创建的具体实现,代码我这里不写出来了,这个方法主要是对请求的参数进行解析,然后配置,最终再创建容器。其最终目的是实例化了一个 Container 的结构体我们先看一下容器的结构: (头条对代码的支持让人头疼啊,希望要深入学习的可以自己下载源码看一下) 这是docker的container的结构,首先说ID字段,这个是每一个容器独有的ID信息,每次创建都会生成下面这样一个ID: 一个64位的十六进制字符串,但是我们看到的只是前12位,大家可能会问,64位的可以不重复,但是截取前12位不就可能重复了吗?是的,所以在截取这个ID时,docker内部是做了检查的,只有判断是已有的容器唯一的ID才可以。 ImageID字段,这个就是创建容器使用的镜像的ID,在我们创建容器发送请求时我们已经指定了容器的名字,这里就是这个镜像的ID。 我们看一下创建一个base container的代码: NewState(): 创建一个默认状态对象,其中包含一个用于状态更改的新信道(里面的具体实现不在这里讲解,如果大家感兴趣,以后我会慢慢的都写一遍的)。 这里是创建一个最基础的容器,每一个容器都是这样,创建了这个base container之后,再根据具体的需求,修改这个容器。 容器创建好了之后,我们的守护线程(daemon)就会保存起来了,在运行的时候我们就可以直接用了。容器的创建过程的细节还有很多,如果要把所有都说一遍,恐怕要几篇文章才能说的完。 其实创建容器的目的就是实例化了这样一个结构体,结构体的基本信息有一些是我们指定的,比如使用的镜像,mount的目录,映射的端口等,还有一些就是docker自己管理的信息。我们创建了一个容器实质上就是有了这个结构体的实例,接下来我们就可以启动这个容器了,启动容器今天不做过多介绍,下一篇文章我再继续和大家分享。 其实创建的过程是很简单的,只不过是实例化了一个container的结构体。但是运行的过程要比这个复杂了。 今天没有说里面的细节,只是和大家说一下大体实现过程,等以后我会将内部的具体实现都会写出来。大体说一下有助于我们理解,如果要做类似docker的产品的开发就需要深究了。 后续会有更多的模式和算法以及区块链相关的,如果你是想学习go语言或者是对设计模式或者算法感兴趣亦或是区块链开发工作者,都可以关注一下。(微信公众号:Go语言之美,更多go语言知识信息等)。公众号会持续为大家分享更多干货。docker run; docker create
// initRoutes initializes the routes in container router
func (r *containerRouter) initRoutes() {
r.routes = []router.Route{
// HEAD
router.NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive),
// GET
router.NewGetRoute("/containers/json", r.getContainersJSON),
router.NewGetRoute("/containers/{name:.*}/export", r.getContainersExport),
router.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges),
router.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName),
router.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop),
router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs),
router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats),
router.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach),
router.NewGetRoute("/exec/{id:.*}/json", r.getExecByID),
router.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive),
// POST
router.NewPostRoute("/containers/create", r.postContainersCreate),
router.NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill),
router.NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause),
router.NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause),
router.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart),
router.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart),
router.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop),
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), // Deprecated since 1.8, Errors out since 1.12
router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
router.NewPostRoute("/containers/prune", r.postContainersPrune),
router.NewPostRoute("/commit", r.postCommit),
// PUT
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
// DELETE
router.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers),
}
}
// Container holds the structure defining a container object.
type Container struct {
StreamConfig *stream.Config
// embed for Container to support states directly.
*State `json:"State"` // Needed for Engine API version <= 1.11
Root string `json:"-"` // Path to the "home" of the container, including metadata.
BaseFS containerfs.ContainerFS `json:"-"` // interface containing graphdriver mount
RWLayer layer.RWLayer `json:"-"`
ID string
Created time.Time
Managed bool
Path string
Args []string
Config *containertypes.Config
ImageID image.ID `json:"Image"`
NetworkSettings *network.Settings
LogPath string
Name string
Driver string
OS string
// MountLabel contains the options for the 'mount' command
MountLabel string
ProcessLabel string
RestartCount int
HasBeenStartedBefore bool
HasBeenManuallyStopped bool // used for unless-stopped restart policy
MountPoints map[string]*volumemounts.MountPoint
HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable
ExecCommands *exec.Store `json:"-"`
DependencyStore agentexec.DependencyGetter `json:"-"`
SecretReferences []*swarmtypes.SecretReference
ConfigReferences []*swarmtypes.ConfigReference
// logDriver for closing
LogDriver logger.Logger `json:"-"`
LogCopier *logger.Copier `json:"-"`
restartManager restartmanager.RestartManager
attachContext *attachContext
// Fields here are specific to Unix platforms
AppArmorProfile string
HostnamePath string
HostsPath string
ShmPath string
ResolvConfPath string
SeccompProfile string
NoNewPrivileges bool
// Fields here are specific to Windows
NetworkSharedContainerID string `json:"-"`
SharedEndpointList []string `json:"-"`
}
82303d4d4bc0b0c71b789e2160d0c27237489221202f28813e456248056b76a8
// NewBaseContainer creates a new container with its
// basic configuration.
func NewBaseContainer(id, root string) *Container {
return &Container{
ID: id,
State: NewState(),
ExecCommands: exec.NewStore(),
Root: root,
MountPoints: make(map[string]*volumemounts.MountPoint),
StreamConfig: stream.NewConfig(),
attachContext: &attachContext{},
}
}