2016-06-16 93 views
6

在執行docker push或拉取圖像時,Docker如何確定映像名稱中是否存在註冊表服務器,或者它是否爲默認註冊表(例如Docker Hub)上的路徑/用戶名?如何解析碼頭圖像名稱?

我看到從1.1 image spec如下:

標籤

的標籤用來描述的,用戶給定的名稱映射到任何單個圖像 ID。標記值僅限於字符集[a-zA-Z_0-9]。

下一個共同的前綴分組標籤集合(:)之前的名稱部分 。例如,在名稱爲my-app:3.1.4,0.的圖像中,my-app是名稱的Repository組件。存儲庫名稱爲 ,由斜槓分隔的名稱組件組成,可選地,前綴爲 DNS主機名。主機名必須遵守標準DNS規則 ,但不得包含_字符。如果存在主機名,則可能會有 (可選)後跟一個端口號,格式爲:8080。名稱 組件可能包含小寫字符,數字和分隔符。一個 分隔符被定義爲一個句點,一個或兩個下劃線,或一個或更多破折號 。名稱組件不能以分隔符開始或結束。

對於DNS主機名,是否需要完全限定點或是「my-local-server」是有效的註冊表主機名?對於名稱組件,我將週期視爲有效,這意味着「team.user/appserver」是有效的圖像名稱。如果註冊表服務器在端口80上運行,因此圖像名稱中的主機名不需要端口號,似乎主機名和註冊表服務器上的路徑之間會有不明確的地方。我很好奇Docker如何解決這個模糊問題。

回答

3

TL; DR:主機名必須在第一個/之前包含. dns分隔符或:端口分隔符,否則代碼假定您需要默認註冊表。


後一些通過代碼挖掘,我碰到distribution/reference/reference.go想出了以下內容:

// Grammar 
// 
// reference      := name [ ":" tag ] [ "@" digest ] 
// name       := [hostname '/'] component ['/' component]* 
// hostname      := hostcomponent ['.' hostcomponent]* [':' port-number] 
// hostcomponent     := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/ 
// port-number      := /[0-9]+/ 
// component      := alpha-numeric [separator alpha-numeric]* 
// alpha-numeric     := /[a-z0-9]+/ 
// separator      := /[_.]|__|[-]*/ 
// 
// tag        := /[\w][\w.-]{0,127}/ 
// 
// digest       := digest-algorithm ":" digest-hex 
// digest-algorithm    := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ] 
// digest-algorithm-separator  := /[+.-_]/ 
// digest-algorithm-component  := /[A-Za-z][A-Za-z0-9]*/ 
// digest-hex      := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value 

實際執行的是通過在distribution/reference/regexp.go一個正則表達式。

但是有些挖掘和戳動,我發現除了那個正則表達式還有另外一個檢查(如果你不包括.:,你會得到一個大寫主機名的錯誤)。我找到了名稱爲以下實際分割中docker/reference.go

func splitHostname(name string) (hostname, remoteName string) { 
    i := strings.IndexRune(name, '/') 
    if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") { 
     hostname, remoteName = DefaultHostname, name 
    } else { 
     hostname, remoteName = name[:i], name[i+1:] 
    } 
    if hostname == LegacyDefaultHostname { 
     hostname = DefaultHostname 
    } 
    if hostname == DefaultHostname && !strings.ContainsRune(remoteName, '/') { 
     remoteName = DefaultRepoPrefix + remoteName 
    } 
    return 
} 

那對我來說最重要的部分是在第一個if語句爲.:檢查第一/之前。使用它,主機名將從第一個/之前拆分出來,如果沒有它,則會將整個名稱傳遞給默認的註冊表主機名。

+0

根據圖像符合規範的標籤被限制在127個字符。所以我認爲標籤正則表達式應該是/[\w][\w.-]{0,126}/ –

+0

正則表達式的長度是0到127個字符,所以我認爲是正確的。如果沒有,那麼這將是一個公關改變這個:https://github.com/docker/distribution/blob/master/reference/regexp.go#L37 – BMitch

+0

這是我的方式......正則表達式開始[/ w] [\ w.-] {0,127}並且沒有|在。。之間 [ ]。所以這意味着匹配a/w,然後匹配127 \ w或點或連字符。在Ruby的irb中嘗試/^([\w][\w.-]{0,4}$$.match('ssss-')確認5個字符被消耗... –