使用 Public Registry 分享 image

寫好 Dockerfile,確實完成了 IaC,但拿到 Dockerfile 才開始 build image,一來花時間,二來這樣就會有其他變因(如 base image 更新),因此直接分享 image 會是更好的方法。

Registry 正是分享 image 的好地方,今天將會介紹如何把 image 放到 public registry 上。

若把 Dockerfile 當作原始碼,則 build 過程產生的 image 是 artifacts,應該要被管理的產出物。

Registry 在手動下指令上傳的方法其實是一樣的,這點留到明天再說明。不同平台的差異,主要是在 Web 功能或 CI 串接支援不大一樣,以下會簡單說明與介紹。

Docker Hub

在今年八月前,Docker Hub 都是第一首選,直到 Docker 官方宣布新限制後,就開始有想轉其他平台了。

不過 Docker Hub 有強大的自動建置設定與 image 整合測試功能,可以輕鬆設定多種版本的 base image,就這點來說,還是比其他平台強上許多。

建立 repository

申請好帳號並登入後,即可在 Docker Hub 個人 dashboard 頁面上找到 Create Repository 按鈕。按下後,需要輸入 repository 的基本資訊,如名稱與說明等。

下面的 Build Setting 就是 Docker Hub 方便的地方了:

它可以與 GitHub 或 Bitbucket 串接 Git repository,在 Git push 的時候,觸發 Docker Hub 的 build event。從範例可以看得出,它可以依照 Git branch 或 Git tag 觸發 Docker build,並產生對應的 Docker tag,甚至還可以使用 regex 來處理。

提供寫過的 image mileschou/lua,裡面的 build 設定做為範例參考:

目前只有設定 branch,沒設定過 tag。主要是因為 Docker image 的原始碼都是其他人的既有專案,如範例的 Lua

當原始碼不是自己控制的時候,使用 branch 控制會比較單純一點,畢竟我們不會知道原始碼何時會發生 Git tag。使用 master branch 控制的話,當 master 更新時,所有版本 image 都會跟著更新,相較簡單很多。但所有版本都放在 master branch 的話,就需要在一個 branch 放所有版本的 Dockerfile,目錄規劃可以參考 [MilesChou/docker-lua][https://github.com/MilesChou/docker-lua] 原始碼。

當原始碼自己可以控制的時候,即可參考 Docker Hub 官方的 tag 設定範例,只要 Regex 設定好即可正常運作。

多版本 Dockerfile 更新

不同版本的差異(如 Lua 5.1、5.2、5.3),通常只有版號的差別,Dockerfile 差異不大。可以額外寫腳本用來產對應版本的 Dockerfile。

詳細腳本可參考原始碼,原理單純只是使用取代指令達成的。

Build image

完成設定後,點選 Create & Build,Docker Hub 就會開始使用 GitHub 上的 Dockerfile 執行 build image 了。可能因為維運考量,所以 Docker Hub build image 的效率越來越差,如果一個 push 會 build 十多個 image,這樣就得等上好一陣子。

完成後,即可使用 docker pull yourname/yourimage 下載自己建好的 image 了!

GitHub

Docker Hub 限制公布沒多久,GitHub 推出了新服務 Container Registry。它的設計概念為,repository 不再只限 Git 原始碼,artifacts 也可以做為 repository 保存在 GitHub 上,而 Container 是其中一種 artifacts。

前一陣子有調整了 Composer Action,同時做為今天的範例介紹。

上面有提到 Docker Hub 最大的優勢在於 build 設定可以透過網頁,比較直覺。使用 GitHub 的話則需要調整 CI 流程才能完成複雜的 build 設定。因為是 GitHub 的產品,所以這裡使用 GitHub Actions(以下簡稱 Actions)來做為範例:

# /.github/workflows/registry.yml
name: Publish Docker

on: [push]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
version: ["7.4", "7.3", "7.2", "7.1", "7.0", "5.6", "5.5"]
steps:
- uses: actions/checkout@master
- name: Build PHP ${{ matrix.version }} and publish to GitHub Registry
uses: elgohr/[email protected]
with:
name: mileschou/composer-action/runner:${{ matrix.version }}
dockerfile: ${{ matrix.version }}/Dockerfile
username: ${{ secrets.GITHUB_USERNAME }}
password: ${{ secrets.GITHUB_TOKEN }}
registry: docker.pkg.github.com

Docker image 建置與推上 GitHub 是在第二個 steps elgohr/[email protected]。這個套件已經非常好用了,with 後的參數,以下特別說明一下。

namedockerfile

name 是 image name,跟 Docker Hub 用途一樣,在 docker pull 的時候會使用到。比較討厭的是,GitHub 規定 name 的格式如下:

:user_name/:repository_name/:image_name

這個格式比 Docker Hub 多出一層子類,而且是強制要求。目前用來做 Docker image 的 Git repository,都是以 image 來命名的,像是 docker-lua 等,若要強制多一層,也只能叫 runner 了。

這裡有用到 matrix.version 這個特殊變數,它對應到上面的設定:

strategy:
matrix:
version: ["7.4", "7.3", "7.2", "7.1", "7.0", "5.6", "5.5"]

這個設定會同時開 7 個對應 version 的 job,而每個 job 的 matrix.version 都會帶入對應的值,有點像在 for loop 一樣。像本例是不同版本要標不同的 tag,與跑不同的 Dockerfile,這個功能就非常地好用。

dockerfile 參數與 Docker Hub 設定一樣,可以指定 Dockerfile 位置。

username password

這裡使用了兩個環境變數:secrets.GITHUB_USERNAMEsecrets.GITHUB_TOKEN,Actions 的環境變數設定可以到 Git repository setting 裡調整:

GITHUB_USERNAME 就是帳號,本例會是我的帳號。

而這裡會發現沒有 GITHUB_TOKEN 的設定。GITHUB_TOKEN 是 Actions 內建 secret 變數,它會自動生成對應 Git repository 權限的 token 代入,所以 Actions 會有權限可以讀寫 repository,包括推 image 上 GitHub Container Registry。

registry

之前在說明 Hello World 的時候有提過,registry 是存放一堆 image 與驗證身分的地方,本例的 docker.pkg.github.com 即為 GitHub 的 registry domain。搭配上面提到的 image name,要下載 7.4 版的 image 需執行下面這個指令:

docker pull docker.pkg.github.com/mileschou/composer-action/runner:7.4

這裡可以發現,完整的 repository 名稱是包含 registry 的。

那 Docker Hub 呢?與 GitHub 一樣是 registry,Docker Hub 也有自己的驗證中心與網域--docker.io。換句話說,下面這幾個指令會到一樣的位置,下載一樣的 image。

docker pull alpine
docker pull docker.io/alpine
docker pull docker.io/library/alpine

了解這點,相信大家就能知道該如何去別的 registry 下載 image 了。

Build image

Actions 只要 workflow 檔案 commit 並 push 就會自動執行了。最後完成即可在 Git repository 主頁或個人的 packages 頁面找到對應的 image。

今日自我回顧

今天的內容比較單純,在網頁設定一下以及 Dockerfile commit 上 GitHub,應該就能 work 了。

  • 練習使用公開的 Registry 服務分享 image