Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
DockerÔ´Âë·ÖÎö(¶þ)£ºDocker Client´´½¨ÓëÃüÁîÖ´ÐÐ
 
×÷ÕߣºËïºêÁÁ À´Ô´£ºInfoQ ·¢²¼ÓÚ 2015-04-01
  1586  次浏览      27
 

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¿ª·Å˼ÏëµÄ¼ÛÖµ¡£

   
1586 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

ÿÈÕ¹¹½¨½â¾ö·½°¸
ÈçºÎÖÆ¶¨ÓÐЧµÄÅäÖùÜÀíÁ÷³Ì
ÅäÖùÜÀíÖ÷Òª»î¶¯¼°ÊµÏÖ·½·¨
¹¹½¨¹ÜÀíÈëÃÅ
Ïà¹ØÎĵµ

ÅäÖùÜÀíÁ÷³Ì
ÅäÖùÜÀí°×ƤÊé
CM09_CÅäÖùÜÀí±ê×¼
ʹÓÃSVN½øÐа汾¿ØÖÆ
Ïà¹Ø¿Î³Ì

ÅäÖùÜÀíʵ¼ù
ÅäÖùÜÀí·½·¨¡¢¹¤¾ßÓëÓ¦ÓÃ
¶à²ã´Î¼¯³ÉÅäÖùÜÀí
²úÆ··¢²¼¹ÜÀí
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

Èí¼þÅäÖùÜÀíµÄÎÊÌ⡢ĿµÄ
Èí¼þÅäÖùÜÀí¹æ·¶
CQWeb 7.1ÐÔÄܲâÊÔÓëµ÷ÓÅÖ¸ÄÏ
ΪʲôÐèҪʹÓÃClearCase
ClearCaseÓëRTCµÄ¼¯³É
ÀûÓÃClearQuest ½øÐвâÊÔ¹ÜÀí


²úÆ··¢²¼¹ÜÀí
ÅäÖùÜÀí·½·¨¡¢Êµ¼ù¡¢¹¤¾ß
¶à²ã´Î¼¯³ÉÅäÖùÜÀí
ʹÓÃCCÓëCQ½øÐÐÏîĿʵ¼ù
CVSÓëÅäÖùÜÀí
Subversion¹ÜÀíÔ±


ÅäÖùÜÀíʵ¼ù£¨´Ó×éÖ¯¼¶µ½ÏîÄ¿¼¶£©
ͨºÅÔº ÅäÖùÜÀí¹æ·¶ÓëÓ¦ÓÃ
ÅäÖùÜÀíÈÕ¹¹½¨¼°³ÖÐø¼¯³É
µ¤·ð˹ ClearCaseÓëÅäÖùÜÀí
ÖйúÒÆ¶¯ Èí¼þÅäÖùÜÀí
ÖйúÒøÐÐ Èí¼þÅäÖùÜÀí
Ìì½ò»ªÒíÀ¶Ìì¿Æ¼¼ ÅäÖùÜÀíÓëPvcs