跳至主要内容

4.7 推送映像檔到 DockerHub

接下來將會練習把本地的映像檔推送到 DockerHub。

映像檔加上儲存庫的名稱

4.3 映像檔的標籤 中已經有介紹過關於映像檔的『 標籤們 』會對應到同一份獨一無二的映像檔,對於熟悉 Git 的朋友們來說,可能會認為這和 commit 是一樣的。

但實質上不一樣,commit 代表的是紀錄這次檔案的更動,而映像檔的標籤更像是指向某一個版本的映像檔而已,所以說一個版本的映像檔可以有超級多的標籤,如同之前提過的一樣。

所以現在腦中的認知,映像檔應該是長這樣的,下方用 nginx 做示範:

nginx:latest # 映像檔的名稱:標籤

而 latest 這個標籤在目前的使用慣例上幾乎都是最新版本的意思,但其實它是預設的標籤,所以我個人認為如果叫做 default 會更好,但這也不是我能決定的,大家用得習慣有共識就好。

接下來要在這個映像檔前面加上儲存庫的名稱,告訴它要存到哪一個儲存庫之中,我們先打開映像檔的列表,就可以看到從左至右分別是儲存庫的名稱、標籤、映像檔的 ID、建立時間以及大小。

$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 7.0.4 dc7b40a0b05d 2 mins ago 117MB
redis 7.0 dc7b40a0b05d 2 mins ago 117MB
httpd latest a981c8992512 7 days ago 145MB
postgres latest f8dd270e5152 2 weeks ago 376MB
nginx latest b692a91e4e15 4 weeks ago 142MB
robeeerto/whoami latest 44dec3c891tr 5 days ago 276MB

而上方的 robeeerto/whoami 明顯看起來和其他的映像檔不太一樣,4.2 從 DockerHub 開始認識映像檔 有簡單的提到官方的映像檔是沒有前綴的,而斜線前面的名稱則代表儲存庫的名稱,也就是 DockerHub 登入後右上角的名稱。

那我們要怎麼改變映像檔的名字呢?可以用 docker image tag 的指令把 nginx:latest 貼上一個不同的標籤。

$ docker image tag nginx:latest robeeerto/nginx:latest
# 無反應是正常的

$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 7.0.4 dc7b40a0b05d 2 mins ago 117MB
redis 7.0 dc7b40a0b05d 2 mins ago 117MB
httpd latest a981c8992512 7 days ago 145MB
postgres latest f8dd270e5152 2 weeks ago 376MB
nginx latest b692a91e4e15 4 weeks ago 142MB
robeeerto/whoami latest 44dec3c891tr 5 days ago 276MB
robeeerto/nginx latest b692a91e4e15 4 weeks ago 142MB

記住喔! 這邊的貼標籤並沒有對映像檔做任何的更動,可以看到不論是建立時間還是 IMAGE ID 都是一模一樣的。

接著可以利用 docker image push 的指令來把映像檔推到已經註冊好的 DockerHub。

$ docker image push robeeerto/nginx:latest
The push refers to repository [docker.io/robeeerto/nginx]
b539cf60d7bb: Preparing
bdc7a32279cc: Preparing
f91d0987b144: Preparing
3a89c8160a43: Preparing
e3257a399753: Preparing
92a4e8a3140f: Waiting
denied: requested access to the resource is denied

發現請求被回絕了,看起來是權限上面的問題,這是因為還沒有登入的關係,對於推送映像檔到 robeeerto 的儲存庫並沒有權限。

用終端機登入 DockerHub

接著使用 docker login 這個指令,並輸入您的使用者名稱以及 DockerHub 的密碼。

$ docker login
Username: robeeerto
Password: 輸入 DockerHub 的密碼

Login Succeeded

有可能您會遇到下面的問題,若是沒有遇到的讀者可以直接跳過。

$ docker login
Username: robeeerto
Password: 輸入 DockerHub 的密碼

Error response from daemon: Get "https://registry-1.docker.io/v2/": unauthorized: please use personal access token to login

錯誤訊息請我們去申請個人的 Token 來進行登入,這時候打開 DockerHub 點擊大頭貼並進入 Account Setting。

Token 申請流程圖-1

接著點擊左手邊的 Security 的選項,會看到畫面中有 New Access Token 的按鈕,點擊下去。

Token 申請流程圖-2

接著填入對於這個 Token 的描述,我填入的是 MyMacBook

Token 申請流程圖-3

點擊下 Generate 之後,畫面會有順序的告知你該如何在終端機登入 DockerHub。

Token 申請流程圖-4

接著照著步驟在終端機依序輸入:

$ docker login -u robeeerto
Password: # 貼上產生的 Token
Login Succeeded

Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/

這樣就成功利用終端機登入了 DockerHub,可以來試試看推送映像檔了。

推送映像檔

$ docker image push robeeerto/nginx:latest
The push refers to repository [docker.io/robeeerto/nginx]
b539cf60d7bb: Mounted from library/nginx
bdc7a32279cc: Mounted from library/nginx
f91d0987b144: Mounted from library/nginx
3a89c8160a43: Mounted from library/nginx
e3257a399753: Mounted from library/nginx
92a4e8a3140f: Mounted from library/postgres
latest: digest: sha256:f26fbadb0acab4a21ecb4e337a3269.. size: 1570

從上方的輸出中可以注意到 Mounted from library/nginx 這段資訊,代表的是現在推上去的這個映像檔,雖然不存在 robeeerto 的儲存庫中,但在整個 DockerHub 內是有一模一樣的映像層存在。

所以 DockerHub 從另一個儲存庫 library/nginx 分享了映像層給我們,這樣做可以大幅度的減少 DockerHub 在儲存映像檔的容量問題,同時也能加快推送的速度。

還透露了另外一個訊息就是官方映像檔並非真的沒有前綴,而是不顯示而已,這邊不就清楚的看到前綴是 library 了嗎?代表它們隸屬於 library 這個儲存庫。

接著回到自己 DockerHub 的個人頁面,應該會看到剛剛推送上來的映像檔。

成功推送 robeeerto/nginx

重貼標籤試試快取

前面有提過映像層是利用每一層的獨特 ID 來辨識存不存在,並利用這個機制來避免重複建置映像層。

那我們就把剛剛的 robeeerto/nginx:latest 這個映像檔換一個標籤推上去看看,會發生什麼事吧!

$ docker image tag robeeerto/nginx:latest robeeerto/nginx:v2
# 無反應為正常情況

$ docker image push robeeerto/nginx:v2
The push refers to repository [docker.io/robeeerto/nginx]
b539cf60d7bb: Layer already exists
bdc7a32279cc: Layer already exists
f91d0987b144: Layer already exists
3a89c8160a43: Layer already exists
e3257a399753: Layer already exists
92a4e8a3140f: Layer already exists
v2: digest: sha256:f26fbadb0acab4a21ecb4e337a32690... size: 1570

不論是體感的速度,還是 Docker 給予的回應都可以驗證先前所提到的快取機制。

接著回到 DockerHub 也確實可以看到兩個不同的標籤有著相同的映像檔 ID。

重新推送新的標籤

映像檔的完全名稱

在推送映像檔的時候,會注意到有一行寫著:

The push refers to repository [docker.io/robeeerto/nginx]

後面的 robeeerto/nginx 已經解釋過的部分,那前面的 docker.io 又是什麼呢?

這其實是 DockerHub 儲存庫的網域名稱,所以下方這段才是映像檔的全名:

docker.io/robeeerto/nginx:latest

而 Docker 也有提供儲存庫本身的映像檔,意味著使用者可以建立屬於自己的儲存庫,若成功部署至網際網路後,推送映像檔的全名會像這樣:robeeerto.com ( 部署的網域名稱 )/robeeerto/nginx:latest

對於私人的專案除了付費使用 DockerHub 的 Private Registry 外,架設一個屬於自己的映像檔儲存庫也是一件很值得的事情,在後面的章節將會帶領大家部署一個屬於自己的映像檔儲存庫。