±¾Ìû×îºóÓÉ 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 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º¯Êý´úÂëÈçÏ£º
func main() {
if reexec.Init() {
return
}
flag.Parse()
// FIXME: validate daemon flags here
¡¡
} ¸´ÖÆ´úÂë
ÔÚÒÔÉÏ´úÂëÖУ¬Ê×ÏÈÅжÏreexec.Init()·½·¨µÄ·µ»ØÖµ£¬ÈôΪÕ棬ÔòÖ±½ÓÍ˳öÔËÐУ¬·ñÔòµÄ»°¼ÌÐøÖ´ÐС£²é¿´Î»ÓÚ./docker/reexec/reexec.goÖÐreexec.Init() µÄ¶¨Ò壬¿ÉÒÔ·¢ÏÖÓÉÓÚÔÚdockerÔËÐÐ֮ǰûÓÐÈκεÄInitializer×¢²á£¬¹Ê¸Ã´úÂë¶ÎÖ´Ðеķµ»ØֵΪ¼Ù¡£
½ô½Ó×Å£¬mainº¯Êýͨ¹ýµ÷ÓÃflag.Parse()½âÎöÃüÁîÐÐÖеÄflag²ÎÊý¡£²é¿´Ô´Âë¿ÉÒÔ·¢ÏÖDockerÔÚ./docker/docker/flag.go Öж¨ÒåÁ˶à¸öflag²ÎÊý£¬²¢Í¨¹ýinitº¯Êý½øÐгõʼ»¯¡£´úÂëÈçÏ£º
var (
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
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")
flEnableCors = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
flTls = flag.Bool([]string{"-tls"}, false, "Use TLS; implied by tls-verify flags")
flTlsVerify = flag.Bool([]string{"-tlsverify"}, false, "Use TLS and verify the remote (daemon: verify client, client: verify daemon)")
// these are initialized in init() below since their default values depend on dockerCertPath which isn't fully initialized until init() runs
flCa *string
flCert *string
flKey *string
flHosts []string
)
func init() {
flCa = flag.String([]string{"-tlscacert"}, filepath.Join(dockerCertPath, defaultCaFile), "Trust only remotes providing a certificate signed by the CA given here")
flCert = flag.String([]string{"-tlscert"}, filepath.Join(dockerCertPath, defaultCertFile), "Path to TLS certificate file")
flKey = flag.String([]string{"-tlskey"}, filepath.Join(dockerCertPath, defaultKeyFile), "Path to TLS key file")
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.")
} ¸´ÖÆ´úÂë
ÕâÀïÉæ¼°µ½ÁË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()Ö®ºóµÄ´úÂëÈçÏ£º
if *flVersion {
showVersion()
return
} ¸´ÖÆ´úÂë
²»ÄÑÀí½âµÄÊÇ£¬µ±¾¹ý½âÎöflag²ÎÊýºó£¬ÈôflVersion²ÎÊýΪÕæʱ£¬µ÷ÓÃshowVersion()ÏÔʾ°æ±¾ÐÅÏ¢£¬²¢´Ómainº¯ÊýÍ˳ö£»·ñÔòµÄ»°£¬¼ÌÐøÍùÏÂÖ´ÐС£
if *flDebug {
os.Setenv("DEBUG", "1")
} ¸´ÖÆ´úÂë
ÈôflDebug²ÎÊýΪÕæµÄ»°£¬Í¨¹ýos°üµÄÖÐSetenvº¯Êý´´½¨Ò»¸öÃûΪDEBUGµÄϵͳ»·¾³±äÁ¿£¬²¢½«ÆäÖµÉèΪ¡±1¡±¡£¼ÌÐøÍùÏÂÖ´ÐС£
if len(flHosts) == 0 {
defaultHost := os.Getenv("DOCKER_HOST")
if defaultHost == "" || *flDaemon {
// If we do not have a host, default to unix socket
defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
}
if _, err := api.ValidateHost(defaultHost); err != nil {
log.Fatal(err)
}
flHosts = append(flHosts, defaultHost)
} ¸´ÖÆ´úÂë
ÒÔÉϵÄÔ´ÂëÖ÷Òª·ÖÎöÄÚ²¿±äÁ¿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µÄĩβ¡£¼ÌÐøÍùÏÂÖ´ÐС£
if *flDaemon {
mainDaemon()
return
} ¸´ÖÆ´úÂë
ÈôflDaemon²ÎÊýΪÕæµÄ»°£¬ÔòÖ´ÐÐmainDaemonº¯Êý£¬ÊµÏÖDocker DaemonµÄÆô¶¯£¬ÈômainDaemonº¯ÊýÖ´ÐÐÍê±Ï£¬ÔòÍ˳ömainº¯Êý£¬Ò»°ãmainDaemonº¯Êý²»»áÖ÷¶¯ÖսᡣÓÉÓÚ±¾Õ½ڽéÉÜDocker ClientµÄÆô¶¯£¬¹Ê¼ÙÉèflDaemon²ÎÊýΪ¼Ù£¬²»Ö´ÐÐÒÔÉÏ´úÂë¿é¡£¼ÌÐøÍùÏÂÖ´ÐС£
if len(flHosts) > 1 {
log.Fatal("Please specify only one -H")
}
protoAddrParts := strings.SplitN(flHosts[0], "://", 2) ¸´ÖÆ´úÂë
ÒÔÉÏ£¬ÈôflHostsµÄ³¤¶È´óÓÚ1µÄ»°£¬ÔòÅ׳ö´íÎóÈÕÖ¾¡£½Ó׎«flHostsÕâ¸östringÊý×éÖеĵÚÒ»¸öÔªËØ£¬½øÐзָͨ¹ý¡±://¡±À´·Ö¸î£¬·Ö¸î³öµÄÁ½¸ö²¿·Ö·ÅÈë±äÁ¿protoAddrPartsÊý×éÖС£protoAddrPartsµÄ×÷ÓÃΪ½âÎö³öÓëDocker Server½¨Á¢Í¨ÐŵÄÐÒéÓëµØÖ·£¬ÎªDocker Client´´½¨¹ý³ÌÖв»¿É»òȱµÄÅäÖÃÐÅÏ¢Ö®Ò»¡£
var (
cli *client.DockerCli
tlsConfig tls.Config
)
tlsConfig.InsecureSkipVerify = true ¸´ÖÆ´úÂë
ÓÉÓÚ֮ǰÒѾ¼ÙÉè¹ýflDaemonΪ¼Ù£¬Ôò¿ÉÒÔÈ϶¨mainº¯ÊýµÄÔËÐÐÊÇΪÁËDocker ClientµÄ´´½¨ÓëÖ´ÐС£ÔÚÕâÀï´´½¨Á½¸ö±äÁ¿£ºÒ»¸öΪÀàÐÍÊÇclient.DockerCliÖ¸ÕëµÄ¶ÔÏócli£¬ÁíÒ»¸öΪÀàÐÍÊÇtls.ConfigµÄ¶ÔÏótlsConfig¡£²¢½«tlsConfigµÄInsecureSkipVerifyÊôÐÔÉèÖÃΪÕæ¡£TlsConfig¶ÔÏóµÄ´´½¨ÊÇΪÁ˱£ÕÏcliÔÚ´«ÊäÊý¾ÝµÄʱºò£¬×ñÑ°²È«´«Êä²ãÐÒé(TLS)¡£°²È«´«Êä²ãÐÒé(TLS) ÓÃÓÚÁ½¸öͨÐÅÓ¦ÓóÌÐòÖ®¼ä±£ÃÜÐÔÓëÊý¾ÝÍêÕûÐÔ¡£tlsConfigÊÇDocker Client´´½¨¹ý³ÌÖпÉÑ¡µÄÅäÖÃÐÅÏ¢¡£
// 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
} ¸´ÖÆ´úÂë
ÈôflTlsVerifyÕâ¸öflag²ÎÊýΪÕæµÄ»°£¬Ôò˵Ã÷ÐèÒªÑéÖ¤server¶ËµÄ°²È«ÐÔ£¬tlsConfig¶ÔÏóÐèÒª¼ÓÔØÒ»¸öÊÜÐŵÄcaÎļþ¡£¸ÃcaÎļþµÄ·¾¶Îª*flCA²ÎÊýµÄÖµ£¬×îÖÕÍê³ÉtlsConfig¶ÔÏóÖÐRootCAsÊôÐԵĸ³Öµ£¬²¢½«InsecureSkipVerifyÊôÐÔÖÃΪ¼Ù¡£
// 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}
}
} ¸´ÖÆ´úÂë
Èç¹ûflTlsºÍflTlsVerifyÁ½¸öflag²ÎÊýÖÐÓÐÒ»¸öΪÕ棬Ôò˵Ã÷ÐèÒª¼ÓÔØÒÔ¼°·¢ËÍclient¶ËµÄÖ¤Êé¡£×îÖÕ½«Ö¤ÊéÄÚÈݽ»¸øtlsConfigµÄCertificatesÊôÐÔ¡£
ÖÁ´Ë£¬flag²ÎÊýÒѾȫ²¿´¦Àí£¬²¢ÒѾÊÕ¼¯Íê±ÏDocker ClientËùÐèµÄÅäÖÃÐÅÏ¢¡£Ö®ºóµÄÄÚÈÝΪDocker ClientÈçºÎʵÏÖ´´½¨²¢Ö´ÐС£
2.3. Docker ClientµÄ´´½¨
Docker ClientµÄ´´½¨Æäʵ¾ÍÊÇÔÚÒÑÓÐÅäÖòÎÊýÐÅÏ¢µÄÇé¿ö£¬Í¨¹ýClient°üÖеÄNewDockerCli·½·¨´´½¨Ò»¸öʵÀýcli£¬Ô´ÂëʵÏÖÈçÏ£º
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)
} ¸´ÖÆ´úÂë
Èç¹ûflag²ÎÊýflTlsΪÕæ»òÕßflTlsVerifyΪÕæµÄ»°£¬Ôò˵Ã÷ÐèҪʹÓÃTLSÐÒéÀ´±£ÕÏ´«ÊäµÄ°²È«ÐÔ£¬¹Ê´´½¨Docker ClientµÄʱºò£¬½«TlsConfig²ÎÊý´«È룻·ñÔòµÄ»°£¬Í¬Ñù´´½¨Docker Client£¬Ö»²»¹ýTlsConfigΪnil¡£
¹ØÓÚClient°üÖеÄNewDockerCliº¯ÊýµÄʵÏÖ£¬¿ÉÒÔ¾ßÌå²Î¼û./docker/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¡±£¬ÁíÍ⻹ÓйØÓÚÊäÈ룬Êä³öÒÔ¼°´íÎóÏÔʾµÄÅäÖã¬×îÖÕ·µ»Ø¸Ã¶ÔÏó¡£
ͨ¹ýµ÷ÓÃ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º¯ÊýÖ®ºóµÄÔ´Â벿·Ö £º
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)
} ¸´ÖÆ´úÂë
²éÔÄÒÔÉÏÔ´Â룬¿ÉÒÔ·¢ÏÖ£¬ÕýÈç֮ǰËù˵£¬Ê×ÏȽâÎö´æ·ÅÓÚflag.Args()ÖеľßÌåÇëÇó²ÎÊý£¬Ö´Ðеĺ¯ÊýΪcli¶ÔÏóµÄCmdº¯Êý¡£½øÈë./docker/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º¯ÊýÖ´ÐоßÌåµÄÖ¸Áî¡£Ô´ÂëʵÏÖÖУ¬Ê×ÏÈÅжÏÇëÇó²ÎÊýÁбíµÄ³¤¶ÈÊÇ·ñ´óÓÚ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¡£
cmd := cli.Subcmd("pull", "NAME[:TAG]", "Pull an image or a repository from the registry") ¸´ÖÆ´úÂë
(2) ¸øcmd¶ÔÏó¶¨ÒåÒ»¸öÀàÐÍΪStringµÄflag£¬ÃûΪ¡±#t¡±»ò¡±#-tag¡±£¬³õʼֵΪ¿Õ¡£
tag := cmd.String([]string{"#t", "#-tag"}, "", "Download tagged image in a repository") ¸´ÖÆ´úÂë
(3) ½«args²ÎÊý½øÐнâÎö£¬½âÎö¹ý³ÌÖУ¬ÏÈÌáÈ¡³öÊÇ·ñÓзûºÏtagÕâ¸öflagµÄ²ÎÊý£¬ÈôÓУ¬½«Æä¸ø¸³Öµ¸øtag²ÎÊý£¬ÆäÓàµÄ²ÎÊý´æÈëcmd.NArg();ÈôÎ޵Ļ°£¬ËùÓеIJÎÊý´æÈëcmd.NArg()ÖС£
if err := cmd.Parse(args); err != nil {
return nil } ¸´ÖÆ´úÂë
(4) ÅжϾ¹ýflag½âÎöºóµÄ²ÎÊýÁÐ±í£¬Èô²ÎÊýÁбíÖвÎÊýµÄ¸öÊý²»Îª1£¬Ôò˵Ã÷ÐèÒªpull¶à¸öimage£¬pullÃüÁî²»Ö§³Ö£¬Ôòµ÷ÓôíÎó´¦Àí·½·¨cmd.Usage()£¬²¢·µ»Ønil¡£
if cmd.NArg() != 1 {
cmd.Usage()
return nil
} ¸´ÖÆ´úÂë
(5) ´´½¨Ò»¸ömapÀàÐ͵ıäÁ¿v£¬¸Ã±äÁ¿ÓÃÓÚ´æ·Åpull¾µÏñʱËùÐèµÄurl²ÎÊý£»Ëæºó½«²ÎÊýÁбíµÄµÚÒ»¸öÖµ¸³¸øremote±äÁ¿£¬²¢½«remote×÷Ϊ¼üΪfromImageµÄÖµÌí¼ÓÖÁv£»×îºóÈôÓÐtagÐÅÏ¢µÄ»°£¬½«tagÐÅÏ¢×÷Ϊ¼üΪ¡±tag¡±µÄÖµÌí¼ÓÖÁv¡£
var (
v = url.Values{}
remote = cmd.Arg(0)
)
v.Set("fromImage", remote)
if *tag == "" {
v.Set("tag", *tag)
} ¸´ÖÆ´úÂë
(6) ͨ¹ýremote±äÁ¿½âÎö³ö¾µÏñËùÔÚµÄhostµØÖ·£¬ÒÔ¼°¾µÏñµÄÃû³Æ¡£
remote, _ = parsers.ParseRepositoryTag(remote)
// Resolve the Repository name from fqn to hostname + name
hostname, _, err := registry.ResolveRepositoryName(remote)
if err != nil {
return err
} ¸´ÖÆ´úÂë
(7) ͨ¹ýcli¶ÔÏó»ñÈ¡ÓëDocker ServerͨÐÅËùÐèÒªµÄÈÏÖ¤ÅäÖÃÐÅÏ¢¡£
cli.LoadConfigFile()
// Resolve the Auth config relevant for this server
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,}¡£
pull := func(authConfig registry.AuthConfig) error {
buf, err := json.Marshal(authConfig)
if err != nil {
return err
}
registryAuthHeader := []string{
base64.URLEncoding.EncodeToString(buf),
}
return cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.out, map[string][]string{
" X-Registry-Auth": registryAuthHeader,
})
} ¸´ÖÆ´úÂë
(9) ÓÉÓÚÉÏÒ»¸ö²½ÖèÖ»ÊǶ¨Òåpullº¯Êý£¬ÕâÒ»²½Öè¾ßÌåµ÷ÓÃÖ´ÐÐpullº¯Êý£¬Èô³É¹¦Ôò×îÖÕ·µ»Ø£¬Èô·µ»Ø´íÎó£¬Ôò×öÏàÓ¦µÄ´íÎó´¦Àí¡£Èô·µ»Ø´íÎóΪ401£¬ÔòÐèÒªÏȵǼ£¬×ªÖÁµÇ¼»·½Ú£¬Íê³ÉÖ®ºó£¬¼ÌÐøÖ´ÐÐpullº¯Êý£¬ÈôÍê³ÉÔò×îÖÕ·µ»Ø¡£
if err := pull(authConfig); err != nil {
if strings.Contains(err.Error(), "Status 401") {
fmt.Fprintln(cli.out, "\nPlease login prior to pull:")
if err := cli.CmdLogin(hostname); err != nil {
return err
}
authConfig := cli.configFile.ResolveAuthConfig(hostname)
return pull(authConfig)
}
return err
} ¸´ÖÆ´úÂë
ÒÔÉϱãÊÇpullÇëÇóµÄÈ«²¿Ö´Ðйý³Ì£¬ÆäËûÇëÇóµÄÖ´ÐÐÔÚÁ÷³ÌÉÏÒ²ÊÇ´óͬСÒì¡£×ÜÖ®£¬ÇëÇóÖ´Ðйý³ÌÖУ¬´ó¶à¶¼Êǽ«ÃüÁîÐÐÖйØÓÚÇëÇóµÄ²ÎÊý½øÐгõ²½´¦Àí£¬²¢Ìí¼ÓÏàÓ¦µÄ¸¨ÖúÐÅÏ¢£¬×îÖÕͨ¹ýÖ¸¶¨µÄÐÒé¸øDocker Server·¢ËÍDocker ClientºÍDocker ServerÔ¼¶¨ºÃµÄAPIÇëÇó¡£
4. ×ܽá
±¾ÎÄ´ÓÔ´ÂëµÄ½Ç¶È·ÖÎöÁË´Ódocker¿ÉÖ´ÐÐÎļþ¿ªÊ¼£¬µ½´´½¨Docker Client£¬×îÖÕ·¢Ë͸øDocker ServerÇëÇóµÄÍêÕû¹ý³Ì¡£
±ÊÕßÈÏΪ£¬Ñ§Ï°ÓëÀí½âDocker ClientÏà¹ØµÄÔ´ÂëʵÏÖ£¬²»½ö¿ÉÒÔÈÃÓû§ÊìÁ·ÕÆÎÕDockerÃüÁîµÄʹÓ㬻¹¿ÉÒÔʹµÃÓû§ÔÚÌØÊâÇé¿öÏÂÓÐÄÜÁ¦ÐÞ¸ÄDocker ClientµÄÔ´Â룬ʹÆäÂú×ã×ÔÉíϵͳµÄijЩÌØÊâÐèÇó£¬ÒÔ´ïµ½¶¨ÖÆDocker ClientµÄÄ¿µÄ£¬×î´ó·¢»ÓDocker¿ª·Å˼ÏëµÄ¼ÛÖµ¡£