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 ClientµÄ´´½¨¡£Õⲿ·ÖµÄ·ÖÎö¿É·ÖΪÒÔÏÂÈý¸ö²½Ö裺
·ÖÎöÈçºÎͨ¹ýdockerÃüÁ½âÎö³öÃüÁîÐÐflag²ÎÊý£¬ÒÔ¼°dockerÃüÁîÖеÄÇëÇó²ÎÊý£»
·ÖÎöÈçºÎ´¦Àí¾ßÌåµÄflag²ÎÊýÐÅÏ¢£¬²¢ÊÕ¼¯Docker ClientËùÐèµÄÅäÖÃÐÅÏ¢£»
·ÖÎöÈçºÎ´´½¨Ò»¸öDocker Client¡£
µÚ¶þ²¿·ÖÔÚÒÑÓÐDocker ClientµÄ»ù´¡ÉÏ£¬·ÖÎöÈçºÎÖ´ÐÐdockerÃüÁî¡£Õⲿ·ÖµÄ·ÖÎöÓÖ¿É·ÖΪÒÔÏÂÁ½¸ö²½Ö裺
·ÖÎöÈçºÎ½âÎödockerÃüÁîÖеÄÇëÇó²ÎÊý£¬»ñÈ¡ÏàÓ¦ÇëÇóµÄÀàÐÍ£»
·ÖÎöDocker ClientÈçºÎÖ´ÐоßÌåµÄÇëÇóÃüÁ×îÖÕ½«ÇëÇó·¢ËÍÖÁDocker
Server¡£
3. Docker ClientµÄ´´½¨
Docker ClientµÄ´´½¨£¬ÊµÖÊÉÏÊÇDockerÓû§Í¨¹ý¿ÉÖ´ÐÐÎļþdocker£¬ÓëDocker
Server½¨Á¢ÁªÏµµÄ¿Í»§¶Ë¡£ÒÔÏ·ÖÈý¸öС½Ú·Ö±ð²ûÊöDocker ClientµÄ´´½¨Á÷³Ì¡£
ÒÔÏÂΪÕû¸ödockerÔ´´úÂëÔËÐеÄÁ÷³Ìͼ£º
ÉÏͼͨ¹ýÁ÷³ÌͼµÄ·½Ê½£¬Ê¹µÃ¶ÁÕ߸üΪÇåÎúµÄÁ˽âDocker Client´´½¨¼°Ö´ÐÐÇëÇóµÄ¹ý³Ì¡£ÆäÖÐÉæ¼°ÁËÖî¶àÔ´´úÂëÖеÄÌØÓÐÃû´Ê£¬ÔÚÏÂÎÄÖлáÒ»Ò»½âÊÍÓë·ÖÎö¡£
3.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µÄ½âÎö¡£
3.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ÈçºÎʵÏÖ´´½¨²¢Ö´ÐС£
3.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º¯Êý¼ÌÐøÖ´ÐС£
4. DockerÃüÁîÖ´ÐÐ
mainº¯ÊýÖ´Ðе½Ä¿Ç°ÎªÖ¹£¬ÓÐÒÔÏÂÄÚÈÝÐèҪΪDockerÃüÁîµÄÖ´ÐзþÎñ£º´´½¨Íê±ÏµÄDocker Client£¬dockerÃüÁîÖеÄÇëÇó²ÎÊý£¨¾flag½âÎöºó´æ·ÅÓÚflag.Arg()£©¡£Ò²¾ÍÊÇ˵£¬ÐèҪʹÓÃDocker
ClientÀ´·ÖÎödocker ÃüÁîÖеÄÇëÇó²ÎÊý£¬²¢×îÖÕ·¢ËÍÏàÓ¦ÇëÇó¸øDocker Server¡£
4.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:]¡)¡£
4.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ÇëÇó¡£
5. ×ܽá
±¾ÎÄ´ÓÔ´ÂëµÄ½Ç¶È·ÖÎöÁË´Ódocker¿ÉÖ´ÐÐÎļþ¿ªÊ¼£¬µ½´´½¨Docker Client£¬×îÖÕ·¢Ë͸øDocker
ServerÇëÇóµÄÍêÕû¹ý³Ì¡£
±ÊÕßÈÏΪ£¬Ñ§Ï°ÓëÀí½âDocker ClientÏà¹ØµÄÔ´ÂëʵÏÖ£¬²»½ö¿ÉÒÔÈÃÓû§ÊìÁ·ÕÆÎÕDockerÃüÁîµÄʹÓ㬻¹¿ÉÒÔʹµÃÓû§ÔÚÌØÊâÇé¿öÏÂÓÐÄÜÁ¦ÐÞ¸ÄDocker
ClientµÄÔ´Â룬ʹÆäÂú×ã×ÔÉíϵͳµÄÄ³Ð©ÌØÊâÐèÇó£¬ÒÔ´ïµ½¶¨ÖÆDocker ClientµÄÄ¿µÄ£¬×î´ó·¢»ÓDocker¿ª·Å˼ÏëµÄ¼ÛÖµ¡£
|