ÔÚÉÏÎÄDockerÔ´Âë·ÖÎöÖ®¡ª¡ªDocker
DaemonµÄÆô¶¯ ÖУ¬½éÉÜÁËDocker Daemon½ø³ÌµÄÆô¶¯¡£Docker Daemon¿ÉÒÔÈÏΪÊÇÒ»¸öDocker×÷ΪServerµÄÔËÐÐÔØÌ壬¶øÕæÕý·¢Ë͹ØÓÚdocker
container²Ù×÷µÄÇëÇóµÄÔØÌ壬ÔÚÓÚDocker Client¡£±¾ÎÄ´ÓDockerÔ´ÂëµÄ½Ç¶È£¬·ÖÎöDocker
ClientÆô¶¯ÓëÖ´ÐÐÇëÇóµÄ¹ý³Ì¡£
Docker ClientÆô¶¯µÄÁ÷³ÌÓëDocker DaemonÆô¶¯µÄ¹ý³ÌÏà·Â¡£Ê×ÏÈÖ´ÐÐreexec.Init()£»Ëæºó½âÎöflag²ÎÊý£»ÓÉÓÚûÓÐÖ¸¶¨-v£¬-D²ÎÊý£¬Òò´Ë*flVersionÓë*flDebug¾ùΪfalse£¬²»Ö´ÐÐÏàÓ¦µÄ´úÂë¿é£»½Ó×ųÌÐòÖ´ÐÐflHostsÐÅÏ¢µÄ»ñÈ¡ÓëÑéÖ¤£»ÓÖÓÉÓÚûÓÐÖ¸¶¨-d²ÎÊý£¬¹Ê*flDeamonΪfalse£¬²»»áÖ´ÐÐmainDaemon()·½·¨ËùÔڵĴúÂë¿é£»×îºó£¬½Ó×ÅÖ´ÐеͼÊÇDocker
ClientÆô¶¯ÒÔ¼°Ö´ÐеŤ×÷¡£
Ê×ÏÈ£¬ÑéÖ¤flHosts²ÎÊýÖÐÊÇ´øÓжà¸öHostµÄÐÅÏ¢£¬Èçtcp://host:port£¬unix://path_to_socket»òÕßfd://socketfd£¬µ±flHostsµÄ³¤¶È´óÓÚ1£¬¼´HostÐÅÏ¢²»Ö¹Ò»¸öʱ£¬Í¨¹ýlogµÄÐÎʽ֪ͨÓû§×îºÃÖ¸¶¨Ò»¸öHost¡£È»ºó£¬Ä¬ÈϽ«flHostsÐÅÏ¢ÖеĵÚÒ»¸ö¶ÔÏó×÷ΪHost£¬½øÐÐÐÒéÓëhostµØÖ·µÄ½âÎö£¬´úÂëÈçÏ£º
if len(flHosts) > 1 { log.Fatal("Please specify only one -H") } protoAddrParts := strings.SplitN(flHosts[0], "://", 2) |
½Ó×Å£¬´´½¨Ò»¸öDocker ClientµÄcliÒÔ¼°Ó밲ȫ´«Êä²ãÐÒéTLSÏà¹ØµÄ¶ÔÏótlsConfig¡£°²È«´«Êä²ãÐÒ飨TLS£©ÓÃÓÚÁ½¸öͨÐÅÓ¦ÓóÌÐòÖ®¼ä±£ÃÜÐÔÓëÊý¾ÝÍêÕûÐÔ£¬¸ÃÐÒéÓÐÁ½²ã×é³É£ºTLS¼Ç¼ÐÒéºÍTLSÎÕÊÖÐÒé¡£´úÂëÈçÏ£º
var ( cli *client.DockerCli tlsConfig tls.Config ) tlsConfig.InsecureSkipVerify = true |
Ëæºó£¬Èç¹ûÖ´ÐÐdockerÃüÁîµÄʱºòÖ¸¶¨ÁË-tlsverify²ÎÊý£¬Ôò*flTlsVerifyΪtrue£¬ËµÃ÷Docker
ClientÐèÒª¼ÓÔØÒ»¸öÊÜÐŵÄca£¬ÓÃÒÔÑéÖ¤ Docker Server£¬Ö´ÐÐһϴúÂë¿é£º
// If we should verify the server, we need to load a trusted ca if *flTlsVerify { *flTls = true certPool := x509.NewCertPool() file, err := ioutil.ReadFile(*flCa) if err != nil { log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err) } certPool.AppendCertsFromPEM(file) tlsConfig.RootCAs = certPool tlsConfig.InsecureSkipVerify = false } |
¿ÉÒÔ¿´µ½£¬×îÒªµÄ¾ÍÊÇ*flCa²ÎÊý£¬¶ø¸Ã²ÎÊýÔÚ./docker/flag.goÖеÄinit()·½·¨Öгõʼ»¯Ê±±»¸³Öµ£¬ÈçÏ£º
flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile),
"Trust only remotes providing a certificate signed by the CA given here") |
var ( dockerCertPath = os.Getenv("DOCKER_CERT_PATH") ) |
const ( defaultCaFile = "ca.pem" defaultKeyFile = "key.pem" defaultCertFile = "cert.pem" ) |
Òò´Ë£¬¿ÉÒÔͨ¹ýÒÔÉÏÐÅÏ¢£¬»ñÈ¡*flCa£¬²¢¶ÁÈ¡ÏàÓ¦µÄca.pemÎļþ£¬×îÖÕÌí¼ÓÖÁtlsConfig¶ÔÏóµÄÊôÐÔRootCAsºÍInsecureSkipVerifyÖС£
ÑéÖ¤Íêserver£¬Ìí¼ÓÁËÊÜÐÅcaºó£¬Docker ClientÐèÒªÅäÖÃÈÏÖ¤ÐÅÏ¢£¬ÒÔ±ãÖ®ºóµÄ·¢ËÍ¡£Ö÷Òª»¹ÊǸøtlsConfig¶ÔÏóÖÐÌí¼ÓÊôÐÔCertificates£¬´úÂëÈçÏ£º
// If tls is enabled, try to load and send client certificates if *flTls || *flTlsVerify { _, errCert := os.Stat(*flCert) _, errKey := os.Stat(*flKey) if errCert == nil && errKey == nil { *flTls = true cert, err := tls.LoadX509KeyPair(*flCert, *flKey) if err != nil { log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err) } tlsConfig.Certificates = []tls.Certificate{cert} } } |
ÒÔÏÂÕæÕý¸øDocker ClientµÄcli¶ÔÏó³õʼ»¯£¬Ö÷ÒªµÄÇø±ðÔÚÓÚÊÇ·ñÐèҪʹÓð²È«´«Êä²ãÐÒ飬¼´Ö»Òª*flTlsºÍ*flTlsVerifyÖÐÓÐÒ»¸öΪtrue£¬Ôò˵Ã÷ÐèҪʹÓð²È«´«Êä²ãÐÒ飻·´Ö®£¬²»Ê¹Óð²È«´«Êä²ãÐÒé¡£
if *flTls || *flTlsVerify { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig) } else { cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil) } |
client.NewDockerCli()µÄʵÏÖλÓÚ./api/client/cli.go£¬´úÂëÈçÏ£º
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli { var ( isTerminal = false terminalFd uintptr scheme = "http" ) if tlsConfig != nil { scheme = "https" } if in != nil { if file, ok := out.(*os.File); ok { terminalFd = file.Fd() isTerminal = term.IsTerminal(terminalFd) } } if err == nil { err = out } return &DockerCli{ proto: proto, addr: addr, in: in, out: out, err: err, isTerminal: isTerminal, terminalFd: terminalFd, tlsConfig: tlsConfig, scheme: scheme, } } |
×ÜÌå¶øÑÔ£¬´´½¨DockerCli¶ÔÏó½ÏΪ¼òµ¥£¬½ÏÎªÖØÒªµÄDockerCliµÄÊôÐÔÓÐproto£º´«ÊäÐÒ飻addr£ºhostµÄÄ¿±êµØÖ·£¬tlsConfig£º°²È«´«Êä²ãÐÒéµÄÅäÖá£ÈôtlsConfigΪÓÐÄÚÈÝ£¬Ôò˵Ã÷ÐèҪʹÓð²È«´«Êä²ãÐÒ飬DockerCli¶ÔÏóµÄschemeÉèÖÃΪ¡°https¡±£¬ÁíÍ⻹ÓйØÓÚÊäÈ룬Êä³öÒÔ¼°´íÎóÏÔʾµÄÅäÖã¬×îÖÕ·µ»Ø¸Ã¶ÔÏó¡£
ÔÚ./docker/docker.goÖУ¬´´½¨Íê¸øcli¶ÔÏó³õʼ»¯Ö®ºó£¬Ö´ÐеľÍÊÇÓû§ËùÖ¸¶¨µÄÃüÁîÁË£¬´úÂëÈçÏ£º
if err := cli.Cmd(flag.Args()...); err != nil { if sterr, ok := err.(*utils.StatusError); ok { if sterr.Status != "" { log.Println(sterr.Status) } os.Exit(sterr.StatusCode) } log.Fatal(err) } |
Ôڸùý³ÌÖУ¬ÕæÕýµÄÖ´ÐÐÔØÌåΪcli.Cmd(flag.Args()...)£¬¸Ã´úÂë½âÎö²¢Ö´ÐÐÕæÕýÈç¡°docker
pull xxx¡±, ¡°docker search xxx¡±µÈµÄÖ¸Áî¡£
½øÈë./api/client/cli.goÖеÄCmd·½·¨£¬´úÂëÈçÏ£º
// Cmd executes the specified command func (cli *DockerCli) Cmd(args ...string) error { if len(args) > 0 { method, exists := cli.getMethod(args[0]) if !exists { fmt.Println("Error: Command not found:", args[0]) return cli.CmdHelp(args[1:]...) } return method(args[1:]...) } return cli.CmdHelp(args...) } |
Ê×ÏÈCmd·½·¨Í¨¹ýµÚÒ»¸ö²ÎÊýÀ´Ö´ÐÐgetMethod·½·¨£¬Èô¸ÃmethodûÓÐÕÒµ½µÄ»°£¬Ôòµ÷ÓÃCmdHelp·½·¨£¬ÈômethodÕÒµ½£¬ÔòÖ´ÐÐmethod·½·¨£¬´«Èë²ÎÊýΪµÚÒ»¸ö¿ªÊ¼ÍùºóËùÓеIJÎÊý£¬´úÂëÈçÏ£º
func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) { if len(name) == 0 { return nil, false } methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) method := reflect.ValueOf(cli).MethodByName(methodName) if !method.IsValid() { return nil, false } return method.Interface().(func(...string) error), true } |
ÒÔÏÂÒÔÃüÁî¡°docker pull xxx¡±ÎªÀý£¬·ÖÎöDocker ClientµÄCmdµÄÔËÐС£Ê×ÏÈ£¬ÔØCmd·½·¨Öд«ÈëµÄ²ÎÊýΪ¡°pull¡±£¬¡°xxx¡±£»ÔògetMethod·½·¨´«Èë²ÎÊýÖ»ÓÐÒ»¸ö£¬Îª¡°pull¡±£»getMethod·½·¨·µ»ØCmdPull£»ÔòÔÚCmd·½·¨ÖÐÖ´ÐÐCmdPull(args[1:]...)¡£¶øCmdPull·½·¨µÄʵÏÖλÓÚ./api/client/command.goÖеÄCmdPull¡£
ÔÚ¾ßÌåµÄCmdXxx·½·¨ÖУ¬Ò»°ã¶¼ÐèҪͨ¹ýcliÓÚDocker Server½øÐÐͨÐÅ£¬ÈçCmdPull·½·¨ÊµÏÖÖÐÓÐcli.stream("POST",
"/images/create?"+v.Encode(), nil, cli.out,
map[string][]string{ "X-Registry-Auth": registryAuthHeader,})
£¬¶øcliµÄstream·½·¨ÊµÏÖ£¬ÒÔ¼°ÀàËÆµÄcall·½·¨ÊµÏÖ£¬¶¼Î»ÓÚ./api/client/utils.goÖС£utils.goÖÐÖ÷ҪʵÏÖÁËcliÈçºÎÒ»¸öHTTPClientµÄÐÎʽ¸øserver·¢ËÍÇëÇó£¬ÒÔ¼°Èç¹ûÐèÒªµÄ»°£¬ÈçºÎÔÚÕû¸ö·¢Ë͹ý³ÌʹÓð²È«´«ÊäÐÒé¡£
µ±cliÇëÇó·¢ËÍÍê±Ï£¬ÇÒ½ÓÊÕµ½ÏàÓ¦µÄÏàÓ¦Ö®ºó£¬Ôò¶ÔÓÚDocker Client¶øÑÔ£¬Ö´ÐÐÒ»´ÎµÄÉúÃüÖÜÆÚ¾Í½áÊøÁË¡£µ±ÄãÐèÒªÁíÍâÔÙÖ´ÐÐÒ»¸öÃüÁîʱ£¬ÔòÐèÒªÒÔÉϵÄÁ÷³ÌÔÙ×ßÒ»±é¡£
ÒÔÉϱãÊÇ´ÓDockerÔ´ÂëµÄ½Ç¶È£¬·ÖÎöDocker ClientµÄÆô¶¯ÓëÃüÁîÖ´ÐС£ |