前言
首先試想這樣一個場景:當在自己的機器上(docker中)構建了mysql鏡像,eureka鏡像等等微服務鏡像,這些鏡像有可能需要放到其他的機器上docker環境中去運行,實行分布式架構部署。但如何把這些鏡像共享到其他機器上去呢?可能很多小伙伴想到的是使用docker 的save和load命令或docker export和import命令。除此之外,還有更好的解決方案,就是這章要講的使用registry這個工具。使用registry可以很方便的在團隊內部,或者公司內部,在不同的linux主機上分享鏡像。
registry的作用就是共享鏡像。
一、使用docker命令導入導出鏡像
在講使用registry私服共享鏡像之前,先講如何使用docker命令共享鏡像,肯定是因為使用這些命令在某些情況下有局限性。
使用docker命令導入導出容器有兩種方式:
一種是使用save和load命令,另一種是使用export和import命令。需要注意的是這兩種方法不可混用。
#使用docker save和load命令 docker save ubuntu:load>root/ubuntu.tar docker load<ubuntu.tar # 使用docker export和import命令 docker export 98ca35> ubuntu.tar cat ubuntu.tar | sudo docker import - ununtu:import
可點擊下面四個命令,進入官網查看對該命令的詳細介紹,這里就不一一展開。
docker save、docker load、docker export、docker import。
使用docker命令進行導入和導出的局限性:
- 不知道對方是使用docker save還是docker export生成的tar文件
- 當鏡像更新比較頻繁時(如在測試階段,集成測試時),需要頻繁的去生成tar文件,並進行傳輸。如果是只傳給一個人,實在要忍,或許你能忍,如果是需要對多個人傳輸,頻繁生成tar文件,並且有多個版本時,你還能忍嗎?
有沒有更好的解決方案?當然有,那就是這章的主角,docker私服Registry。
二、Docker私服Registry安裝
# regisry鏡像下載 $ sudo docker pull registry c87736221ed0: Pull complete 1cc8e0bb44df: Pull complete 54d33bcb37f5: Pull complete e8afc091c171: Pull complete b4541f6d3db6: Pull complete Digest: sha256:3b00e5438ebd8835bcfa7bf5246445a6b57b9a50473e89c02ecc8e575be3ebb5 Status: Downloaded newer image for registry:latest # 安裝並運行regisry,端口映射為5000 $ sudo docker run -d --name=registry -p 5000:5000 registry 72ceb5dc167ea9a50c92dbf46f8b06d5ecd5222377d440174e4f4f7a7da9049d
通過瀏覽器訪問registry的入口,http://192.168.31.181:5000/v2/_catalog,可以看到返回的repositories的結果中是空的,也就是docker私服registry中,並沒有私服鏡像。
三、修改docker配置,讓docker信任registry地址
已經安裝好了registry,接着就是把docker中的鏡像,傳到regisry。但是,由於docker是沒有對registry開放權限,所以需要修改配置,讓docker信任regisry。
修改/etc/docker/daemon.json文件,添加:"insecure-registies":["192.168.31.181:5000"]。由於docker和registry是在同一台主機中,所以這里的registry地址也是本機地址。如果是要往別的主機的registry中上傳鏡像,可加入其它主機的ip地址。添加之后重啟docker,這時docker就信任regisry地址了。
$ sudo vi /etc/docker/daemon.json { # ustc的加速源 "registry-mirrors": ["https://nrbewqda.mirror.aliyuncs.com"],#由於該文件是個json格式的文件,所以需要先在這行最后面添加一個, # 讓docker信任192.168.31.181:5000registry私服地址 "insecure-registries":["192.168.31.181:5000"] } # 重啟docker,如果docker中服務較多,重啟操作,可能需要很久 $ sudo systemctl restart docker
四、上傳鏡像到regisry
上傳鏡像到regisry有兩種方式:
- 手動上傳
- 利用DockerMaven插件自動上傳
五、手動上傳鏡像到私服Registry
上傳鏡像到registry命令:docker tag 本地鏡像REPOSITORY名稱 registry地址/registry中的名稱
$ sudo docker tag eureka 192.168.31.181:5000/eureka $ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE ... 192.168.31.181:5000/eureka latest 9b410097b49e 44 hours ago 645MB eureka latest 9b410097b49e 44 hours ago 645MB ...
命令詳解:
docker tag : 給鏡像打標簽
eureka :本機docker本地倉庫中的一個REPOSITORY名為eureka的鏡像
192.168.31.181:5000/eureka :registry私服地址/私服地址中該鏡像的名稱為eureka
在上面通過docker images的輸出結果可以看到,可以看到多了一個REPOSITORY名為192.168.31.181:5000/eureka的鏡像,而且該鏡像的IMAGE ID以及其他,和REPOSTIRY名為eureka的鏡像的IMAGE ID以及其他都是一模一樣的。表明該兩個鏡像是一樣的。
然后通過docker push命令上傳剛剛的192.168.31.181:5000/eureka鏡像到私服registry,出現如下結果,表示已經上傳了該鏡像到私服registry中。
$ sudo docker push 192.168.31.181:5000/eureka The push refers to repository [192.168.31.181:5000/eureka] 0fd51de780a4: Pushed c302e69bdee3: Pushed dd836de89ae0: Pushed d69483a6face: Pushed latest: digest: sha256:6ddce0d73923b3a6efcf5892f239c48c8197890892b2cbeb9b1f37d10fb070fa size: 1161
========================================
提示:
如果運行上面的命令報connect:connection refused錯誤,那是因為剛重啟了registry,而regisry是安裝在docker中的,重啟docker之后,registry是出來停止狀態的,需要重啟registry。重啟registry的命令為:
$ sudo docker start registry
然后再執行上面的push命令。
========================================
如何確認192.168.31.181:5000/eureka鏡像是否上傳到了私服registry中呢?
可通過瀏覽器訪問私服registry的入口地址:http://192.168.31.181:5000/v2/_catalog
為什么私服registry中的名稱是eureka?還記得上面寫的docker tag命令嗎?
六、 利用DockerMaven插件自動鏡像上傳到私服Registry
手動上傳鏡像到私服registry,有個前提,那就是需要上傳的鏡像(通過docker tag命令之前的鏡像)必須是在docker的本地倉庫(也就是通過docker images命令中可以查看到)。
如果在docker的本地倉庫中還沒有鏡像,那么手動上傳鏡像到私服registry,需要做兩步,第一步:打包微服務項目並上傳到docker本地倉庫,並生成鏡像;第二步:通過docker tag命令和docker push命令上傳鏡像到私服registry。其實,這不是兩步,而是四五步。
1.為了演示自動打包項目和上傳鏡像,需要先刪除正在運行的鏡像,實際操作中可省略此步
由於需要演示利用DockerMaven插件自動打包項目、自動生成鏡像和上傳到私服,所以需要刪除掉某個正在運行的項目鏡像。
以zuul鏡像為例,來講解如何刪除zuul鏡像
# 查看所有zuul容器(運行中的和非運行中的) $ sudo docker ps -a | grep zuul a959a9465e7c zuul "/.r/r java -jar /ap…" 8 hours ago Exited (143) About an hour ago r-microservice-zuul-1-c8c7c48d # 可以看到zuul的STATUS為Exited表示已經是停止狀態,如果STATUS為UP,則表示是運行狀態,需要先停止 # 停止運行中的zuul容器,a959a9465e7c為zuul的CONTAINER ID # 如果有多個運行中的zuul容器,可在stop命令后面跟上多個CONTAINER ID,中間以空格隔開 $ sudo docker stop a959a9465e7c a959a9465e7c # 刪除zuul容器,如果有多個zuul容器,可在rm命令后面跟上多個CONTAINER ID,中間以空格隔開 $ sudo docker rm a959a9465e7c a959a9465e7c # 查看zuul鏡像,鏡像只可能有一個 $ sudo docker images | grep zuul zuul latest ffed513f7188 42 hours ago 642MB # 刪除zuul鏡像 $ sudo docker rmi zuul Untagged: zuul:latest Deleted: sha256:ffed513f7188562d2ee9544ff369ebe0472977295ea5ba83a32261d45f98e517 Deleted: sha256:eee67d5f43adf92a58cc0cad84a1e5f02f9c962e8b8ddfc9fc68275c4af12305 Deleted: sha256:6fc9d1be85a095edb7342f99a57669dab11e82dbb5b913f1f1a081ac501112ea
2.利用DockerMaven插件自動上傳鏡像到Registry
下面就講利用DockerMaven插件,一步搞定項目的打包、上傳到linux系統、生成docker鏡像,執行docker tag和push到私服registry。在docker微服務部署之:五、利用DockerMaven插件自動構建鏡像中,已經講了利用DockerMaven插件自動構建鏡像。
方法一
首先,需要修改demo_zuul項目的pom.xml文件,將configuration的imageName標簽中鏡像名前面加上私服registry的地址192.168.31.181:5000/即可。
... <configuration> <!-- 下面為此次修改的地方,在原來的zuul前,添加了192.168.31.181:5000/ --> <imageName>192.168.31.181:5000/zuul</imageName> <!-- 上面為此次修改的地方 --> <baseImage>jdk1.8</baseImage> ...
然后點擊idea左小角的Terminal窗口,把demo_zuul項目,拖動到該窗口(或者輸入 cd demo_zuul),然后執行mvn clean package docker:build -DpushImage
命令詳解:
cd demo_zuul :在當前的目錄....\demo_parent,進入子目錄(zuul項目的目錄)demo_zuul
mvn clean package :將demo_zuul項目打成jar包
docker:build :將jar包上傳到linux主機,並通過Dockerfile配置生成鏡像到docker的本地倉庫
-D :代表增加一個參數
pushImage :參數名為pushImage,即為同時將本地倉庫中的zuul鏡像,上傳到私服registry(192.168.31.181:5000),並命名私服registry中的鏡像名為pom.xml中imageName標簽中的zuul
通過docker images名稱查看鏡像
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.31.181:5000/zuul latest 09449796276f 3 minutes ago 642MB
刷新registry
方法二
原有demo_zuul項目中的pom.xml文件不動,復制該pom.xml文件,重命名為一個pom_registry.xml的pom文件。修改pom_registry.xml文件中的內容:
... <configuration> <registryUrl>192.168.31.181:5000</registryUrl> <pushImage>true</pushImage> <!-- article的名稱為demo_zuul,如果鏡像名不是用zuul,而是用demo_zuul,可修改imageName的內容為:192.168.31.181:5000/${project.artifactId} <imageName>192.168.31.181:5000/zuul</imageName> <baseImage>jdk1.8</baseImage> ...
然后點擊idea左小角的Terminal窗口,把demo_zuul項目,拖動到該窗口(或者輸入 cd demo_zuul),然后執行mvn -f pom_registry.xml clean package docker:build
通過兩個pom.xml文件,當只需要把鏡像放到本地倉庫時,通過mvn clean package docker:build執行即可。而需要把鏡像上傳到私服時,通過mvn -f pom_registry.xml clean package docker:build即可。
寫給自己:有待完善的地方:
- 把該篇文章分為兩個文章:一是把構建私服,弄成兩台服務器,並顯示如何從私服中下載鏡像
- 把利用DockerMaven自動構建鏡像,演示在一個開源項目中修改pom文件,並自動上傳到私服。