·ÖÏí

DockerÔ´Âë·ÖÎö(¶þ)£ºDocker Client´´½¨ÓëÃüÁîÖ´ÐÐ

±¾Ìû×îºóÓÉ pig2 ÓÚ 2014-10-14 09:12 ±à¼­
ÔĶÁµ¼¶Á£º
1.ÈçºÎͨ¹ýdockerÃüÁ½âÎö³öÃüÁîÐÐflag²ÎÊý£¬ÒÔ¼°dockerÃüÁîÖеÄÇëÇó²ÎÊý?
2.ÈçºÎ´¦Àí¾ßÌåµÄflag²ÎÊýÐÅÏ¢£¬²¢ÊÕ¼¯Docker ClientËùÐèµÄÅäÖÃÐÅÏ¢?
3.ÈçºÎ´´½¨Ò»¸öDocker Client?
4.ÈçºÎ½âÎödockerÃüÁîÖеÄÇëÇó²ÎÊý£¬»ñÈ¡ÏàÓ¦ÇëÇóµÄÀàÐÍ?
5.Docker ClientÈçºÎÖ´ÐоßÌåµÄÇëÇóÃüÁ×îÖÕ½«ÇëÇó·¢ËÍÖÁDocker Server?







1. Ç°ÑÔ
Èç½ñ£¬Docker×÷Ϊҵ½çÁìÏȵÄÇáÁ¿¼¶ÐéÄ⻯ÈÝÆ÷¹ÜÀíÒýÇ棬¸øÈ«Çò¿ª·¢ÕßÌṩÁËÒ»ÖÖÐÂÓ±¡¢±ã½ÝµÄÈí¼þ¼¯³É²âÊÔÓ벿ÊðÖ®µÀ¡£ÔÚÍŶӿª·¢Èí¼þʱ£¬Docker¿ÉÒÔÌṩ¿É¸´ÓõÄÔËÐл·¾³¡¢Áé»îµÄ×ÊÔ´ÅäÖᢱã½ÝµÄ¼¯³É²âÊÔ·½·¨ÒÔ¼°Ò»¼üʽµÄ²¿Êð·½Ê½¡£¿ÉÒÔ˵£¬DockerµÄÓÅÊÆÔÚ¼ò»¯³ÖÐø¼¯³É¡¢ÔËά²¿Êð·½ÃæÌåÏÖµÃÁÜÀ쾡Ö£¬ËüÍêÈ«Èÿª·¢Õß´Ó³ÖÐø¼¯³É¡¢ÔËά²¿Êð·½ÃæÖнâ·Å³öÀ´£¬°Ñ¾«Á¦ÕæÕýµØÇã×¢ÔÚ¿ª·¢ÉÏ¡£
È»¶ø£¬°ÑDockerµÄ¹¦ÄÜ·¢»Óµ½¼«Ö£¬²¢·ÇÒ»¼þÒ×Ê¡£ÔÚÉî¿ÌÀí½âDocker¼Ü¹¹µÄÇé¿öÏ£¬ÊìÁ·ÕÆÎÕDocker ClientµÄʹÓÃÒ²·Ç³£ÓбØÒª¡£Ç°Õß¿ÉÒÔ²ÎÔÄ¡¶DockerÔ´Âë·ÖÎö¡·ÏµÁÐÖ®Docker¼Ü¹¹Æª£¬¶ø±¾ÎÄÖ÷ÒªÕë¶ÔºóÕߣ¬´ÓÔ´ÂëµÄ½Ç¶È·ÖÎöDocker Client£¬Á¦Çó°ïÖú¿ª·¢Õ߸üÉî¿ÌµÄÀí½âDocker ClientµÄ¾ßÌåʵÏÖ£¬×îÖÕ¸üºÃµÄÕÆÎÕDocker ClientµÄʹÓ÷½·¨¡£¼´±¾ÎÄΪ¡¶DockerÔ´Âë·ÖÎö¡·ÏµÁеĵڶþƪ¡ª¡ªDocker Clientƪ¡£
2.Docker ClientµÄ´´½¨
Docker ClientµÄ´´½¨£¬ÊµÖÊÉÏÊÇDockerÓû§Í¨¹ý¿ÉÖ´ÐÐÎļþdocker£¬ÓëDocker Server½¨Á¢ÁªÏµµÄ¿Í»§¶Ë¡£ÒÔÏ·ÖÈý¸öС½Ú·Ö±ð²ûÊöDocker ClientµÄ´´½¨Á÷³Ì¡£

ÒÔÏÂΪÕû¸ödockerÔ´´úÂëÔËÐеÄÁ÷³Ìͼ£º

dockerÔ´´úÂëÔËÐеÄÁ÷³Ìͼ.jpg

ÉÏͼͨ¹ýÁ÷³ÌͼµÄ·½Ê½£¬Ê¹µÃ¶ÁÕ߸üΪÇåÎúµÄÁ˽âDocker Client´´½¨¼°Ö´ÐÐÇëÇóµÄ¹ý³Ì¡£ÆäÖÐÉæ¼°ÁËÖî¶àÔ´´úÂëÖеÄÌØÓÐÃû´Ê£¬ÔÚÏÂÎÄÖлáÒ»Ò»½âÊÍÓë·ÖÎö¡£

2.1. DockerÃüÁîµÄflag²ÎÊý½âÎö
ÖÚËùÖÜÖª£¬ÔÚDockerµÄ¾ßÌåʵÏÖÖУ¬Docker ServerÓëDocker Client¾ùÓÉ¿ÉÖ´ÐÐÎļþdockerÀ´Íê³É´´½¨²¢Æô¶¯¡£ÄÇô£¬Á˽âdocker¿ÉÖ´ÐÐÎļþͨ¹ýºÎÖÖ·½Ê½Çø·ÖÁ½Õߣ¬¾ÍÏÔµÃÓÈΪÖØÒª¡£

¶ÔÓÚÁ½Õߣ¬Ê×ÏȾÙÀý˵Ã÷ÆäÖеÄÇø±ð¡£Docker ServerµÄÆô¶¯£¬ÃüÁîΪdocker -d»òdocker --daemon=true£»¶øDocker ClientµÄÆô¶¯ÔòÌåÏÖΪdocker --daemon=false ps¡¢docker pull NAMEµÈ¡£

¿ÉÒÔ°ÑÒÔÉÏDockerÇëÇóÖеIJÎÊý·ÖΪÁ½ÀࣺµÚÒ»ÀàΪÃüÁîÐвÎÊý£¬¼´docker³ÌÐòÔËÐÐʱËùÐèÌṩµÄ²ÎÊý£¬Èç: -D¡¢--daemon=true¡¢--daemon=falseµÈ£»µÚ¶þÀàΪdocker·¢Ë͸øDocker ServerµÄʵ¼ÊÇëÇó²ÎÊý£¬È磺ps¡¢pull NAMEµÈ¡£

¶ÔÓÚµÚÒ»À࣬ÎÒÃÇÏ°¹ß½«Æä³ÆΪflag²ÎÊý£¬ÔÚgoÓïÑԵıê×¼¿âÖУ¬Í¬Ê±»¹ÌṩÁËÒ»¸öflag°ü£¬·½±ã½øÐÐÃüÁîÐвÎÊýµÄ½âÎö¡£
½»´ýÒÔÉϱ³¾°Ö®ºó£¬Ëæ¼´½øÈëʵÏÖDocker Client´´½¨µÄÔ´Â룬λÓÚ./docker/docker/docker.go£¬¸ÃgoÎļþ°üº¬ÁËÕû¸öDockerµÄmainº¯Êý£¬Ò²¾ÍÊÇÕû¸öDocker£¨²»ÂÛDocker Daemon»¹ÊÇDocker Client£©µÄÔËÐÐÈë¿Ú¡£²¿·Ömainº¯Êý´úÂëÈçÏ£º

  1. func main() {
  2.     if reexec.Init() {
  3.       return
  4.     }
  5.     flag.Parse()
  6.     // FIXME: validate daemon flags here
  7.     ¡­¡­
  8. }
¸´ÖÆ´úÂë

ÔÚÒÔÉÏ´úÂëÖУ¬Ê×ÏÈÅжÏreexec.Init()·½·¨µÄ·µ»ØÖµ£¬ÈôΪÕ棬ÔòÖ±½ÓÍ˳öÔËÐУ¬·ñÔòµÄ»°¼ÌÐøÖ´ÐС£²é¿´Î»ÓÚ./docker/reexec/reexec.goÖÐreexec.Init()µÄ¶¨Ò壬¿ÉÒÔ·¢ÏÖÓÉÓÚÔÚdockerÔËÐÐ֮ǰûÓÐÈκεÄInitializer×¢²á£¬¹Ê¸Ã´úÂë¶ÎÖ´Ðеķµ»ØֵΪ¼Ù¡£

½ô½Ó×Å£¬mainº¯Êýͨ¹ýµ÷ÓÃflag.Parse()½âÎöÃüÁîÐÐÖеÄflag²ÎÊý¡£²é¿´Ô´Âë¿ÉÒÔ·¢ÏÖDockerÔÚ./docker/docker/flag.goÖж¨ÒåÁ˶à¸öflag²ÎÊý£¬²¢Í¨¹ýinitº¯Êý½øÐгõʼ»¯¡£´úÂëÈçÏ£º

  1. var (
  2.   flVersion     = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
  3.   flDaemon      = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
  4.   flDebug       = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
  5.   flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specified by -H when running in daemon mode use '' (the empty string) to disable setting of a group")
  6.   flEnableCors  = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
  7.   flTls         = flag.Bool([]string{"-tls"}, false, "Use TLS; implied by tls-verify flags")
  8.   flTlsVerify   = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)")
  9.   // these are initialized in init() below since their default values depend on dockerCertPath which isn't fully initialized until init() runs
  10.   flCa    *string
  11.   flCert  *string
  12.   flKey   *string
  13.   flHosts []string
  14. )
  15. func init() {
  16.   flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust only remotes providing a certificate signed by the CA given here")
  17.   flCert = flag.String([]string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file")
  18.   flKey = flag.String([]string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file")
  19.   opts.HostListVar(&flHosts, []string{"H", "-host"}, "The socket(s) to bind to in daemon mode\nspecified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.")
  20. }
¸´ÖÆ´úÂë
ÕâÀïÉæ¼°µ½ÁËGolangµÄÒ»¸öÌØÐÔ£¬¼´initº¯ÊýµÄÖ´ÐС£ÔÚGolangÖÐinitº¯ÊýµÄÌØÐÔÈçÏ£º
initº¯ÊýÓÃÓÚ³ÌÐòÖ´ÐÐÇ°°üµÄ³õʼ»¯¹¤×÷£¬±ÈÈç³õʼ»¯±äÁ¿µÈ£»
ÿ¸ö°ü¿ÉÒÔÓжà¸öinitº¯Êý£»
°üµÄÿһ¸öÔ´ÎļþÒ²¿ÉÒÔÓжà¸öinitº¯Êý£»
ͬһ¸ö°üÄÚµÄinitº¯ÊýµÄÖ´ÐÐ˳ÐòûÓÐÃ÷È·µÄ¶¨Ò壻
²»Í¬°üµÄinitº¯Êý°´ÕÕ°üµ¼ÈëµÄÒÀÀµ¹Øϵ¾ö¶¨³õʼ»¯µÄ˳Ðò£»
initº¯Êý²»Äܱ»µ÷Ó㬶øÊÇÔÚmainº¯Êýµ÷ÓÃÇ°×Ô¶¯±»µ÷Óá£
Òò´Ë£¬ÔÚmainº¯ÊýÖ´ÐÐ֮ǰ£¬DockerÒѾ­¶¨ÒåÁËÖî¶àflag²ÎÊý£¬²¢¶ÔºÜ¶àflag²ÎÊý½øÐгõʼ»¯¡£¶¨ÒåµÄÃüÁîÐÐflag²ÎÊýÓУºflVersion¡¢flDaemon¡¢flDebug¡¢flSocketGroup¡¢flEnableCors¡¢flTls¡¢flTlsVerify¡¢flCa¡¢flCert¡¢flKeyµÈ¡£
ÒÔϾßÌå·ÖÎöflDaemon£º
¶¨Ò壺flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
flDaemonµÄÀàÐÍΪBoolÀàÐÍ
flDaemonÃû³ÆΪ¡±d¡±»òÕß¡±-daemon¡±£¬¸ÃÃû³Æ»á³öÏÖÔÚdockerÃüÁîÖÐ
flDaemonµÄĬÈÏֵΪfalse
flDaemonµÄ°ïÖúÐÅϢΪ¡±Enable daemon mode¡±
·ÃÎÊflDaemonµÄֵʱ£¬Ê¹ÓÃÖ¸Õë* flDaemon½âÒýÓ÷ÃÎÊ
ÔÚ½âÎöÃüÁîÐÐflag²ÎÊýʱ£¬ÒÔϵÄÓïÑÔΪºÏ·¨µÄ£º
-d, --daemon
-d=true, --daemon=true
-d=¡±true¡±, --daemon=¡±true¡±
-d=¡¯true¡¯, --daemon=¡¯true¡¯
µ±½âÎöµ½µÚÒ»¸ö·Ç¶¨ÒåµÄflag²ÎÊýʱ£¬ÃüÁîÐÐflag²ÎÊý½âÎö¹¤×÷½áÊø¡£¾ÙÀý˵Ã÷£¬µ±Ö´ÐÐdockerÃüÁîdocker --daemon=false --version=false psʱ£¬flag²ÎÊý½âÎöÖ÷ÒªÍê³ÉÁ½¸ö¹¤×÷£º
Íê³ÉÃüÁîÐÐflag²ÎÊýµÄ½âÎö£¬ÃûΪ-daemonºÍ-versionµÄflag²ÎÊýflDaemonºÍflVersion·Ö±ð»ñµÃÏàÓ¦µÄÖµ£¬¾ùΪfalse£»
Óöµ½µÚÒ»¸ö·Çflag²ÎÊýµÄ²ÎÊýpsʱ£¬½«ps¼°ÆäÖ®ºóËùÓеIJÎÊý´æÈëflag.Args()£¬ÒÔ±ãÖ®ºóÖ´ÐÐDocker Client¾ßÌåµÄÇëÇóʱʹÓá£
ÈçÐèÉîÈëѧϰflagµÄ½âÎö£¬¿ÉÒԲμûÔ´ÂëÃüÁîÐвÎÊýflagµÄ½âÎö¡£

2.2. ´¦ÀíflagÐÅÏ¢²¢ÊÕ¼¯Docker ClientµÄÅäÖÃÐÅÏ¢
ÓÐÁËÒÔÉÏflag²ÎÊý½âÎöµÄÏà¹Ø֪ʶ£¬·ÖÎöDockerµÄmainº¯Êý¾Í±äµÃ¼òµ¥Ò׶®ºÜ¶à¡£Í¨¹ý×ܽᣬÊ×ÏÈÁгöÔ´´úÂëÖд¦ÀíµÄflagÐÅÏ¢ÒÔ¼°ÊÕ¼¯Docker ClientµÄÅäÖÃÐÅÏ¢£¬È»ºóÔÙÒ»Ò»¶Ô´Ë·ÖÎö£º

´¦ÀíµÄflag²ÎÊýÓУºflVersion¡¢flDebug¡¢flDaemon¡¢flTlsVerifyÒÔ¼°flTls£»
ΪDocker ClientÊÕ¼¯µÄÅäÖÃÐÅÏ¢ÓУºprotoAddrParts(ͨ¹ýflHosts²ÎÊý»ñµÃ£¬×÷ÓÃΪÌṩDocker ClientÓëServerµÄͨÐÅЭÒéÒÔ¼°Í¨ÐŵØÖ·)¡¢tlsConfig(ͨ¹ýһϵÁÐflag²ÎÊý»ñµÃ£¬Èç*flTls¡¢*flTlsVerify£¬×÷ÓÃΪÌṩ°²È«´«Êä²ãЭÒéµÄ±£ÕÏ)¡£
Ëæ¼´·ÖÎö´¦ÀíÕâЩflag²ÎÊýÐÅÏ¢£¬ÒÔ¼°ÅäÖÃÐÅÏ¢¡£
ÔÚflag.Parse()Ö®ºóµÄ´úÂëÈçÏ£º
  1. if *flVersion {
  2.     showVersion()
  3.     return
  4.   }
¸´ÖÆ´úÂë


²»ÄÑÀí½âµÄÊÇ£¬µ±¾­¹ý½âÎöflag²ÎÊýºó£¬ÈôflVersion²ÎÊýΪÕæʱ£¬µ÷ÓÃshowVersion()ÏÔʾ°æ±¾ÐÅÏ¢£¬²¢´Ómainº¯ÊýÍ˳ö£»·ñÔòµÄ»°£¬¼ÌÐøÍùÏÂÖ´ÐС£
  1. if *flDebug {
  2.     os.Setenv("DEBUG", "1")
  3.   }
¸´ÖÆ´úÂë


ÈôflDebug²ÎÊýΪÕæµÄ»°£¬Í¨¹ýos°üµÄÖÐSetenvº¯Êý´´½¨Ò»¸öÃûΪDEBUGµÄϵͳ»·¾³±äÁ¿£¬²¢½«ÆäÖµÉèΪ¡±1¡±¡£¼ÌÐøÍùÏÂÖ´ÐС£
  1. if len(flHosts) == 0 {
  2.     defaultHost := os.Getenv("DOCKER_HOST")
  3.     if defaultHost == "" || *flDaemon {
  4.       // If we do not have a host, default to unix socket
  5.       defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
  6.     }
  7.     if _, err := api.ValidateHost(defaultHost); err != nil {
  8.       log.Fatal(err)
  9.     }
  10.     flHosts = append(flHosts, defaultHost)
  11.   }
¸´ÖÆ´úÂë

ÒÔÉϵÄÔ´ÂëÖ÷Òª·ÖÎöÄÚ²¿±äÁ¿flHosts¡£flHostsµÄ×÷ÓÃÊÇΪDocker ClientÌṩËùÒªÁ¬½ÓµÄhost¶ÔÏó£¬Ò²ÎªDocker ServerÌṩËùÒª¼àÌýµÄ¶ÔÏó¡£
·ÖÎö¹ý³ÌÖУ¬Ê×ÏÈÅжÏflHosts±äÁ¿ÊÇ·ñ³¤¶ÈΪ0£¬ÈôÊǵĻ°£¬Í¨¹ýos°ü»ñÈ¡ÃûΪDOCKER_HOST»·¾³±äÁ¿µÄÖµ£¬½«Æ丳ֵÓÚdefaultHost¡£ÈôdefaultHostΪ¿Õ»òÕßflDaemonΪÕæµÄ»°£¬ËµÃ÷Ä¿Ç°»¹Ã»ÓÐÒ»¸ö¶¨ÒåµÄhost¶ÔÏó£¬Ôò½«ÆäĬÈÏÉèÖÃΪunix socket£¬ÖµÎªapi.DEFAULTUNIXSOCKET£¬¸Ã³£Á¿Î»ÓÚ./docker/api/common.go£¬ÖµÎª"/var/run/docker.sock"£¬¹ÊdefaultHostΪ¡±unix:///var/run/docker.sock¡±¡£ÑéÖ¤¸ÃdefaultHostµÄºÏ·¨ÐÔÖ®ºó£¬½«defaultHostµÄÖµ×·¼ÓÖÁflHostµÄĩβ¡£¼ÌÐøÍùÏÂÖ´ÐС£

  1. if *flDaemon {
  2.     mainDaemon()
  3.     return
  4.   }
¸´ÖÆ´úÂë

ÈôflDaemon²ÎÊýΪÕæµÄ»°£¬ÔòÖ´ÐÐmainDaemonº¯Êý£¬ÊµÏÖDocker DaemonµÄÆô¶¯£¬ÈômainDaemonº¯ÊýÖ´ÐÐÍê±Ï£¬ÔòÍ˳ömainº¯Êý£¬Ò»°ãmainDaemonº¯Êý²»»áÖ÷¶¯ÖսᡣÓÉÓÚ±¾Õ½ڽéÉÜDocker ClientµÄÆô¶¯£¬¹Ê¼ÙÉèflDaemon²ÎÊýΪ¼Ù£¬²»Ö´ÐÐÒÔÉÏ´úÂë¿é¡£¼ÌÐøÍùÏÂÖ´ÐС£

  1. if len(flHosts) > 1 {
  2.     log.Fatal("Please specify only one -H")
  3.   }
  4.   protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
¸´ÖÆ´úÂë

ÒÔÉÏ£¬ÈôflHostsµÄ³¤¶È´óÓÚ1µÄ»°£¬ÔòÅ׳ö´íÎóÈÕÖ¾¡£½Ó׎«flHostsÕâ¸östringÊý×éÖеĵÚÒ»¸öÔªËØ£¬½øÐзָͨ¹ý¡±://¡±À´·Ö¸î£¬·Ö¸î³öµÄÁ½¸ö²¿·Ö·ÅÈë±äÁ¿protoAddrPartsÊý×éÖС£protoAddrPartsµÄ×÷ÓÃΪ½âÎö³öÓëDocker Server½¨Á¢Í¨ÐŵÄЭÒéÓëµØÖ·£¬ÎªDocker Client´´½¨¹ý³ÌÖв»¿É»òȱµÄÅäÖÃÐÅÏ¢Ö®Ò»¡£

  1. var (
  2.     cli       *client.DockerCli
  3.     tlsConfig tls.Config
  4.   )
  5. tlsConfig.InsecureSkipVerify = true
¸´ÖÆ´úÂë

ÓÉÓÚ֮ǰÒѾ­¼ÙÉè¹ýflDaemonΪ¼Ù£¬Ôò¿ÉÒÔÈ϶¨mainº¯ÊýµÄÔËÐÐÊÇΪÁËDocker ClientµÄ´´½¨ÓëÖ´ÐС£ÔÚÕâÀï´´½¨Á½¸ö±äÁ¿£ºÒ»¸öΪÀàÐÍÊÇclient.DockerCliÖ¸ÕëµÄ¶ÔÏócli£¬ÁíÒ»¸öΪÀàÐÍÊÇtls.ConfigµÄ¶ÔÏótlsConfig¡£²¢½«tlsConfigµÄInsecureSkipVerifyÊôÐÔÉèÖÃΪÕæ¡£TlsConfig¶ÔÏóµÄ´´½¨ÊÇΪÁ˱£ÕÏcliÔÚ´«ÊäÊý¾ÝµÄʱºò£¬×ñÑ­°²È«´«Êä²ãЭÒé(TLS)¡£°²È«´«Êä²ãЭÒé(TLS) ÓÃÓÚÁ½¸öͨÐÅÓ¦ÓóÌÐòÖ®¼ä±£ÃÜÐÔÓëÊý¾ÝÍêÕûÐÔ¡£tlsConfigÊÇDocker Client´´½¨¹ý³ÌÖпÉÑ¡µÄÅäÖÃÐÅÏ¢¡£

  1. // If we should verify the server, we need to load a trusted ca
  2.   if *flTlsVerify {
  3.     *flTls = true
  4.     certPool := x509.NewCertPool()
  5.     file, err := ioutil.ReadFile(*flCa)
  6.     if err != nil {
  7.       log.Fatalf("Couldn't read ca cert %s: %s", *flCa, err)
  8.     }
  9.     certPool.AppendCertsFromPEM(file)
  10.     tlsConfig.RootCAs = certPool
  11.     tlsConfig.InsecureSkipVerify = false
  12.   }
¸´ÖÆ´úÂë

ÈôflTlsVerifyÕâ¸öflag²ÎÊýΪÕæµÄ»°£¬Ôò˵Ã÷ÐèÒªÑéÖ¤server¶ËµÄ°²È«ÐÔ£¬tlsConfig¶ÔÏóÐèÒª¼ÓÔØÒ»¸öÊÜÐŵÄcaÎļþ¡£¸ÃcaÎļþµÄ·¾¶Îª*flCA²ÎÊýµÄÖµ£¬×îÖÕÍê³ÉtlsConfig¶ÔÏóÖÐRootCAsÊôÐԵĸ³Öµ£¬²¢½«InsecureSkipVerifyÊôÐÔÖÃΪ¼Ù¡£

  1. // If tls is enabled, try to load and send client certificates
  2.   if *flTls || *flTlsVerify {
  3.     _, errCert := os.Stat(*flCert)
  4.     _, errKey := os.Stat(*flKey)
  5.     if errCert == nil && errKey == nil {
  6.       *flTls = true
  7.       cert, err := tls.LoadX509KeyPair(*flCert, *flKey)
  8.       if err != nil {
  9.         log.Fatalf("Couldn't load X509 key pair: %s. Key encrypted?", err)
  10.       }
  11.       tlsConfig.Certificates = []tls.Certificate{cert}
  12.     }
  13.   }
¸´ÖÆ´úÂë

Èç¹ûflTlsºÍflTlsVerifyÁ½¸öflag²ÎÊýÖÐÓÐÒ»¸öΪÕ棬Ôò˵Ã÷ÐèÒª¼ÓÔØÒÔ¼°·¢ËÍclient¶ËµÄÖ¤Êé¡£×îÖÕ½«Ö¤ÊéÄÚÈݽ»¸øtlsConfigµÄCertificatesÊôÐÔ¡£
ÖÁ´Ë£¬flag²ÎÊýÒѾ­È«²¿´¦Àí£¬²¢ÒѾ­ÊÕ¼¯Íê±ÏDocker ClientËùÐèµÄÅäÖÃÐÅÏ¢¡£Ö®ºóµÄÄÚÈÝΪDocker ClientÈçºÎʵÏÖ´´½¨²¢Ö´ÐС£

2.3. Docker ClientµÄ´´½¨

Docker ClientµÄ´´½¨Æäʵ¾ÍÊÇÔÚÒÑÓÐÅäÖòÎÊýÐÅÏ¢µÄÇé¿ö£¬Í¨¹ýClient°üÖеÄNewDockerCli·½·¨´´½¨Ò»¸öʵÀýcli£¬Ô´ÂëʵÏÖÈçÏ£º

  1. if *flTls || *flTlsVerify {
  2.     cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
  3.   } else {
  4.     cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil)
  5.   }
¸´ÖÆ´úÂë

Èç¹ûflag²ÎÊýflTlsΪÕæ»òÕßflTlsVerifyΪÕæµÄ»°£¬Ôò˵Ã÷ÐèҪʹÓÃTLSЭÒéÀ´±£ÕÏ´«ÊäµÄ°²È«ÐÔ£¬¹Ê´´½¨Docker ClientµÄʱºò£¬½«TlsConfig²ÎÊý´«È룻·ñÔòµÄ»°£¬Í¬Ñù´´½¨Docker Client£¬Ö»²»¹ýTlsConfigΪnil¡£
¹ØÓÚClient°üÖеÄNewDockerCliº¯ÊýµÄʵÏÖ£¬¿ÉÒÔ¾ßÌå²Î¼û./docker/api/client/cli.go¡£

  1. func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
  2.   var (
  3.     isTerminal = false
  4.     terminalFd uintptr
  5.     scheme     = "http"
  6.   )
  7.   if tlsConfig != nil {
  8.     scheme = "https"
  9.   }
  10.   if in != nil {
  11.     if file, ok := out.(*os.File); ok {
  12.       terminalFd = file.Fd()
  13.       isTerminal = term.IsTerminal(terminalFd)
  14.     }
  15.   }
  16.   if err == nil {
  17.     err = out
  18.   }
  19.   return &DockerCli{
  20.     proto:      proto,
  21.     addr:       addr,
  22.     in:         in,
  23.     out:        out,
  24.     err:        err,
  25.     isTerminal: isTerminal,
  26.     terminalFd: terminalFd,
  27.     tlsConfig:  tlsConfig,
  28.     scheme:     scheme,
  29.   }
  30. }
¸´ÖÆ´úÂë

×ÜÌå¶øÑÔ£¬´´½¨DockerCli¶ÔÏó½ÏΪ¼òµ¥£¬½ÏΪÖØÒªµÄDockerCliµÄÊôÐÔÓÐproto£º´«ÊäЭÒ飻addr£ºhostµÄÄ¿±êµØÖ·£¬tlsConfig£º°²È«´«Êä²ãЭÒéµÄÅäÖá£ÈôtlsConfigΪ²»Îª¿Õ£¬Ôò˵Ã÷ÐèҪʹÓð²È«´«Êä²ãЭÒ飬DockerCli¶ÔÏóµÄschemeÉèÖÃΪ¡°https¡±£¬ÁíÍ⻹ÓйØÓÚÊäÈ룬Êä³öÒÔ¼°´íÎóÏÔʾµÄÅäÖã¬×îÖÕ·µ»Ø¸Ã¶ÔÏó¡£

ͨ¹ýµ÷ÓÃNewDockerCliº¯Êý£¬³ÌÐò×îÖÕÍê³ÉÁË´´½¨Docker Client£¬²¢·µ»Ømainº¯Êý¼ÌÐøÖ´ÐС£

3. DockerÃüÁîÖ´ÐÐ
mainº¯ÊýÖ´Ðе½Ä¿Ç°ÎªÖ¹£¬ÓÐÒÔÏÂÄÚÈÝÐèҪΪDockerÃüÁîµÄÖ´ÐзþÎñ£º´´½¨Íê±ÏµÄDocker Client£¬dockerÃüÁîÖеÄÇëÇó²ÎÊý£¨¾­flag½âÎöºó´æ·ÅÓÚflag.Arg()£©¡£Ò²¾ÍÊÇ˵£¬ÐèҪʹÓÃDocker ClientÀ´·ÖÎödocker ÃüÁîÖеÄÇëÇó²ÎÊý£¬²¢×îÖÕ·¢ËÍÏàÓ¦ÇëÇó¸øDocker Server¡£

3.1. Docker Client½âÎöÇëÇóÃüÁî
Docker Client½âÎöÇëÇóÃüÁîµÄ¹¤×÷£¬ÔÚDockerÃüÁîÖ´Ðв¿·ÖµÚÒ»¸öÍê³É£¬Ö±½Ó½øÈëmainº¯ÊýÖ®ºóµÄÔ´Â벿·Ö£º
  1. if err := cli.Cmd(flag.Args()...); err != nil {
  2.     if sterr, ok := err.(*utils.StatusError); ok {
  3.       if sterr.Status != "" {
  4.         log.Println(sterr.Status)
  5.       }
  6.       os.Exit(sterr.StatusCode)
  7.     }
  8.     log.Fatal(err)
  9.   }
¸´ÖÆ´úÂë


²éÔÄÒÔÉÏÔ´Â룬¿ÉÒÔ·¢ÏÖ£¬ÕýÈç֮ǰËù˵£¬Ê×ÏȽâÎö´æ·ÅÓÚflag.Args()ÖеľßÌåÇëÇó²ÎÊý£¬Ö´Ðеĺ¯ÊýΪcli¶ÔÏóµÄCmdº¯Êý¡£½øÈë
./docker/api/client/cli.goµÄCmdº¯Êý£º

  1. // Cmd executes the specified command
  2. func (cli *DockerCli) Cmd(args ...string) error {
  3.   if len(args) > 0 {
  4.     method, exists := cli.getMethod(args[0])
  5.     if !exists {
  6.       fmt.Println("Error: Command not found:", args[0])
  7.       return cli.CmdHelp(args[1:]...)
  8.     }
  9.     return method(args[1:]...)
  10.   }
  11.   return cli.CmdHelp(args...)
  12. }
¸´ÖÆ´úÂë

ÓÉ´úÂë×¢ÊÍ¿ÉÖª£¬Cmdº¯ÊýÖ´ÐоßÌåµÄÖ¸Áî¡£Ô´ÂëʵÏÖÖУ¬Ê×ÏÈÅжÏÇëÇó²ÎÊýÁбíµÄ³¤¶ÈÊÇ·ñ´óÓÚ0£¬Èô²»ÊǵĻ°£¬ËµÃ÷ûÓÐÇëÇóÐÅÏ¢£¬·µ»ØdockerÃüÁîµÄHelpÐÅÏ¢£»Èô³¤¶È´óÓÚ0µÄ»°£¬ËµÃ÷ÓÐÇëÇóÐÅÏ¢£¬ÔòÊ×ÏÈͨ¹ýÇëÇó²ÎÊýÁбíÖеĵÚÒ»¸öÔªËØargs[0]À´»ñÈ¡¾ßÌåµÄmethodµÄ·½·¨¡£Èç¹ûÉÏÊömethod·½·¨²»´æÔÚ£¬Ôò·µ»ØdockerÃüÁîµÄHelpÐÅÏ¢£¬Èô´æÔڵĻ°£¬µ÷ÓþßÌåµÄmethod·½·¨£¬²ÎÊýΪargs[1]¼°ÆäÖ®ºóËùÓеÄÇëÇó²ÎÊý¡£
»¹ÊÇÒÔÒ»¸ö¾ßÌåµÄdockerÃüÁîΪÀý£¬docker ¨Cdaemon=false ¨Cversion=false pull Name¡£Í¨¹ýÒÔÉϵķÖÎö£¬¿ÉÒÔ×ܽá³öÒÔϲÙ×÷Á÷³Ì£º
(1) ½âÎöflag²ÎÊýÖ®ºó£¬½«dockerÇëÇó²ÎÊý¡±pull¡±ºÍ¡°Name¡±´æ·ÅÓÚflag.Args();
(2) ´´½¨ºÃµÄDocker ClientΪcli£¬cliÖ´ÐÐcli.Cmd(flag.Args()¡­);
     ÔÚCmdº¯ÊýÖУ¬Í¨¹ýargs[0]Ò²¾ÍÊÇ¡±pull¡±,Ö´ÐÐcli.getMethod(args[0])£¬»ñÈ¡methodµÄÃû³Æ£»
(3) ÔÚgetMothod·½·¨ÖУ¬Í¨¹ý´¦Àí×îÖÕ·µ»ØmethodµÄֵΪ¡±CmdPull¡±;
(4) ×îÖÕÖ´ÐÐmethod(args[1:]¡­)Ò²¾ÍÊÇCmdPull(args[1:]¡­)¡£

3.2. Docker ClientÖ´ÐÐÇëÇóÃüÁî
ÉÏÒ»½Úͨ¹ýһϵÁеÄÃüÁî½âÎö£¬×îÖÕÕÒµ½Á˾ßÌåµÄÃüÁîµÄÖ´Ðз½·¨£¬±¾½ÚÄÚÈÝÖ÷Òª½éÉÜDocker ClientÈçºÎͨ¹ý¸ÃÖ´Ðз½·¨´¦Àí²¢·¢ËÍÇëÇó¡£
ÓÉÓÚ²»Í¬µÄÇëÇóÄÚÈݲ»Í¬£¬Ö´ÐÐÁ÷³Ì´óÖÂÏàͬ£¬±¾½ÚÒÀ¾ÉÒÔÒ»¸öÀý×ÓÀ´²ûÊöÆäÖеÄÁ÷³Ì£¬Àý×ÓΪ£ºdocker pull NAME¡£
Docker ClientÔÚÖ´ÐÐÒÔÉÏÇëÇóÃüÁîµÄʱºò£¬»áÖ´ÐÐCmdPullº¯Êý£¬´«Èë²ÎÊýΪargs[1:]...¡£Ô´Âë¾ßÌåΪ./docker/api/client/command.goÖеÄCmdPullº¯Êý¡£
ÒÔÏÂÖðÒ»·ÖÎöCmdPullµÄÔ´ÂëʵÏÖ¡£


(1) ͨ¹ýcli°üÖеÄSubcmd·½·¨¶¨ÒåÒ»¸öÀàÐÍΪFlagsetµÄ¶ÔÏócmd¡£
  1. cmd := cli.Subcmd("pull", "NAME[:TAG]", "Pull an image or a repository from the registry")
¸´ÖÆ´úÂë


(2)
¸øcmd¶ÔÏó¶¨ÒåÒ»¸öÀàÐÍΪStringµÄflag£¬ÃûΪ¡±#t¡±»ò¡±#-tag¡±£¬³õʼֵΪ¿Õ¡£
  1. tag := cmd.String([]string{"#t", "#-tag"}, "", "Download tagged image in a repository")
¸´ÖÆ´úÂë


(3)
½«args²ÎÊý½øÐнâÎö£¬½âÎö¹ý³ÌÖУ¬ÏÈÌáÈ¡³öÊÇ·ñÓзûºÏtagÕâ¸öflagµÄ²ÎÊý£¬ÈôÓУ¬½«Æä¸ø¸³Öµ¸øtag²ÎÊý£¬ÆäÓàµÄ²ÎÊý´æÈëcmd.NArg();ÈôÎ޵Ļ°£¬ËùÓеIJÎÊý´æÈëcmd.NArg()ÖС£
  1. if err := cmd.Parse(args); err != nil {
  2. return nil }
¸´ÖÆ´úÂë

(4) ÅжϾ­¹ýflag½âÎöºóµÄ²ÎÊýÁÐ±í£¬Èô²ÎÊýÁбíÖвÎÊýµÄ¸öÊý²»Îª1£¬Ôò˵Ã÷ÐèÒªpull¶à¸öimage£¬pullÃüÁî²»Ö§³Ö£¬Ôòµ÷ÓôíÎó´¦Àí·½·¨cmd.Usage()£¬²¢·µ»Ønil¡£
  1. if cmd.NArg() != 1 {
  2. cmd.Usage()
  3. return nil
  4.     }
¸´ÖÆ´úÂë

(5) ´´½¨Ò»¸ömapÀàÐ͵ıäÁ¿v£¬¸Ã±äÁ¿ÓÃÓÚ´æ·Åpull¾µÏñʱËùÐèµÄurl²ÎÊý£»Ëæºó½«²ÎÊýÁбíµÄµÚÒ»¸öÖµ¸³¸øremote±äÁ¿£¬²¢½«remote×÷Ϊ¼üΪfromImageµÄÖµÌí¼ÓÖÁv£»×îºóÈôÓÐtagÐÅÏ¢µÄ»°£¬½«tagÐÅÏ¢×÷Ϊ¼üΪ¡±tag¡±µÄÖµÌí¼ÓÖÁv¡£
  1. var (
  2.   v      = url.Values{}
  3.   remote = cmd.Arg(0)
  4. )
  5. v.Set("fromImage", remote)
  6. if *tag == "" {
  7.   v.Set("tag", *tag)
  8. }
¸´ÖÆ´úÂë

(6) ͨ¹ýremote±äÁ¿½âÎö³ö¾µÏñËùÔÚµÄhostµØÖ·£¬ÒÔ¼°¾µÏñµÄÃû³Æ¡£
  1. remote, _ = parsers.ParseRepositoryTag(remote)
  2.     // Resolve the Repository name from fqn to hostname + name
  3.     hostname, _, err := registry.ResolveRepositoryName(remote)
  4.     if err != nil {
  5.       return err
  6.     }
¸´ÖÆ´úÂë

(7) ͨ¹ýcli¶ÔÏó»ñÈ¡ÓëDocker ServerͨÐÅËùÐèÒªµÄÈÏÖ¤ÅäÖÃÐÅÏ¢¡£
  1. cli.LoadConfigFile()
  2.     // Resolve the Auth config relevant for this server
  3.     authConfig := cli.configFile.ResolveAuthConfig(hostname)
¸´ÖÆ´úÂë

(8) ¶¨ÒåÒ»¸öÃûΪpullµÄº¯Êý£¬´«ÈëµÄ²ÎÊýÀàÐÍΪregistry.AuthConfig£¬·µ»ØÀàÐÍΪerror¡£º¯ÊýÖ´ÐпéÖÐ×îÖ÷ÒªµÄÄÚÈÝΪ£ºcli.stream(¡­¡­)²¿·Ö¡£¸Ã²¿·Ö¾ßÌå·¢ÆðÁËÒ»¸ö¸øDocker ServerµÄPOSTÇëÇó£¬ÇëÇóµÄurlΪ"/images/create?"+v.Encode()£¬ÇëÇóµÄÈÏÖ¤ÐÅϢΪ£ºmap[string][]string{"X-Registry-Auth": registryAuthHeader,}¡£
  1. pull := func(authConfig registry.AuthConfig) error {
  2.       buf, err := json.Marshal(authConfig)
  3.       if err != nil {
  4.         return err
  5.       }
  6.       registryAuthHeader := []string{
  7.         base64.URLEncoding.EncodeToString(buf),
  8.       }
  9.       return cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.out, map[string][]string{
  10.       "  X-Registry-Auth": registryAuthHeader,
  11.       })
  12.     }
¸´ÖÆ´úÂë

(9) ÓÉÓÚÉÏÒ»¸ö²½ÖèÖ»ÊǶ¨Òåpullº¯Êý£¬ÕâÒ»²½Öè¾ßÌåµ÷ÓÃÖ´ÐÐpullº¯Êý£¬Èô³É¹¦Ôò×îÖÕ·µ»Ø£¬Èô·µ»Ø´íÎó£¬Ôò×öÏàÓ¦µÄ´íÎó´¦Àí¡£Èô·µ»Ø´íÎóΪ401£¬ÔòÐèÒªÏȵǼ£¬×ªÖÁµÇ¼»·½Ú£¬Íê³ÉÖ®ºó£¬¼ÌÐøÖ´ÐÐpullº¯Êý£¬ÈôÍê³ÉÔò×îÖÕ·µ»Ø¡£
  1. if err := pull(authConfig); err != nil {
  2.   if strings.Contains(err.Error(), "Status 401") {
  3.     fmt.Fprintln(cli.out, "\nPlease login prior to pull:")
  4.     if err := cli.CmdLogin(hostname); err != nil {
  5.       return err
  6.     }
  7.         authConfig := cli.configFile.ResolveAuthConfig(hostname)
  8.         return pull(authConfig)
  9.   }
  10.   return err
  11. }
¸´ÖÆ´úÂë

ÒÔÉϱãÊÇpullÇëÇóµÄÈ«²¿Ö´Ðйý³Ì£¬ÆäËûÇëÇóµÄÖ´ÐÐÔÚÁ÷³ÌÉÏÒ²ÊÇ´óͬСÒì¡£×ÜÖ®£¬ÇëÇóÖ´Ðйý³ÌÖУ¬´ó¶à¶¼Êǽ«ÃüÁîÐÐÖйØÓÚÇëÇóµÄ²ÎÊý½øÐгõ²½´¦Àí£¬²¢Ìí¼ÓÏàÓ¦µÄ¸¨ÖúÐÅÏ¢£¬×îÖÕͨ¹ýÖ¸¶¨µÄЭÒé¸øDocker Server·¢ËÍDocker ClientºÍDocker ServerÔ¼¶¨ºÃµÄAPIÇëÇó¡£


4. ×ܽá
±¾ÎÄ´ÓÔ´ÂëµÄ½Ç¶È·ÖÎöÁË´Ódocker¿ÉÖ´ÐÐÎļþ¿ªÊ¼£¬µ½´´½¨Docker Client£¬×îÖÕ·¢Ë͸øDocker ServerÇëÇóµÄÍêÕû¹ý³Ì¡£

±ÊÕßÈÏΪ£¬Ñ§Ï°ÓëÀí½âDocker ClientÏà¹ØµÄÔ´ÂëʵÏÖ£¬²»½ö¿ÉÒÔÈÃÓû§ÊìÁ·ÕÆÎÕDockerÃüÁîµÄʹÓ㬻¹¿ÉÒÔʹµÃÓû§ÔÚÌØÊâÇé¿öÏÂÓÐÄÜÁ¦ÐÞ¸ÄDocker ClientµÄÔ´Â룬ʹÆäÂú×ã×ÔÉíϵͳµÄijЩÌØÊâÐèÇó£¬ÒÔ´ïµ½¶¨ÖÆDocker ClientµÄÄ¿µÄ£¬×î´ó·¢»ÓDocker¿ª·Å˼ÏëµÄ¼ÛÖµ¡£

ÒÑÓÐ(3)ÈËÆÀÂÛ

Ìøתµ½Ö¸¶¨Â¥²ã
º«¿ËÀ­Â꺮 ·¢±íÓÚ 2014-10-13 09:16:57
¸Ðл¥Ö÷µÄϸÐÄ·ÖÏí
»Ø¸´

ʹÓõÀ¾ß ¾Ù±¨

hb1984 ·¢±íÓÚ 2014-10-15 16:19:04
¸Ðл¥Ö÷·ÖÏí
»Ø¸´

ʹÓõÀ¾ß ¾Ù±¨

hb1984 ·¢±íÓÚ 2014-10-15 17:01:54
¿´Á˼¸ÐУ¬¿´²»ÏÂÈ¥ÁË¡£
»Ø¸´

ʹÓõÀ¾ß ¾Ù±¨

ÄúÐèÒªµÇ¼ºó²Å¿ÉÒÔ»ØÌû µÇ¼ | Á¢¼´×¢²á

±¾°æ»ý·Ö¹æÔò

¹Ø±Õ

ÍƼöÉÏÒ»Ìõ /2 ÏÂÒ»Ìõ