使用Travis在Docker Hub上管理開源Docker映象
我最近正在開展一個小專案,學習使用Docker工具鏈,並瞭解其工作原理。 我決定構建(又一個)etcd的開源Docker映象並將其釋出在Docker Hub上。 像所有開源專案一樣,構建一個有效的Docker映象非常簡單,並沒有花太多時間。反而是如何映象讓更多人覺得有用會花費更多的時間。 在這個過程中,我學到了一些關於使用Docker,Docker Hub和Travis的內容,但仍然有一些問題沒有得到解答。 因此,我認為值得記錄我的發現和未解答的問題,以獲得反饋並提高我的理解。
\\首先闡述我的要求:
\\- 支援最新版本和一些舊版本的應用程式似乎是Docker社群中的常見做法。 支援常見發行版及其精簡版本似乎也是一種常見做法。 因此,該映象應該遵循社群的做法。\\t
- Github上的README自動同步到Docker Hub上的描述是必須的。 我的假設是開發人員通常會在Docker Hub上發現Docker映象。 所以只在Github上有一個很好的自述檔案是不夠的。 該文件也必須存在於Docker Hub上。 我不想在我的git倉庫中編寫文件,然後每次有更改時手動將其複製到Docker Hub。\\t
- 映象本身應該非常易於使用,既可以作為伺服器執行etcd,也可以作為CLI客戶端執行。 我不打算討論這個,因為這與本章主題有點無關。 但是如果你感興趣的話,請檢視README並在Github專案中開啟一個issue來反饋問題。\
第一個挑戰是建立一個自動化流程來構建新映象並將其上傳到Docker Hub。 有一篇很好的部落格記錄瞭如何使用Travis實現這一目標,以便每次推送到程式碼庫都會構建一個新映象像,並且當合並分支時,構建的新映象將被推送到Docker Hub。 設定很簡單。
\\儘管簡單,但它不符合我的任何要求。 下面嘗試逐一解決。
\\問題#1 - 自動同步README
\\雖然上面提及到的Travis構建過程可以構建並將映象推送到Docker Hub,但它無法同步README。 Docker CLI也不支援更新Docker Hub上的描述。
\\Docker Hub有一個名為Automated Builds的東西,通過配置,可以達到Travis作業產生的結果。 並且,它還可以從Github倉庫中提取README的內容,以便在Docker Hub上作為描述使用。 因此,我們可以使用Automated Builds來構建映象並從Github同步README。 這解決了我們的一項要求。
\\\\Automated Builds的工作原理是我們必須在Docker Hub上配置它以指定Docker上下文的路徑(即Dockerfile的路徑),從該Dockerfile構建映象並打上自己的標記。 這意味著從倉庫構建的每個映象,必須在唯一路徑上存在Dockerfile。 這很快就會成為一個問題。
\\問題#2 - 執行測試
\\雖然Docker Hub上的Automated Builds解決了README同步問題,但自動構建還存在一些其他問題。 你無法將其用作執行測試和獲取PR測試狀態的工具。 根本沒有辦法從Docker Hub的構建系統獲得反饋給Github。 這對於開發流程至關重要
\\所以有一件事是肯定的 - 如果構建失敗,我們需要回到Travis執行測試並阻止PR。
\\問題#3 - 為多個版本構建映象
\\我不僅想構建etcd的最新版本,也包括之前的一些版本,並構建這些版本的發行版本。
\\支援的版本:
\\3.3(最新)
\\3.2
\\支援的發行版本:
\\Debian:stretch-slim
\\alpine
\\因此,我們必須構建總共4個映象 - 每個發行版本對應一個版本。
\\首先看看多版本問題。
\\我開始檢視其他開源Docker映象是如何實現這一點的。 結果並不令人滿意。
\\看了MySQL映象的Dockerfiles。 每個版本的MySQL的docker映象都在倉庫的“版本目錄”中有一個專用的Dockerfile。 他們幾乎沒有區別。 請參閱這兩個MySQL的Dockerfiles - MySQL 5.6和MySQL 5.7的Dockerfile。 在76行程式碼中,它們只有一行不同,並且只是版本不同。
\\我在Nginx的Dockerfiles中觀察到了一個非常相似的模式。 平均而言,每個Dockerfile中每個基本映象的每個版本只有5-10%的行不同。
\\這看起來像是大量的重複程式碼。 我不想這樣,因為每個映象中唯一不同的是版本和包管理器(Alpine和Debian使用不同的包管理器)。
\\Dockerfile的ARG可用於簡化此操作。 通過將值傳遞給docker build命令,ARG可用於定義在構建映象時可以設定的變數。 這非常方便。 由於每個版本的Dockerfiles唯一不同的是URL中的版本本身,我可以輕鬆地使用它並使用相同的Dockerfile和以下命令為不同版本構建docker映象:
\\\docker build . -t \"3.3\" --build-arg version=3.3\docker build . -t \"3.2\" --build-arg version=3.2
\\在帶有環境矩陣的Travis中使用它,我們可以自動為多個版本構建Docker映象。 請參閱.travis.yml中為每個版本構建多個映象的程式碼段:
\\\language: bash\services: docker\env:\ matrix:\ - VERSION=3.3.1\ - VERSION=3.2.19\script:\ - docker build . -t \"$VERSION\" --build-arg version=$VERSION
\\這解決了多版本的多映象問題。 但我們仍然需要解決為每個版本的每個基本映象構建映象的問題。
\\問題#4 - 為多個基本映象進行構建
\\除了為多個版本構建映象,我們還存在為多個基本映象構建映象的問題。 現在僅僅使用ARG是不夠的。
\\在這種情況下,挑戰變成了每個發行版可能都有自己的具體操作方式,例如包管理。 Alpine和Debian使用不同的包管理器。 因此僅使用ARG不足以處理所有更改。 還需要管理如何進行包的安裝。 在這種情況下,我們需要一個安裝包,但不需要執行etcd。 如果我們能夠以某種方式獲得沒有任何額外的etcd二進位制檔案,我們就可以製作出完美的Docker映象。
\\多階段Docker構建和構建器模式
\\Docker的Multi-Stage Builds是一種乾淨利落地構建Docker映象的方式。 通常在構建過程中,我們會安裝大量隨機包。 成功構建應用程式後,清理可能會很麻煩。
\\構建Docker映象時,映象總是越小越好。 有些人使用bash指令碼編寫清理指令。 有些人將開發和生產Dockerfiles分開,開發Dockerfile會產生一個較大包體的映象,其包含開發所需的一切,生產Dockerfile會生成一個僅具有開發Docker映象所必需工件的docker映象。 但這兩種方法都有各自的不足。
\\多階段構建簡化了其中的一部分,並提供了更好地組織Dockerfiles的方法。 你可以在Dockerfiles中新增多個階段,為每個階段構建一個完全獨立的Docker映象,並使用其他構造可以輕鬆地將工件從一個階段複製到另一個階段。 從Docker Hub上的文件中檢視此示例:
\\\FROM golang:1.7.3\WORKDIR /go/src/github.com/alexellis/href-counter/\RUN go get -d -v golang.org/x/net/html \COPY app.go .\RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .\\FROM alpine:latest \RUN apk --no-cache add ca-certificates\WORKDIR /root/\COPY --from=0 /go/src/github.com/alexellis/href-counter/app .\CMD [\"./app\"]
\\首先,注意這個Dockerifle有多個FROM指令。 每條指令表示不同的構建階段,從而產生完全不同的映象。 COPY指令採用名為--from的引數,可用於從其他構建階段複製檔案。 使用此選項來複制你想要用來構建映象的檔案,並留下不需要的所有內容。
\\多階段構建與ARG結合可以解決我們的問題。 現在可以同時使用version和base_image,並使用base_image和FROM指令在構建時選擇基本映象。
\\\FROM debian:stretch-slim\...\\FROM \"$base_image\"\...\COPY --from=0 /path/to/etcd-binary /usr/local/bin\CMD [\"etcd\"]
\\然後執行以下命令來構建所有的映象:
\\\# Version 3.3 on debian:stretch-slim\docker build . -t \"3.3\" --build-arg version=3.3 \\\ --build-arg base_image=\"debian:stretch-slim\"\# Version 3.3 on alpine:latest\docker build . -t \"3.3:alpine\" --build-arg version=3.3 \\\ --build-arg base_image=\"alpine:latest\"\# Version 3.2 on debian:stretch-slim\docker build . -t \"3.2\" --build-arg version=3.2 \\\ --build-arg base_image=\"debian:stretch-slim\"\# Version 3.2 on alpine:latest\docker build . -t \"3.2:alpine\" --build-arg version=3.2 \\\ --build-arg base_image=\"alpine:latest\"
\\在這裡檢視完整的Dockerfile。
\\這為我們解決為多版本構建映象和多個基本映象程式碼重複的問題。
\\Multi-Stage Builds有一些很酷的功能。 我建議檢查一下,以獲得更好的Docker體驗。
\\有了這個,可以通過環境構建矩陣提供的不同環境來構建在Travis上的所有映象,在每個環境合併程式碼到主分支,構建映象、執行測試、推送構建好的映象到Docker Hub。 這是一個示例.travis.yml檔案(上一個示例的擴充套件):
\\\language: bash\services: docker\env:\ matrix:\ - VERSION=3.3.1 BASE_IMAGE=debian:stretch-slim\ - VERSION=3.2.19 BASE_IMAGE=debian:stretch-slim\ - VERSION=3.3.1 BASE_IMAGE=alpine\ - VERSION=3.2.19 BASE_IMAGE=alpine\script:\ - |\ docker build . -t \"$VERSION\" \\\ --build-arg version=$VERSION \\\ --build-arg base_image=\"$BASE_IMAGE\"
\\但同步README的問題仍然存在,並且Travis似乎也無法做到。 下面看看如何解決。
\\問題#5 - 捆綁在一起
\\我們在這裡取得了以下進展:
\\- 我們知道如何為每個版本和每個基本映象構建Docker映象。 可用一種可管理的方式執行此操作,而無需重複程式碼。 並且可以在Travis上進行構建。\\t
- 可以在Travis上構建映象並推送到Docker。 但是無法在Docker Hub上獲得README。\\t
- 可以使用Automated Builds在Docker Hub上構建映象,並將README同步到Docker Hub。 但是我們無法為Github上的每個pull請求構建映象,並且如果構建失敗則阻止合併pull請求。 並且不會給Github任何反饋。\
因此,雖然我們可以使用Travis構建所有映象併為每個PR執行測試,但無法使用它來推送映象。 而對於Docker Hub則相反。 實際上,最簡單形式的Docker Hub的Automated Build系統不能用於基於ARG的設定,因為Automated Builds可以使用Docker上下文,即在構建設定中為“每個指定的路徑”構建映象,並期望這些路徑中存在Dockerfile。 你無法在此類設定中傳遞CLI引數。 因此,我們的自定義docker構建命令不適用於Automated Builds。
\\自定義構建階段鉤子,用於Docker Hub上的自動構建
\\自定義構建階段鉤子允許在不同的構建階段執行自定義指令碼,從而對自動構建進行更高階的自定義。 例如,可以覆蓋構建階段以將額外引數傳遞給docker構建,或者可以覆蓋推送階段以推送到多個倉庫。 當然,你還可以做很多事情。
\\這最終解決了我們所有的問題:
\\- 我們可以使用Travis設定為每個PR構建和執行測試,但不能將映象推送到Docker Hub。\\t
- 只能在主分支上使用自動構建和自定義階段鉤子。 這將把我們的映象推送到Docker Hub並同步來自Github的README。\
構建鉤子指令碼是很通用的。 我參考在Travis中構建映象的指令碼來編寫鉤子指令碼!
\\在此處檢視整個設定:
\\- Dockerfile\\t
- .travis.yml\\t
- 自定義構建鉤子\
結論
\\沒有重複程式碼,易於構建的過程,良好的開發體驗和README的自動同步 - 這對我來說非常有用,我對最終的設定非常滿意。
\\有人可能會說使用Docker Automated Build和Travis很難維護。 可以通過自定義構建鉤子將PR狀態推送到Github,但這不是我到目前為止所探討的,與在Docker Hub上維護Travis和Automated Builds相比,它看起來也需要更多精力。
\\但有一件事不確定是使用ARG構建Docker映象的方法和多階段構建。 雖然它適合我,但我在這個領域的經驗是有限的,我想得到反饋。 你怎麼看? 還有構建和分發開源Docker映象更好的方法嗎? 請通過評論部分告訴我你的想法。
相關文章
- Docker 如何把映象上傳到docker hubDocker
- 如何將docker 映象上傳到docker hub倉庫Docker
- Docker Hub 映象加速器Docker
- docker hub切換國內映象Docker
- Docker Hub 公有映象在國內拉取加速配置Docker
- Docker 映象源Docker
- Docker入門系列之三:如何將dockerfile製作好的映象釋出到Docker hub上Docker
- 開始在 CentOS 上使用 dockerCentOSDocker
- 『現學現忘』Docker基礎 — 40、釋出映象到Docker HubDocker
- Docker——映象管理Docker
- Docker筆記(四):Docker映象管理Docker筆記
- 如何給Docker hub使用者上傳頭像Docker
- 在宿主機上搭建docker映象倉庫Docker
- 在FreeBSD上使用DockerDocker
- docker學習4:Docker 映象使用Docker
- 在python專案的docker映象裡使用pdm管理依賴PythonDocker
- 【Docker】第二篇 Docker映象管理Docker
- 修改docker映象源的方法Docker
- docker 映象建立與使用Docker
- Docker的映象使用-WindowDocker
- Docker | Docker技術基礎梳理(二) - 映象管理Docker
- 【docker專欄5】詳解docker映象管理命令Docker
- 使用 Drools 和 JPA & Drools show case in docker hubDocker
- Docker映象管理快速入門Docker
- 在ubuntu上安裝docker, 使用國內的安裝源UbuntuDocker
- 繞開Docker Hub下載限制:JFrog ArtifactoryDocker
- docker 映象Docker
- Docker Desktop 現在可以在 Linux 上使用DockerLinux
- Docker 公司與阿里雲達成合作,在中國提供 Docker Hub 服務Docker阿里
- 使用Cloudflare Worker加速docker映象CloudDocker
- 第三節 使用Docker映象Docker
- 使用 Docker 開發 - 使用多階段構建映象Docker
- 使用Docker快速部署開源商城Docker
- Docker中ubuntu映象配置apt阿里源DockerUbuntuAPT阿里
- docker/kubernetes國內源/映象源解決方式Docker
- Docker(五)Docker映象講解Docker
- 實踐:Docker容器與映象管理Docker
- docker bulid tag push到自己的docker hub 倉庫Docker