当前位置:首页 > CN2资讯 > 正文内容

windows docker 服务器 docker server

3天前CN2资讯


一、Docker Server创建流程

Docker Server是Daemon Server的重要组成部分,功能:接收Docker Client发送的请求,并按照相应的路由规则实现请求的路由分发,最终将请求处理的结果返回给Docker Client。

Docker Daemon启动,在mainDaemon()运行的最后创建并运行serverapi的Job,让Docker Daemon提供API访问服务。

Docker Server的整个生命周期

1. 创建Docker Server的Job
2. 配置Job的环境变量
3. 触发执行Job

说明:本文分析的代码为Docker 1.2.0版本。

(一)创建“serverapi”的Job

/docker/daemon.go

/docker/daemon.go

func mainDaemon() { ... // Serve api job := eng.Job("serveapi", flHosts...) ... }

运行serverapi的Job时,会执行该Job的处理方法api.ServeApi。

(二)配置Job环境变量

/docker/daemon.go

job.SetenvBool("Logging", true) job.SetenvBool("EnableCors", *flEnableCors) job.Setenv("Version", dockerversion.VERSION) job.Setenv("SocketGroup", *flSocketGroup) job.SetenvBool("Tls", *flTls) job.SetenvBool("TlsVerify", *flTlsVerify) job.Setenv("TlsCa", *flCa) job.Setenv("TlsCert", *flCert) job.Setenv("TlsKey", *flKey) job.SetenvBool("BufferRequests", true)

参数分为两种

  • 创建Job实例时,用指定参数直接初始化Job的Args属性
  • 创建Job后,给Job添加指定的环境变量

环境变量名

FLAG参数

默认

作用值

Logging

 

true

启用Docker容器的日志输出

EnableCors

flEnableCors

false

在远程API中提供CORS头

Version

 

 

显示Docker版本号

SocketGroup

flSockerGroup

docker

在daemon模式中unix domain socket分配用户组名

Tls

flTls

false

使用TLS安全传输协议

TlsVerify

flTlsVerify

false

使用TLS并验证远程客户端

TlsCa

flCa

 

指定CA文件路径

TlsCert

flCert

 

TLS证书文件路径

TlsKey

flKey

 

TLS密钥文件路径

BufferRequest

 

true

缓存Docker Client请求

(三)运行Job

/api/server/server.go

if err := job.Run(); err != nil { log.Fatal(err) }

Docker在eng对象中注册过键位serverapi的处理方法,在运行Job的时候执行这个处理方法的值函数,相应的处理方法的值为api.ServeApi。

二、ServeApi运行流程

     ServeApi属于Docker Server提供API服务的部分,作为一个监听请求、处理请求、响应请求的服务端,支持三种协议:TCP协议、UNIX Socket形式以及fd的形式。功能是:循环检查Docker Daemon支持的所有协议,并为每一种协议创建一个协程goroutine,并在协程内部配置一个服务于HTTP请求的服务端。

/api/server/server.go

// ServeApi loops through all of the protocols sent in to docker and spawns // off a go routine to setup a serving http.Server for each. func ServeApi(job *engine.Job) engine.Status { if len(job.Args) == 0 { return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", ) } var ( protoAddrs = job.Args chErrors = make(chan error, len(protoAddrs)) ) activationLock = make(chan struct{}) for _, protoAddr := range protoAddrs { protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", ) } go func() { log.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1]) chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job) }() } for i := 0; i < len(protoAddrs); i += 1 { err := <-chErrors if err != nil { return job.Error(err) } } return engine.StatusOK }

ServeApi执行流程:
1. 检查Job参数,确保传入参数无误
2. 定义Docker Server的监听协议与地址,以及错误信息管理channel
3. 遍历协议地址,针对协议创建相应的服务端
4. 通过chErrors建立goroutine与主进程之间的协调关系

(一)判断Job参数

判断Job参数,job.Args,即数组flHost,若flHost的长度为0,则说明没有监听的协议与地址,参数有误。

/api/server/server.go

func ServeApi(job *engine.Job) engine.Status { if len(job.Args) == 0 { return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", ) } ... }

(二)定义监听协议与地址及错误信息

/api/server/server.go

var ( protoAddrs = job.Args chErrors = make(chan error, len(protoAddrs)) ) activationLock = make(chan struct{})

定义protoAddrs[flHosts的内容]、chErrors[错误类型管道]与activationLock[同步serveapi和acceptconnections两个job执行的管道]三个变量,

(三)遍历协议地址

/api/server/server.go

for _, protoAddr := range protoAddrs { protoAddrParts := strings.SplitN(protoAddr, "://", 2) if len(protoAddrParts) != 2 { return job.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", ) } go func() { log.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1]) chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job) }() }

遍历协议地址,针对协议创建相应的服务端。协议地址

(四)协调chErrors与主进程关系

根据chErrors的值运行,如果chErrors这个管道中有错误内容,则ServerApi一次循环结束,若无错误内容,循环被阻塞。即chErrors确保ListenAndServe所对应的协程能和主函数ServeApi进行协调,如果协程出错,主函数ServeApi仍然可以捕获这样的错误,从而导致程序退出。

/api/server/server.go

for i := 0; i < len(protoAddrs); i += 1 { err := <-chErrors if err != nil { return job.Error(err) } } return engine.StatusOK

三、ListenAndServe实现

ListenAndServe的功能:使Docker Server监听某一指定地址,并接收该地址的请求,并对以上请求路由转发至相应的处理方法处。


ListenAndServe执行流程:


1. 创建route路由实例

2. 创建listener监听实例

3. 创建http.Server

4. 启动API服务


流程图:


(一)创建route路由实例

/api/server/server.go

// ListenAndServe sets up the required http.Server and gets it listening for // each addr passed in and does protocol specific checking. func ListenAndServe(proto, addr string, job *engine.Job) error { var l net.Listener r, err := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version")) if err != nil { return err } ... }

路由实例的作用:负责Docker Server对外部请求的路由及转发。

实现过程:

1. 创建全新的route路由实例
2. 为route实例添加路由记录

1、创建空路由实例

/api/server/server.go

func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion string) (*mux.Router, error) { r := mux.NewRouter() ... }

/vendor/src//gorilla/mux/mux.go

// NewRouter returns a new router instance. func NewRouter() *Router { return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} } // This will send all incoming requests to the router. type Router struct { // Configurable Handler to be used when no route matches. NotFoundHandler http.Handler // Parent route, if this is a subrouter. parent parentRoute // Routes to be matched, in order. routes []*Route // Routes by name for URL building. namedRoutes map[string]*Route // See Router.StrictSlash(). This defines the flag for new routes. strictSlash bool // If true, do not clear the request context after handling the request KeepContext bool }

NewRoute()函数返回一个全新的route实例r,类型为mux.Router。实例初始化nameRoutes和KeepContext。

  • nameRoutes:map类型,key为string类型,value为Route路由记录类型
  • KeepContext:属性为false,则处理完请求后清除请求内容,不对请求做存储操作

mux.Router会通过一系列已经注册过的路由记录,来匹配接收的请求。先通过请求的URL或者其他条件找到相应的路由记录,并调用这条记录中的执行处理方法。

mux.Router特性

  • 请求可以基于URL的主机名、路径、路径前缀、shemes、请求头和请求值、HTTP请求方法类型或者使用自定义的匹配规则
  • URL主机名和路径可以通过一个正则表达式来表示
  • 注册的URL可以直接被运用,也可以保留从而保证维护资源的使用
  • 路由记录同样看可以作用于子路由记录

2、添加路由记录

/api/server/server.go

if os.Getenv("DEBUG") != "" { AttachProfiler(r) } m := map[string]map[string]HttpApiFunc{ "GET": { "/_ping": ping, "/events": getEvents, "/info": getInfo, "/version": getVersion, "/images/json": getImagesJSON, "/images/viz": getImagesViz, "/images/search": getImagesSearch, "/images/{name:.*}/get": getImagesGet, "/images/{name:.*}/history": getImagesHistory, "/images/{name:.*}/json": getImagesByName, "/containers/ps": getContainersJSON, "/containers/json": getContainersJSON, "/containers/{name:.*}/export": getContainersExport, "/containers/{name:.*}/changes": getContainersChanges, "/containers/{name:.*}/json": getContainersByName, "/containers/{name:.*}/top": getContainersTop, "/containers/{name:.*}/logs": getContainersLogs, "/containers/{name:.*}/attach/ws": wsContainersAttach, }, "POST": { "/auth": postAuth, "/commit": postCommit, "/build": postBuild, "/images/create": postImagesCreate, "/images/load": postImagesLoad, "/images/{name:.*}/push": postImagesPush, "/images/{name:.*}/tag": postImagesTag, "/containers/create": postContainersCreate, "/containers/{name:.*}/kill": postContainersKill, "/containers/{name:.*}/pause": postContainersPause, "/containers/{name:.*}/unpause": postContainersUnpause, "/containers/{name:.*}/restart": postContainersRestart, "/containers/{name:.*}/start": postContainersStart, "/containers/{name:.*}/stop": postContainersStop, "/containers/{name:.*}/wait": postContainersWait, "/containers/{name:.*}/resize": postContainersResize, "/containers/{name:.*}/attach": postContainersAttach, "/containers/{name:.*}/copy": postContainersCopy, }, "DELETE": { "/containers/{name:.*}": deleteContainers, "/images/{name:.*}": deleteImages, }, "OPTIONS": { "": optionsHandler, }, }

m的类型为映射,key表示HTTP的请求类型,如GET、POST、DELETE等,value为映射类型,代表URL与执行处理方法的映射。

/api/server/server.go

type HttpApiFunc func(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error

(二)创建listener监听实例

路由模块完成请求的路由与分发,监听模块完成请求的监听功能。Listener是一种面向流协议的通用网络监听模块。

/api/server/server.go

var l net.Listener ... if job.GetenvBool("BufferRequests") { l, err = listenbuffer.NewListenBuffer(proto, addr, activationLock) } else { l, err = net.Listen(proto, addr)

Listenbuffer的作用:让Docker Server立即监听指定协议地址上的请求,但将这些请求暂时先缓存下来,等Docker Daemon全部启动完毕之后才让Docker Server开始接受这些请求。

/pkg/listenbuffer/buffer.go

// NewListenBuffer returns a listener listening on addr with the protocol. func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) { wrapped, err := net.Listen(proto, addr) if err != nil { return nil, err } return &defaultListener{ wrapped: wrapped, activate: activate, }, nil }

若协议类型为TCP,Job环境变量中Tls或TlsVerity有一个为true,则说明Docker Server需要支持HTTPS服务。需要建立一个tls.Config类型实例tlsConfig,在tlsConfig中加载证书、认证信息,通过tls包中的NewListener函数创建HTTPS协议请求的Listener实例。

/api/server/server.go

l = tls.NewListener(l, tlsConfig)

(三)创建http.Server

/api/server/server.go

httpSrv := http.Server{Addr: addr, Handler: r}

Docker Server需要创建一个Server对象来运行HTTP/HTTPS服务端,创建http.Server,addr为需要监听的地址,r为mux.Router。

(四)启动API服务

创建http.Server实例后,即启动API服务,监听请求,并对每一个请求生成一个新的协程来做专属服务。对于每个请求,协程会读取请求,查询路由表中的路由记录项,找到匹配的路由记录,最终调用路由记录中的处理方法,执行完毕返回响应信息。

/api/server/server.go

return httpSrv.Serve(l)

 

 文章参考:

《Docker源码分析》

    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/30308.html

    分享给朋友:

    “windows docker 服务器 docker server” 的相关文章

    蘑菇云:自然与核爆炸的惊人现象及其深远影响

    蘑菇云这个词,一提起来让人既熟悉又敬畏。它的外形就像个倒立的蘑菇,顶部宽大、底部则较小,这是因为它源自于强大爆炸所产生的气体。这种云朵看似平常,却是一种强烈爆炸后气体与空气混合的结果。虽然蘑菇云在现代多被与核爆炸联系在一起,但实际上,火山喷发及一些天体撞击也可能产生自然形成的蘑菇云。 了解蘑菇云的形...

    如何查看域名是否被墙:检测工具与方法指南

    域名被墙是一个对很多网站管理员和用户来说都比较陌生的概念。简单来说,当一个网站的内容被认为敏感或者违反某些规定时,防火墙就会把这个域名屏蔽。即使用户通过输入域名试图访问,DNS 解析也许正常,但实际上网站却无法顺利加载。在国内用户访问国外网站或者国外用户尝试访问国内网站时,情况尤为明显,就好像在国际...

    阿里云国际:企业数字化转型的理想云服务解决方案

    阿里云国际概述 阿里云国际成立于2015年,致力于为全球用户提供高效、可靠、安全的云计算服务。作为阿里巴巴集团的一部分,阿里云国际不仅承载着国内市场的技术精华,也积极拓展国际市场。随着全球互联网的快速发展,企业对云服务的需求不断增加,阿里云国际顺应这一趋势,凭借创新的技术和丰富的经验,迅速在全球范围...

    银联卡购买:便捷与安全的消费体验

    在这个快速发展的支付时代,银联卡作为一种便捷的支付工具,已经逐渐渗透到我们的日常生活中。我常常发现自己在购物、旅行时,银联卡都能为我省去不少麻烦。通过这张小小的卡片,我可以轻松实现线上和线下消费,四处都能找到它的身影。 银联卡的发展背景十分丰富。自1994年银联成立以来,它不断扩大和完善自己的支付网...

    HostHatch怎么样?全面评测云服务提供商的性能与性价比

    我们今天要聊聊HostHatch,这个相对年轻却迅速崛起的云服务提供商。简单来说,HostHatch成立于不久前,目标是为用户提供高效、经济的托管服务。他们的理念十分清晰,就是希望能让更多的人无需复杂的技术知识,也能轻松享受到稳定高效的服务器服务。 HostHatch的创始团队由一群充满激情的科技爱...

    AWS新加坡评测:用户体验与性价比全面分析

    在探索AWS在新加坡的使用体验时,服务的可用性是我最先关注的方面。AWS 在全球范围内的广泛服务网络给予用户许多选择。在新加坡,AWS 提供了多种计算、存储和数据库等服务,让我感觉使用起来非常方便。尤其是在需要快速部署解决方案或应对业务高峰时,AWS 新加坡的数据中心承载能力和稳定性非常令人满意。无...