DockerFile構建鏡像和Docker倉庫
利用commit理解鏡像構成
注意: docker commit 命令除了學習之外,還有一些特殊的應用場合,比如被入侵後保存現 場等。但是,不要使用 docker commit 定製鏡像,定製鏡像應該使用 Dockerfile 來完成
鏡像是容器的基礎,每次執行 docker run 的時候都會指定哪個鏡像作為容器運行的基礎。
我們之前所使用的鏡像都是docker hub等網站上的,直接使用這些鏡像可以滿足一定的需求,而當這些鏡像無法直接滿足需求時候,我們需要定製這些鏡像.之前有說過,鏡像是多層存儲,每一層是在前一層的基礎上進行的修改,而容器也是多層存儲,是在以鏡像為基礎層,在其基礎上加一層作為容器運行時的存儲層.
定製一個Web服務器
docker pull daocloud.io/library/nginx
docker run --name webserver -d -p 80:80 daocloud.io/library/nginx
# 我們訪問這個web服務,會看到nginx的默認歡迎界面,假如我不喜歡這個界面,想看到歡迎docker的文字,可以exec
curl 119.3.255.91
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
docker exec -it webserver bash
root@6e63ab0d5109:/# echo '<h1>Hello,Docker!</h1>'> /usr/share/nginx/html/index.html
root@6e63ab0d5109:/# exit
exit
# 我們在訪問時候就發現內容改變了
curl 119.3.255.91
<h1>Hello,Docker!</h1>
# 我們修改了容器的文件,就是改動了容器的存儲層,我們可以通過docker diff命令看到具體變動
docker diff webserver
C /root
A /root/.bash_history
C /run
A /run/nginx.pid
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
現在我們定製好了變化,我們希望將其保存下來形成鏡像.
要知道,當我們運行一個容器的時候(如果不使用卷的話),我們做的任何文件修改都會被 記錄於容器存儲層里。而 Docker 提供了一個 docker commit 命令,可以將容器的存儲層保 存下來成為鏡像。換句話說,就是在原有鏡像的基礎上,再疊加上容器的存儲層,並構成新 的鏡像。以後我們運行這個新鏡像的時候,就會擁有原有容器最後的文件變化(類似於虛擬機的快照)。
docker commit 的語法格式為:
docker commit [選項] <容器ID或容器名> [<倉庫名>[:<標籤>]]
# 我們可以用下面的命令將容器保存為鏡像
docker commit -a="youmen <[email protected]>" -m="edited nginx Default page" webserver nginx:v2
* -m 提交的描述信息
* -a 指定鏡像作者
* webserver為你要給那個容器做成鏡像的那個容器名字或者ID
* nginx:v2是形成的新鏡像名
# 接下來我們基於這個創建好的新鏡像再啟動一個容器.
docker run --name web2 -d -p 81:80 nginx:v2
curl `cat ip.txt`:81
<h1>Hello,Docker!</h1>
# 就這樣,我們完成了一次基於容器構建定製鏡像的操作.
慎用docker commit
使用 docker commit 命令雖然可以比較直觀的幫助理解鏡像分層存儲的概念,但是實際環境 中並不會這樣使用。
首先,如果仔細觀察之前的 docker diff webserver 的結果,你會發現除了真正想要修改的 /usr/share/nginx/html/index.html 文件外,由於命令的執行,還有很多文件被改動或添加 了。這還僅僅是最簡單的操作,如果是安裝軟件包、編譯構建,那會有大量的無關內容被添 加進來,如果不小心清理,將會導致鏡像極為臃腫。
此外,使用 docker commit 意味着所有對鏡像的操作都是黑箱操作,生成的鏡像也被稱為黑 箱鏡像,換句話說,就是除了製作鏡像的人知道執行過什麼命令、怎麼生成的鏡像,別人根 本無從得知。而且,即使是這個製作鏡像的人,過一段時間後也無法記清具體在操作的。雖 然 docker diff 或許可以告訴得到一些線索,但是遠遠不到可以確保生成一致鏡像的地步。 這種黑箱鏡像的維護工作是非常痛苦的。
而且,回顧之前提及的鏡像所使用的分層存儲的概念,除當前層外,之前的每一層都是不會 發生改變的,換句話說,任何修改的結果僅僅是在當前層進行標記、添加、修改,而不會改 動上一層。如果使用 docker commit 製作鏡像,以及後期修改的話,每一次修改都會讓鏡像 更加臃腫一次,所刪除的上一層的東西並不會丟失,會一直如影隨形的跟着這個鏡像,即使 根本無法訪問到。這會讓鏡像更加臃腫.
使用Dockerfile定製鏡像
從剛才的 docker commit 的學習中,我們可以了解到,鏡像的定製實際上就是定製每一層所 添加的配置、文件。如果我們可以把每一層修改、安裝、構建、操作的命令都寫入一個腳 本,用這個腳本來構建、定製鏡像,那麼之前提及的無法重複的問題、鏡像構建透明性的問 題、體積的問題就都會解決。這個腳本就是 Dockerfile。
Dockerfile 是一個文本文件,其內包含了一條條的指令(Instruction),每一條指令構建一層, 因此每一條指令的內容,就是描述該層應當如何構建。
還以之前定製 nginx 鏡像為例,這次我們使用 Dockerfile 來定製。
在一個空白目錄中,建立一個文本文件,並命名為 Dockerfile :
cat DockerFile
mkdir mynginx
cd mynginx
vim Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
FROM指定基礎鏡像
FROM為指定基礎鏡像,我們定製鏡像,肯定要以一個鏡像為基礎,在其上做定製,而FROM就是指定基礎鏡像,因此一個Dockerfile中FROM是必備的命令,並且必須是第一條指令.
在Docker Store上有非常多高質量的官方鏡像,有可以直接拿來使用的服務類鏡像,如nginx,redis,mysql,mongo,tomcat等,也有方便開發、構建、運行各種語言的鏡像,如node,openjdk,python,ruby,golang等,可以在其中尋找一個最符合我們的鏡像為基礎鏡像進行定製.
如果還沒有找到對應服務的鏡像,官方鏡像中提供了一些更為基礎的操作系統鏡像,如ubuntu,debian,centos,fedora,alpine等,這些操作系統的軟件庫為我們提供了更廣闊的擴展空間.
除了選擇現有鏡像為基礎鏡像外,Docker 還存在一個特殊的鏡像,名為 scratch 。這個鏡像 是虛擬的概念,並不實際存在,它表示一個空白的鏡像。
如果你以 scratch 為基礎鏡像的話,意味着你不以任何鏡像為基礎,接下來所寫的指令將作 為鏡像第一層開始存在。 不以任何系統為基礎,直接將可執行文件複製進鏡像的做法並不罕見,比如 swarm 、 coreos/etcd 。對於 Linux 下靜態編譯的程序來說,並不需要有操作系統提供運行時 支持,所需的一切庫都已經在可執行文件里了,因此直接 FROM scratch 會讓鏡像體積更加小 巧。使用 Go 語言 開發的應用很多會使用這種方式來製作鏡像,這也是為什麼有人認為 Go 是特別適合容器微服務架構的語言的原因之一。
RUN 執行命令
RUN 指令是用來執行命令行命令的。由於命令行的強大能力, RUN 指令在定製鏡像時是最 常用的指令之一。其格式有兩種:
shell 格式: RUN <命令> ,就像直接在命令行中輸入的命令一樣。剛才寫的 Dockerfile 中 的 RUN 指令就是這種格式。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exec 格式: RUN [“可執行文件”, “參數1”, “參數2”] ,這更像是函數調用中的格式。 既然 RUN 就像 Shell 腳本一樣可以執行命令,那麼我們是否就可以像 Shell 腳本一樣把每個 命令對應一個 RUN 呢?比如這樣:
cat Dockerfile
FROM debian:jessie
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "//download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install
之前說過,Dockerfile 中每一個指令都會建立一層, RUN 也不例外。每一個 RUN 的行為, 就和剛才我們手工建立鏡像的過程一樣:新建立一層,在其上執行這些命令,執行結束 後, commit 這一層的修改,構成新的鏡像。
而上面的這種寫法,創建了 7 層鏡像。這是完全沒有意義的,而且很多運行時不需要的東 西,都被裝進了鏡像里,比如編譯環境、更新的軟件包等等。結果就是產生非常臃腫、非常 多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。 這是很多初學 Docker 的人常 犯的一個錯誤。
Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層。因此上面Dockerfile可以這樣寫:
cat DockerFile
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \ && apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "//download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
首先,之前所有的命令只有一個目的,就是編譯、安裝 redis 可執行文件。因此沒有必要建立 很多層,這只是一層的事情。因此,這裡沒有使用很多個 RUN 對一一對應不同的命令,而是 僅僅使用一個 RUN 指令,並使用 && 將各個所需命令串聯起來。將之前的 7 層,簡化為了 1 層。在撰寫 Dockerfile 的時候,要經常提醒自己,這並不是在寫 Shell 腳本,而是在定義每 一層該如何構建。
並且,這裡為了格式化還進行了換行。Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方 式,以及行首 # 進行注釋的格式。良好的格式,比如換行、縮進、注釋等,會讓維護、排障 更為容易,這是一個比較好的習慣。
此外,還可以看到這一組命令的最後添加了清理工作的命令,刪除了為了編譯構建所需要的 軟件,清理了所有下載、展開的文件,並且還清理了 apt 緩存文件。這是很重要的一步,我 們之前說過,鏡像是多層存儲,每一層的東西並不會在下一層被刪除,會一直跟隨着鏡像。 因此鏡像構建時,一定要確保每一層只添加真正需要添加的東西,任何無關的東西都應該清 理掉。
很多人初學 Docker 製作出了很臃腫的鏡像的原因之一,就是忘記了每一層構建的最後一定要 清理掉無關文件。
構建鏡像
在之前Dockerfile文件所在目錄執行
cat DockerFile
mkdir mynginx
cd mynginx
vim Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 231d40e811cd
Step 2/2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
---> Running in 3a439666c4da
Removing intermediate container 3a439666c4da
---> 78990dc4a6a6
Successfully built 78990dc4a6a6
Successfully tagged nginx:v3
從命令的輸出結果中,我們可以清晰的看到鏡像的構建過程。在 Step 2 中,如同我們之前 所說的那樣, RUN 指令啟動了一個容器231d40e811cd,執行了所要求的命令,並最後提交 了這一層 3a439666c4da ,隨後刪除了所用到的這個容器78990dc4a6a6。
docker build [選項] <上下文路徑/URL/->
構建成功後我們可以跟nginx:v2那樣運行這個鏡像,結果一樣.
這只是默認行為,實際上 Dockerfile 的文件名並不要求必須為 Dockerfile ,而且並不要求 必須位於上下文目錄中,比如可以用 -f ../Dockerfile.php 參數指定某個文件作為 Dockerfile
Docker build的用法
直接用git repo 進行構建
docker build //github.com/twang2218/gitlab-ce-zh.git#:8.14 docker
build //github.com/twang2218/gitlab-ce-zh.git\#:8.14
Sending build context to Docker daemon 2.048 kB Step 1 :
FROM gitlab/gitlab-ce:8.14.0-ce.0 8.14.0-ce.0:
Pulling from gitlab/gitlab-ce
這行命令指定了構建所需的Git repo,並且指定默認的master分支,構建目錄為/8.14/,然後Docker就會自己去git clone這個項目,切換到指定分支,並進入到指定目錄後開始構建.
用給定的tar壓縮包構建
docker build //server/context.tar.gz
# 如果所給出的 URL 不是個 Git repo,而是個 tar 壓縮包,那麼 Docker 引擎會下載這個包,
# 並自動解壓縮,以其作為上下文,開始構建。
從標準輸入中讀取Dockerfile進行構建
docker build - < Dockerfile
or
cat Dockerfile | docker build -
如果標準輸入傳入的是文本文件,則將其視為 Dockerfile ,並開始構建。這種形式由於直接 從標準輸入中讀取 Dockerfile 的內容,它沒有上下文,因此不可以像其他方法那樣可以將本 地文件 COPY 進鏡像之類的事情。
從標準輸入中讀取上下文壓縮包進行構建
docker build - < context.tar.gz
# 如果發現標準輸入的文件格式是gzip、bzip2、以及xz的話,將會使其為上下文壓縮包,直接將其展開,
# 將裏面視為上下文,並開始構建.
Dockerfile指令詳解
COPY複製文件
# 格式:
# COPY <源路徑>...<目標路徑>
COPY ["<源路徑1>",..."<目標路徑>"]
# 和RUN指令一樣,也有兩種格式,一種類似於命令行,一種類似於函數調用.
COPY指令將從構建上下文目錄中<源路徑>的文件/目錄複製到新的一層的鏡像內的<目標路徑> 位置,比如.
COPY package.json /usr/src/app/
# <源路徑> 可以是多個,甚至可以是通配符,其通配符規則要滿足Go的filepath.Match規則,如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
# <目標路徑> 可以是容器內的絕對路徑,也可以是相對於工作目錄的相對路徑.工作目錄可以 用 WORKDIR 指令來指定).
# 目標路徑不需要事先創建,如果目錄不存在會在複製文件前先行 創建缺失目錄
# 此外,還需要注意一點,使用 COPY 指令,源文件的各種元數據都會保留。比如讀、寫、執 行權限、文件變更時間等.
# 這個特性對於鏡像定製很有用。特別是構建相關文件都在使用 Git 進行管理的時候。
Docker 倉庫和數據管理
訪問倉庫
- 倉庫(Repository)是集中存放鏡像的地方
- 一個容易混淆的概念是註冊服務器( Registry )。實際上註冊服務器是管理倉庫的具體服務 器,每個服務器上可以有多個倉庫,而每個倉庫下面有多個鏡像。從這方面來說,倉庫可以 被認為是一個具體的項目或目錄。例如對於倉庫地址 dl.dockerpool.com/ubuntu 來 說, dl.dockerpool.com 是註冊服務器地址, Ubuntu 是倉庫名。
- 大部分時候,並不需要這兩者的概念.
Docker Hub
-
目前Docker官方維護了一個公共倉庫Docker Hub,其中包括了數量超過15000的鏡像,大部分需求都可以通過在Docker Hub中直接下載鏡像來實現.
-
註冊,可以直接在//cloud.docker.com免費註冊一個Docker Hub賬號.
-
登陸
-
可以通過執行docker login 命令交互式的輸入用戶名及密碼來完成命令行界面登陸Docker Hub。docker logout退出登陸.
拉取鏡像
- 可以通過docker search命令來查找官方倉庫中的鏡像,並利用docker pull命令將他下載到本地.
docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 5717 [OK]
ansible/centos7-ansible Ansible on Centos7 126 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 114 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 101 [OK]
- 可以看到返回了很多包含關鍵字的鏡像,其中包括鏡像名字、描述、收藏數(表示該鏡像的受關注程度),是否官方創建、是否自動創建.
- 根據是否是官方提供,可將鏡像資源分為兩類.
- 一種是類似centos這樣的鏡像,被稱為基礎鏡像或根鏡像,這些基礎鏡像由Docker公司創建、驗證、支持、提供。這樣的鏡像往往使用單個單詞作為名字.
- 還有一種類型,比如tianon/centos鏡像,他是由Docker的用戶創建並維護的,往往帶有用戶名稱前綴,可以通過前綴username/來指定某個用戶提供的鏡像,比如tianon用戶.
- 另外,在查找的時候可以通過–filter=stars=N參數可以顯示收藏數量為N以上的鏡像.
2.2 推送鏡像
- 用戶可以在登陸後通過docker push命令將自己的鏡像推送到Docker Hub。
- 以下命令的flyingdreams請替換為你的Docker賬號用戶名.
docker login # 登陸自己的賬號
docker tag nginx:v2 flyingdreams/nginx:v2
docker push flyingdreams/nginx:v2

2.2 自動創建
- 自動創建(Automated Builds)功能對於需要經常升級鏡像內程序來說,十分方便.
- 有時候,用戶創建了鏡像,安裝了某個軟件,如果程序發佈新版本則需要手動更新鏡像.
- 而自動創建允許用戶Docker Hub指定跟蹤一個目標網站(目前支持GitHub或BitBucket)上的項目,一旦項目發生新的提交或者創建新的標籤(tag),Docker Hub會自動構建鏡像並推送到Docker Hub中.
- 要配置自動創建,包括如下的步驟:
- 創建並登陸Docker Hub,以及目標網站:
- 在目標網站中連接賬戶到Docker Hub;
- 在Docker Hub中配置一個自動連接:
- 選取一個目標網站中的項目(需要含Dockerfile)和分支
- 指定Dockerfile的位置,並提交創建.
- 之後,可以在Docker Hub的自動創建頁面中跟蹤每次創建的狀態.
私有倉庫docker-registry
有時候使用Docker Hub這樣的公共倉庫可能不安全,用戶可以創建一個本地倉庫供私人使用.
通過官方提供的私有倉庫鏡像
registry來搭建私有倉庫。通過 humpback 快速搭建輕量級的Docker容器雲管理平台此外還有像Harbor,rancher等私有倉庫。
3.1 安裝運行docker-registry
# 自定義存儲位置$HOME,一般是root
docker run -d \
-p 5000:5000 \
--restart=always \
--name registry \
-v $HOME/_docker/registry:/var/lib/registry \
registry:2.6
# 從官方倉庫拉去一個鏡像
docker pull nginx
docker tag nginx:latest 47.92.24.137:5000/test_nginx:latest
# 在推送到的時候報錯誤,默認是使用`https`提交,這個搭建的默認使用的是 `http`,解決方法兩個:
# 創建一個https映射
# 將倉庫地址加入到不安全的倉庫列表中
# 我們使用第二種方法,加入到不安全的倉庫列表中,修改docker配置文件
# `vi /etc/docker/daemon.json` 添加 `insecure-registries`配置信息
docker push 47.92.24.137:5000/test_nginx:latest
The push refers to repository [47.92.24.137:5000/test_nginx]
Get //47.92.24.137:5000/v2/: http: server gave HTTP response to HTTPS client
cat /etc/docker/daemon.json
{
"insecure-registries":[
"47.92.24.137:5000"
]
}
systemctl stop docker
systemctl daemon-reload
systemctl start docker
# 推送到私有倉庫中
docker push 47.92.24.137:5000/test_nginx:latest
ls /root/_docker/registry/docker/registry/v2/repositories/test_nginx/
_layers _manifests _uploads
安裝運行harbor(http方式)
- Harbor 可幫助用戶迅速搭建企業級的 Registry 服務, 它提供了管理圖形界面, 基於角色的訪問控制 ( Role Based Access Control), 鏡像遠程複製 (同步), AD/LDAP 集成, 以及審計日誌等企業用戶需求的功能, 同時還原生支持中文, 深受中國用戶的喜愛;
4.1 安裝harbor
-
Harbor 是
VMware公司開源了企業級Registry項目, 其的目標是幫助用戶迅速搭建一個企業級的Docker registry服務。 -
由於 Harbor 是基於 Docker Registry V2 版本,所以 docker 版本必須
>=1.10.0docker-compose>=1.6.0 -
下載最新版
Docker Compose
curl -L “//github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose -
下載最新版
Docker Harbor
wget //github.com/goharbor/harbor/releases/download/v1.10.0-rc1/harbor-offline-installer-v1.10.0-rc1.tgz
# 對二進制文件應用可執行權限:
sudo chmod +x /usr/local/bin/docker-compose
# 測試是否安裝成功
docker-compose --version
# 按照上面給的docker harbor地址,下載離線安裝包
tar xvf harbor-offline-installer-v1.8.1.tgz -C /usr/local/
vim /usr/local/harbor/harbor.yml
hostname: 47.92.24.137
# 運行安裝腳本
./install.sh
[Step 0]: checking installation environment ...
Note: docker version: 19.03.4
Note: docker-compose version: 1.22.0
[Step 1]: loading Harbor images ...
Loaded image: goharbor/harbor-core:v1.8.1
Loaded image: goharbor/harbor-registryctl:v1.8.1
Loaded image: goharbor/redis-photon:v1.8.1
Loaded image: goharbor/notary-server-photon:v0.6.1-v1.8.1
Loaded image: goharbor/chartmuseum-photon:v0.8.1-v1.8.1
Loaded image: goharbor/harbor-db:v1.8.1
Loaded image: goharbor/harbor-jobservice:v1.8.1
Loaded image: goharbor/nginx-photon:v1.8.1
Loaded image: goharbor/registry-photon:v2.7.1-patch-2819-v1.8.1
Loaded image: goharbor/harbor-migrator:v1.8.1
Loaded image: goharbor/prepare:v1.8.1
Loaded image: goharbor/harbor-portal:v1.8.1
Loaded image: goharbor/harbor-log:v1.8.1
Loaded image: goharbor/notary-signer-photon:v0.6.1-v1.8.1
Loaded image: goharbor/clair-photon:v2.0.8-v1.8.1
[Step 2]: preparing environment ...
prepare base dir is set to /usr/local/harbor
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
Generated and saved secret to file: /secret/keys/secretkey
Generated certificate, key file:/secret/core/private_key.pem, cert file:/secret/registry/root.crt
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
[Step 3]: starting Harbor ...
✔ ----Harbor has been installed and started successfully.----
Now you should be able to visit the admin portal at //47.92.24.137.
For more details, please visit //github.com/goharbor/harbor
- 接下來我們可以直接瀏覽器訪問配置文件定義的IP或者域名加端口


4.2 修改harbor端口
# 因為harbor默認端口是80,而大多數時候是不希望使用80端口,修改方法如下
# vim harbor.yml
# 找到port選項修改端口,然後執行./install 就會使用配置文件端口
# 還有一種情況就是更改已有harbor的配置
vim docker-compose.yml
dns_search: .
ports:
- 99:80
auth:
token:
issuer: harbor-token-issuer
realm: //47.92.24.137:99/service/token
rootcertbundle: /etc/registry/root.crt
service: harbor-registry
docker-compose down -v
docker-compose up -d

4.3 使用harbor
- 為了體現出效果,建議使用非harbor的另一台機器
# 鏡像推送
docker login 47.92.24.137:99 -u admin -p youmen
vim /etc/docker/daemon.jsonyml
{
"insecure-registries":["47.92.24.137"]
}
systemctl daemon-reload
systemctl restart docker
# 因為docker默認使用的是https協議,而搭建harbor是http提供服務的,
# 所以要配置可信任,或者強制docker login和docker push 走http的80端口,而不是443端口.
docker tag nginx:latest 47.92.24.137:99/library/nginx:latest
docker push 47.92.24.137:99/library/nginx:latest

安裝harbor(https方式)
DNS服務器安裝dnsmasq
yum -y install dnsmasq
mkdir -p /data/ssl && cd /data/ssl
vim harbor.cfg
hostname = harbor.youmen.com
ui_url_protocol = https
db_password = root123
harbor_admin_password = baiyongjie
ssl_cert = /usr/local/harbor/cert/harbor.youmen.com.crt
ssl_cert_key = /usr/local/harbor/cert/harbor.youmen.com.key
# grep -Ev '#|^$' harbor.yml
hostname: harbor.youmen.com # 本機外網IP或域名,該地址供用戶通過UI進行訪問,不要使用127.0.0.1
https: # 用戶訪問私倉時使用的協議,默認時http,配置成https
port: 443 # https使用的端口
certificate: /usr/local/harbor/cert/harbor.youmen.com.crt # 設置證書文件路徑
private_key: /usr/local/harbor/cert/harbor.youmen.com.key # 設置證書密鑰文件路徑
harbor_admin_password: youmen # harbor的管理員賬戶密碼
database:
password: root123 # 指定mysql數據庫管理員密碼
data_volume: /data # image存儲目錄
clair:
updaters_interval: 12
http_proxy:
https_proxy:
no_proxy: 127.0.0.1,localhost,core,registry
jobservice:
max_job_workers: 10
chart:
absolute_url: disabled
log:
level: info
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 1.8.0
生成harbor證書
mkdir /usr/local/harbor/cert/
cd /usr/local/harbor/cert/
#生成根證書
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt -subj "/C=CN/L=Shanghai/O=harbor/CN=harbor-registry"
#生成一個證書籤名, 設置訪問域名為 harbor.baiyongjie.com
openssl req -newkey rsa:4096 -nodes -sha256 -keyout harbor.youmen.com.key -out server.csr -subj "/C=CN/L=Shanghai/O=harbor/CN=harbor.youmen.com"
#生成主機證書
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out harbor.youmen.com.crt
# 接下來執行自動安裝腳本即可.
添加本地解析到hosts
#echo "192.168.1.155 harbor.baiyongjie.com" >> /etc/hosts
#cd /usr/local/harbor
# ./install.sh
官方建議不要在Harbor上啟用https,而是將Harbor放置到一個SLB的後邊,配置SLB的端口轉發進行訪問,或者再裝一個Nginx,進行Nginx的端口轉發.
如果想做一個HA方案的話,可以按照如下方式構建一個(主從模式個人感覺很不靠譜
負載均衡同時還要承擔檢查的任務,而Redis用於數據的緩存和消息隊列的實現,Mysql存儲用戶信息和倉庫信息,雲存儲用來存儲Docker鏡像.



