docker實踐(3) 倉庫registry和Nexus3作爲私有鏡像倉庫

 

一. docker 官方倉庫


1.1 下載官方的 CentOS 鏡像到本地

   docker pull centos

1.2  搜索官方的 CentOS 鏡像

[root@iZ235fz06auZ docker]# docker search centos
INDEX       NAME                                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/centos                         The official build of CentOS.                   3476      [OK]       
docker.io   docker.io/jdeathe/centos-ssh             CentOS-6 6.9 x86_64 / CentOS-7 7.3.1611 x8...   77                   [OK]
docker.io   docker.io/tutum/centos                   Simple CentOS docker image with SSH access      32                   
docker.io   docker.io/kinogmt/centos-ssh             CentOS with SSH                                 15                   [OK]

STARS:星級( 表示該鏡像的受歡迎程度)

OFFICIAL:是否官方創建

AUTOMATED:是否自動創建。 

官方的鏡像說明是官方項目組創建和維護的,automated資源允許用戶驗證鏡像的來源和內容。


根據是否是官方提供, 可將鏡像資源分爲兩類。 一種是類似centos這樣的基礎鏡像, 被稱爲基礎或根鏡像。這些基礎鏡像是由Docker公司創建、驗證、 支持、 提供。這樣的鏡像往往使用單個單詞作爲名字。
 

還有一種類型, 比如 tianon/centos 鏡像, 它是由 Docker 的用戶創建並維護的, 往往帶有用戶名稱前綴。 可以通過前綴user_name/來指定使用某個用戶提供的鏡像, 比如tianon 用戶。

另外, 在查找的時候通過-s N 參數可以指定僅顯示評價爲N星以上的鏡像。

 

 

二. docker 私有倉庫


    有時候使用 Docker Hub 這樣的公共倉庫可能不方便, 用戶可以創建一個本地倉庫供私人使用。

   Registry在github上有兩份代碼:老代碼庫新代碼庫。老代碼是採用python編寫的,存在pull和push的性能問題,出到0.9.1版本之後就標誌爲deprecated,不再繼續開發。從2.0版本開始就到在新代碼庫進行開發,新代碼庫是採用go語言編寫,修改了鏡像id的生成算法、registry上鏡像的保存結構,大大優化了pull和push鏡像的效率。

2.1  私有倉庫鏡像安裝

    官方在Docker hub上提供了registry的鏡像(詳情),我們可以直接使用該registry鏡像來構建一個容器,搭建我們自己的私有倉庫服務。Tag爲latest的registry鏡像是0.9.1版本的,我們直接採用2.1.1版本。

1、docker run -d -p 5000:5000 registry
1)指定私有倉庫位置:

用戶可以通過指定參數來配置私有倉庫位置, 例如配置鏡像存儲到Amazon S3 服務。
$ sudo docker run \
   -e SETTINGS_FLAVOR=s3 \
   -e AWS_BUCKET=acme-docker \
   -e STORAGE_PATH=/registry \
   -e AWS_KEY=AKIAHSHB43HS3J92MXZ \
   -e AWS_SECRET=xdDowwlK7TJajV1Y7EoOZrmuPEJlHYcNP2k4j49T \
   -e SEARCH_BACKEND=sqlalchemy \
   -p 5000:5000 \
  registry
2)配置文件:

還可以指定本地路徑( 如/home/user/registry-conf) 下的配置文件
docker run -d -p 5000:5000 -v /etc/docker/registry/config.yml:/etc/docker/registry/config.yml registry

3)倉庫本地:

之前老版Register,默認上傳的鏡像保存在容器的位置是/tmp/registry 。新registry的倉庫目錄是在/var/lib/registry,所以運行時掛載目錄需要注意。

docker run -d -p 5000:5000 -v /data/registry:/var/lib/registry registry
     我們將主機的/data/registry目錄掛載到該目錄,即可實現將鏡像保存到主機的/data/registry目錄了。

 

2.2  上傳pull

創建好私有倉庫之後, 就可以使用 docker tag 來標記一個鏡像, 然後推送它到本地倉庫,別的機器上就可以載下來了。 例如私有倉庫本地地址爲127.0.0.1:5000。

$ docker tag java8  127.0.0.1:5000/java8

使用 docker push 上傳標記的鏡像使用 docker push 上傳標記的鏡像


$ docker push 127.0.0.1:5000/java8

當使用curl http://192.168.0.100:5000/v2/_catalog能看到json格式的返回值時,說明registry已經運行起來了。   

 

2.3  遠程訪問

   到目前爲止,docker registry 已經可以正常使用,且可以指定數據存儲位置。但也只能在本地使用,要想在遠程使用該 registry,就必須使用 TLS 來確保通信安全,就像使用 SSL 來配置 web 服務器。也可以強制 docker registry 運行在 insecure 模式,這種模式雖然配置起來要簡單一些,但很不安全,一般不建議使用。
這裏偷懶使用這個簡單的 insecure 模式,假設你在一個域名爲 test.docker.midea.registry.hub 的主機上運行 docker registry,步驟如下:
1,在你要遠程訪問 docker registry 的機器上,修改文件 /etc/default/docker 或 /etc/sysconfig/docker,具體是哪個取決於你的系統。
2,編輯裏面的 DOCKER_OPTS 選項,如果沒有這個選項字段,就添加一個。改成下面這樣的:
 

ADD_REGISTRY='--add-registry test.docker.midea.registry.hub:5000'  
DOCKER_OPTS="--insecure-registry test.docker.midea.registry.hub:5000"  
INSECURE_REGISTRY='--insecure-registry test.docker.midea.registry.hub:5000'

3、重啓你的 docker 守護進程

通過以上3步,你的這個機器就能遠程從 test.docker.midea.registry.hub 上運行的 docker registry 拉取鏡像了

2.4 本地安裝運行


有時候需要本地運行倉庫服務,可以通過源碼方式進行安裝。首先安裝Golang環境支持,以Ubuntu爲例,可以執行如下命令:
$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable
$ sudo apt-get update
$ sudo apt-get install golang
確認Golang環境安裝成功,並配置$GOPATH環境變量,例如/go。
創建$GOPATH/src/github.com/docker/目錄,並獲取源碼,如下所示:


$ mkdir -p $GOPATH/src/github.com/docker/
$ cd $GOPATH/src/github.com/docker/
$ git clone https://github.com/docker/distribution.git
$ cd distribution
將自帶的模板配置文件複製到/etc/docker/registry/路徑下,創建存儲目錄/var/lib/registry:


$ cp cmd/registry/config-dev.yml /etc/docker/registry/config.yml
$ mkdir -p /var/lib/registry
然後執行安裝操作:
$ make PREFIX=/go clean binaries
編譯成功後,可以通過下面的命令來啓動:
$ registry server /etc/docker/registry/config.yml
此時使用訪問本地的5000端口,看到返回成功(200 OK),則說明運行成功:
$ curl -i 127.0.0.1:5000/v2/
HTTP/1.1 200 OK

 

 

三. Registry v2認證模式


Docker Registry v2的認證模式和v1有了較大的變化,降低了系統的複雜度、減少了服務之間的交互次數,其基本工作模式:

 

具體交互過程包括如下步驟:
1)Docker Daemon或者其他客戶端嘗試訪問Registry服務器,比如pull、push或者訪問manifiest文件;
2)在Registry服務器開啓了認證服務模式時,就會直接返回401 Unauthorized錯誤,並通知調用方如何獲得授權;
3)調用方按照要求,向Authorization Service發送請求,並攜帶Authorization Service需要的信息,比如用戶名、密碼;
4)如果授權成功,則可以拿到合法的Bearer token,來標識該請求方可以獲得的權限;
5)請求方將拿到Bearer token加到請求的Authorization header中,再次嘗試步驟1中的請求;
6)Registry服務通過驗證Bearer token以及JWT格式的授權數據,來決定用戶是否有權限進行請求的操作。
當啓用認證服務時,需要注意以下兩個地方:

  •  
  • 對於Authentication Service,Docker官方目前並沒有放出對應的實現方案,需要自行實現對應的服務接口;
  • Registry服務和Authentication服務之間通過證書進行Bearer token的生成和認證,所以要保證兩個服務之間證書的匹配。


除了使用第三方實現的認證服務(如docker_auth、SUSE Portus等)外,還可以通過Nginx代理方式來配置基於用戶名密碼的認證。

 

四. Nexus3作爲私有鏡像倉庫


使用nexus3作爲私有倉庫是最簡單的方式。

4.1 、安裝

1.下載Nexus:
  下載最新版的nexus下載地址: https://www.sonatype.com/oss-thank-you-tar.gz
2.創建nexus文件夾並解壓:
  mkdir /nexus && cd /nexus
  tar -xvf   nexus-3.15.2-01-unix.tar.gz
3.使用java8啓動:
  修改bin/nexus :
  INSTALL4J_JAVA_HOME_OVERRIDE=/usr/java8/
  進入nexus-3.15.2-01/bin目錄下,執行./nexus start 命令啓動
  啓動成功後要等一會兒,8081端口才會起來 ,可以使用lsof -i:8081 命令查看端口占用情況。

4.安全起見,我們建立一個nexus用戶用來啓動nexus
   adduser nexus
   更改nexus文件夾的訪問權限更改爲nexus用戶
   sudo chown -R nexus:nexus  /nexus
   打開/nexus/bin/nexus.rc 文件, 修改啓動用戶如下
   run_as_user=”nexus”

5.如果你想更改默認的數據目錄,可以打開nexus的配置文件,修改-Dkaraf.data屬性。
   vi /nexus/nexus/bin/nexus.vmoptions
下面來一個例子

-Xms1200M
-Xmx1200M
-XX:+UnlockDiagnosticVMOptions
-XX:+UnsyncloadClass
-Djava.net.preferIPv4Stack=truer
-Dkaraf.home=.
-Dkaraf.base=.
-Dkaraf.etc=etc
-Djava.util.logging.config.file=etc/java.util.logging.properties
-Dkaraf.data=/nexus/nexus-data
-Djava.io.tmpdir=data/tmp
-Dkaraf.startLocalConsole=false

6. 修改端口號: etc/nexus-default.properties

 

 7:  supervisor啓動:

 [program:turing-nexus2]
command=/mnt/app/nexus/bin/nexus run
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/nexus
umask=022
user=appuser
stdout_logfile=/mnt/logs/turing-nexus2/server.log
stderr_logfile=/mnt/logs/turing-nexus2/error.log
environment=
serverurl=AUTO

 

4.2 、配置使用

訪問地址:http://192.168.10.50:18082/

使用域名:http://nexus.xxxxx.com  admin admin123

首次默認登陸賬號:admin admin123

nexus可以作用yum的私庫,maven私庫、nuget等,可以參見官方說明,我們這裏只是針對docker的私有鏡像進行配置

代理鏡像庫(proxy repository)的配置和訪問:在內網總是有下載hub.docker.com 的需求,可以通過配置nexus的代理模式來實現

3、nginx代理

配置host repository的HTTPS訪問:nginx代理

 

設置Docker Bearer Token Realm可用:

 

五、docker使用私有registry倉庫


 1、登陸:

     docker login xxxx.com#登陸
      需要輸入創建repository時指定的賬號和密碼 登陸成功後可以pull私有庫的鏡像。

 2、拉取鏡像:

       docker pull xxxx.com/nginx # 拉取xxxx.com上的nginx鏡像,如果沒有則拉取失敗
 3、提交本地鏡像nexus倉庫:

       創建好私有倉庫之後, 就可以使用 docker tag 來標記一個鏡像, 然後推送它到本地倉庫,別的機器上就可以下載下來了。 例如 標記鏡像:

     docker tag java8  xxxx.com/java8

         使用 docker push 上傳標記的鏡像使用 docker push 上傳標記的鏡像
4、上傳鏡像:

       docker push xxxx.com/java8

5、測試:

    1)使用curl http://xxxx.com/v2/_catalog能看到json格式的返回值時,說明registry已經運行起來了。

     2)# docker search  registry.xxxx.com/java8        
     INDEX     NAME      DESCRIPTION   STARS     OFFICIAL   AUTOMATED

6、保存私有倉庫的登陸信息文件位置:

     我們在命令行方式下,輸入docker login登陸成功後,會在 ~/.docker/目錄下生成一個config.json文件。打開後可以看到如下的內容:

# cat ~/.docker/config.json

{
        "auths": {
                "registry.xxxx.com": {
                        "auth": "cmVnaXN0cnktYWRtaW46cmVnaXN0cnktYWRtaW4="
                }
        }

}     

    如果不logout ,下次拉取鏡像就不再需要輸入賬號和密碼:

    這種方式,在kubernetes 中使用deployment定義一個pod,是不能下載鏡像成功的。

 

六、k8s使用私有倉庫


(後續章節我們講到)

通常情況下,在私有云環境中使用kubernetes時,我們要從docker registry拉取鏡像的時候,都會給docker daemo配置--insecure-registry屬性來告訴docker daemo我們所使用的docker registry是可信的,這樣才能從私有的docker registry中拉取鏡像,但是如果要使用nexus作爲kubernetes的鏡像倉庫的話,這種方式就不適用了,下面讓我們看看如何來使用nexus作爲kubernetes的鏡像倉庫。

1、kubenetes設置pause鏡像

由於在Kubenetes中是以pod而不是Docker容器管理單元,在kubelet創建pod的時候,還通過啓動一個名爲google_containers/pause的鏡像來實現pod概念。

Pause容器 全稱infrastucture container(又叫infra)基礎容器。其使用c語言編寫,官方使用的鏡像爲gcr.io/google_containers/pause-amd64:3.1

kubernetes中的pause容器主要爲每個業務容器提供以下功能:

PID命名空間:Pod中的不同應用程序可以看到其他應用程序的進程ID。

網絡命名空間:Pod中的多個容器能夠訪問同一個IP和端口範圍。

IPC命名空間:Pod中的多個容器能夠使用SystemV IPC或POSIX消息隊列進行通信。

UTS命名空間:Pod中的多個容器共享一個主機名;Volumes(共享存儲卷):

Pod中的各個容器可以訪問在Pod級別定義的Volumes。

 

我們可以給每臺node的kubelet服務啓動參數加上--pod_infra_container_image參數,指定pause鏡像地址。例如指定爲官方基礎鏡像:

 kubelet --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/ --v=2 --cgroup-driver=systemd --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice  --pod_infra_container_image=docker.io/mirrorgooglecontainers/pause-amd64:3.1

由於我們使用私有倉庫,需要將其下載,導出或者標記,再push到私有Docker registry中去。

docker pull mirrorgooglecontainers/pause-amd64:3.1

docker tag  da86e6ba6ca1 registry.xxxx.com/pause-amd64

docker push  registry.xxxx.com/pause-amd64

 

之後修改--pod_infra_container_image參數指定爲私有倉庫鏡像:

--pod_infra_container_image=registry.xxx.com/pause-amd64

然後重啓kubelet服務

 

2、設置k8s的Secret

k8s的Secret類型

Kubernetes提供了Secret來處理敏感信息,目前Secret的類型有3種:

  • Opaque:使用base64編碼存儲信息,可以通過base64 --decode解碼獲得原始數據,因此安全性弱。
  • kubernetes.io/dockerconfigjson:用於存儲docker registry的認證信息,作用於Docker registry(nexus),用戶下載docker鏡像認證使用。
  • kubernetes.io/service-account-token:用於被 serviceaccount 引用。serviceaccout 創建時 Kubernetes 會默認創建對應的 secret。Pod 如果使用了 serviceaccount,對應的 secret 會自動掛載到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目錄中。

3、k8s的registry認證Secret

當pod從私用倉庫拉取鏡像時,k8s集羣使用類型爲docker-registry的Secret來提供身份認證,創建一個名爲registry-key的Secret,執行如下命令:

$ kubectl delete secret registry-key
$ kubectl -n k8s-dev create secret docker-registry registry-key-secret \
--docker-server=registry.xxxx.com.com \
--docker-username=registry-admin \
--docker-password=registry-admin \
[email protected]

        


注意 -n k8s-dev爲指定命名空間,一般搭建k8s集羣時,建議新建一個命名空間來隔離資源。
檢查Secret: kubectl get secret registry-key-secret  -o yaml

通過 base64 對 secret 中的內容解碼:

也可以直接讀取 ~/.dockercfg 的內容來創建:

$ kubectl create secret docker-registry registry-key-secret   --from-file="~/.dockercfg"

 

4、配置和部署Pod

imagePullSecrets標籤指定拉取鏡像時的身份驗證信息

在創建 Pod 的時候,通過 imagePullSecrets 來引用registry-key-secret:指定拉取鏡像時的身份驗證信息

springboot-deployment.yml: 

apiVersion: v1
kind: Pod
metadata:
  name: springbootweb1
spec:
  containers:
    - name: springbootweb1
      image: registry.xxxx.com/springboot:latest
  imagePullSecrets:
    - name: registry-key-secret

 

 

問題


問題1:登陸出現401 Unauthorized

Error response from daemon: login attempt to https://registry.xxxx.com/v2/ failed with status: 401 Unauthorized

解決:Docker Bearer Token Realm可用:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章