前文咱們聊了下docker的基礎使用方法,大概介紹了下docker的架構,管理鏡像、運行容器、管理容器的一些相關命令說明;回顧請參考http://www.javashuo.com/article/p-xcrzusri-bu.html;今天這邊博客主要來聊docker的鏡像的製做和分發,以及相關鏡像的操做和說明;html
前面咱們提到過docker最核心資源之一就是鏡像,鏡像就比如是咱們的應用程序,要想運行它,前提是要擁有它,並把它裝載操做系統上;而docker裏的鏡像就是把應用程序所依賴的庫、文件、環境等打包在一塊兒,組成一個靜態的鏡像文件;這樣一來有了這個鏡像,咱們就能夠把咱們本身的應用程序在任何有docker環境的主機上運行成容器;這也是docker受歡迎的緣由之一吧,解脫了程序員爲其應用程序而苦惱;node
docker鏡像包含了應用程序啓動所需的文件系統以及內容,其目的就是爲建立並啓動爲docker容器;那麼docker的鏡像究竟是怎麼構建的呢?咱們來看看下面的圖大概就會明白mysql
提示:docker鏡像採用分層構建的機制,最低層爲bootfs,該層的主要做用是用於系統引導的文件系統,包括bootloader和內核,容器啓動完成後會被卸載以節省內存資源;在bootfs之上的是rootfs,該層主要表現爲docker容器的根文件系統;傳統模式中,系統啓動之時,內核掛載rootfs時會首先將其掛載爲只讀模式,完成完整性自檢後在將其從新掛載爲讀寫模式;而docker中,rootfs有內核掛載爲只讀模式,然後經過聯合掛載技術額外掛載一個可寫成;以下圖所示linux
提示:位於下層的鏡像咱們稱爲父鏡像,最底層的鏡像稱其爲基礎鏡像;最上層爲可寫層,其下的全部層都是隻讀層;從上面的圖咱們也能夠看到,只有鏡像運行成容器之後纔會有可寫層的;也就是說可寫層屬於容器而不屬於鏡像;其實docker容器是共享下面鏡像層的,只有啓動爲容器後,各自的可寫層相互隔離;nginx
瞭解了docker的鏡像構建方式後,咱們在看看多個鏡像怎麼作到聯合掛載的?git
聯合掛載的技術要源於AUFS這個文件系統,該文件系統的全稱是advanced multi-layered unification filesystem翻譯過來就是高級多層統一文件系統;該文件主要做用是爲Linux文件系統實現「聯合掛載」;aufs的前身是unionfs,2006年由junjiro okajima開發;docker最初使用aufs做爲容器文件系統層,它目前仍做爲存儲後端之一,aufs的競爭產品是overlayfs,後者自從3.18版本開始被合併到Linux內核;docker的分層鏡像,除了aufs,docker還支持btrfs,devicemapper和vfs等,在ubuntu系統下,docker默認使用的aufs;而在早期centos7上用的是devicemapper;因此早期跑docker都跑在ubuntu上,緣由之一是ubuntu的內核版本較新,可以很好的兼容aufs文件系統;如今咱們在centos7上運行docker默認使用的是overlayfs2文件系統;以下所示程序員
提示:若是用運行docker建議backing filesystem 使用xfs文件系統,不要使用ext系列文件系統;github
瞭解了docker的文件系統後,在來講一下docker的鏡像倉庫web
docker啓動容器時,docker 服務端會試圖從本地獲取相關鏡像;本地鏡像不存在時,將會從docker默認的鏡像倉庫中下載指定鏡像並保持本地,而後再啓動爲容器;大體過程以下圖所示sql
提示:從上圖能夠了解到docker客戶端和服務端的一個工做流程,客戶端經過http協議向服務端發送指令,服務端首先從本地查找是否有對應版本的鏡像,若是有就啓動爲容器,若是沒有就會去默認的registry中下載對應版本的鏡像到本地,而後在啓動爲容器;對於docker服務端和registry來說他們都須要各自的存儲設備驅動來存儲鏡像;registry是用於保存docker鏡像,包括鏡像的層次機構和元數據;用戶能夠自建registry,也可以使用官方的docker hub;registry分類主要有Sponsor registry 第三方的registry,供客戶和docker社區使用;mirror registry 第三方的registry,只讓客戶使用;vendor registry 由發佈docker鏡像的供應商提供的registry;private registry 經過設有防火牆和額外的安全層的私有實體提供的registry;
registry主要包含了倉庫和索引;所謂倉庫就是由特定的docker鏡像的全部迭代版本組成的鏡像倉庫;一個registry中能夠存在多個repository,而對於repository來講能夠分爲頂層倉庫和用戶倉庫,頂層倉庫就是沒有斜線分割的倉庫,用戶倉庫是由用戶名加斜線分割再加倉庫名組成;每一個倉庫能夠包含多個tag標籤,每一個標籤對應一個鏡像;所謂索引(index)主要用於維護用戶賬號、鏡像的校驗以及公共命名空間的信息,相對於爲registry提供一個完整用戶認證等功能的檢索接口;因此咱們把registry理解爲存放docker鏡像倉庫的倉庫更爲準確;docker registry中的鏡像一般由開發人員製做,然後推送至公共或私有的倉庫上保持,供其餘人員使用;以下圖所示
瞭解了registry和repository的關係後,咱們在來講說docker hub;docker hub 是docker的官方倉庫,它主要有以下幾種特性;
一、image repositories,提供鏡像倉庫的功能
二、autometed builds,提供自動編譯功能,什麼意思呢?它支持咱們向上傳一個構建docker鏡像的源碼文件,它能夠根據這個源碼文件自動生成docker 鏡像;這個源碼文件叫dockerfile 主要用於編寫鏡像的構建過程的指令文件;
三、Webhooks,提供監控目標資源的變化實現根據目標監控對象上的資源變化而變化的一種機制;好比咱們可使用github和dockerhub聯合起來,開發人員經過git向github提交代碼(dockerfile),而後dockerhub就會一直盯着github上的資源,若是有變化,它就根據監控的資源變化而從新編譯成一個鏡像,相似這種功能;
四、organizations,支持建立組的方式對鏡像倉庫的訪問管理
五、github and bitbucket integration,支持將github和bitbucket添加到你當前的docker 鏡像工做流中;
瞭解了以上內容,咱們在dockerhub上去註冊一賬號,就能夠建立倉庫去存放咱們本身製做好的鏡像了;註冊賬號這裏我就很少說了,咱們來講一下怎樣製做鏡像和怎麼把鏡像推送到咱們本身的倉庫中去;
基於現有鏡像製做鏡像
一、拖鏡像到本地
[root@node1 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE centos 7 b5b4d78bc90c 2 weeks ago 203MB nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB [root@node1 ~]# docker image pull busybox:latest latest: Pulling from library/busybox d9cbbca60e5f: Pull complete Digest: sha256:836945da1f3afe2cfff376d379852bbb82e0237cb2925d53a13f53d6e8a8c48c Status: Downloaded newer image for busybox:latest docker.io/library/busybox:latest [root@node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest 78096d0a5478 9 days ago 1.22MB centos 7 b5b4d78bc90c 2 weeks ago 203MB nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB [root@node1 ~]#
二、運行busybox爲容器
提示:busybox容器默認提供的是一個模擬Linux不少命令的一個程序,自己沒有跑任何進程;因此咱們啓動容器必須得用交互式終端才行,不然容器啓動不起來;-it表示啓動爲交互式終端;
三、建立httpd的網頁文件
提示:到此咱們在容器內部的數據就準備好了。如今須要將咱們修改後的數據保存下來製做成鏡像分發給其餘人使用;
四、基於現有容器製造鏡像
[root@node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest 78096d0a5478 9 days ago 1.22MB centos 7 b5b4d78bc90c 2 weeks ago 203MB nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB [root@node1 ~]# docker container commit --help Usage: docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] Create a new image from a container's changes Options: -a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>") -c, --change list Apply Dockerfile instruction to the created image -m, --message string Commit message -p, --pause Pause container during commit (default true) [root@node1 ~]# docker container commit -a "qiuhom <qiuhom@admin123.com>" -p -m "this is test image" -c 'CMD ["/bin/sh","-c","/bin/httpd -f -h /var/www/web/html"]' b1 linux1874/myimg:v0.1 sha256:e408b1c6e04f0e5f5129989f35e6f613dec17d963770c4be8d6daa54343c5399 [root@node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE linux1874/myimg v0.1 e408b1c6e04f 5 seconds ago 1.22MB busybox latest 78096d0a5478 9 days ago 1.22MB centos 7 b5b4d78bc90c 2 weeks ago 203MB nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB [root@node1 ~]#
提示:-a表示指定做者信息,一般狀況下做者信息是帶郵箱地址的;-p 表示製做鏡像時暫停容器,這樣作主要是爲了數據統一,預防制做過程當中的數據增長;-m表示註解信息;-c表示指定容器內部運行的命令;從上面的結果看,咱們在本地就能夠看到咱們製做的鏡像;這裏須要特別注意一點的時,在docker容器裏運行的服務必須前臺運行,若是後臺運行會致使容器一啓動就退出了,緣由是容器內部自己就只有一個進程在跑,若是你後臺運行,就沒有進程在前臺,因此docker會認爲該容器已經宕機;其實咱們能夠理解爲容器內部前臺跑的程序是支撐整個容器爲運行態的重要骨架;
五、登陸本身dockerhub賬號
[root@node1 ~]# docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: linux1874 Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [root@node1 ~]#
六、推送鏡像到dockerhub中咱們本身的倉庫中去
[root@node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE linux1874/myimg v0.1 e408b1c6e04f 7 minutes ago 1.22MB busybox latest 78096d0a5478 9 days ago 1.22MB centos 7 b5b4d78bc90c 2 weeks ago 203MB nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB [root@node1 ~]# docker image push --help Usage: docker image push [OPTIONS] NAME[:TAG] Push an image or a repository to a registry Options: --disable-content-trust Skip image signing (default true) [root@node1 ~]# docker image push linux1874/myimg:v0.1 The push refers to repository [docker.io/linux1874/myimg] 4d567d38fed1: Pushed 1079c30efc82: Mounted from library/busybox v0.1: digest: sha256:6c2f6b7a0df5ca0a46cd46d858e9fd564169471e6715c0155027ac77672508f6 size: 734 [root@node1 ~]#
提示:製做的鏡像打標籤時,須要打成同倉庫名一致的名稱;到此咱們就把咱們製做好的鏡像推送到咱們的倉庫中去了
七、到dockerhub倉庫中查看是否存在咱們剛纔製做好的鏡像?
提示:能夠看到咱們有一個叫v0.1的鏡像;
八、另外開啓一主機,下載該鏡像,看看是否可以啓動爲容器,並提供httpd服務呢?
[root@docker_node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE wordpress latest c3fa1c8546fb 3 weeks ago 540MB mysql 5.7 f965319e89de 3 weeks ago 448MB httpd 2.4.37-alpine dfd436f9a5d8 17 months ago 91.8MB [root@docker_node1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@docker_node1 ~]# docker image pull linux1874/myimg:v0.1 Error response from daemon: pull access denied for linux1874/myimg, repository does not exist or may require 'docker login': denied: requested access to the resource is denied [root@docker_node1 ~]# docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: linux1874 Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [root@docker_node1 ~]# docker image pull linux1874/myimg:v0.1 v0.1: Pulling from linux1874/myimg d9cbbca60e5f: Pull complete ab68b1a31f97: Pull complete Digest: sha256:6c2f6b7a0df5ca0a46cd46d858e9fd564169471e6715c0155027ac77672508f6 Status: Downloaded newer image for linux1874/myimg:v0.1 docker.io/linux1874/myimg:v0.1 [root@docker_node1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE linux1874/myimg v0.1 e408b1c6e04f 20 minutes ago 1.22MB wordpress latest c3fa1c8546fb 3 weeks ago 540MB mysql 5.7 f965319e89de 3 weeks ago 448MB httpd 2.4.37-alpine dfd436f9a5d8 17 months ago 91.8MB [root@docker_node1 ~]# docker run --name myweb1 -d linux1874/myimg:v0.1 5bd8e32089c0431399c9f81bbbdcf946817d3f8ab32ffc1caf072e73ed9ef5d9 [root@docker_node1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5bd8e32089c0 linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 8 seconds ago Up 7 seconds myweb1 [root@docker_node1 ~]#
提示:由於我創建的是私有倉庫,因此只有登陸倉庫後才能夠下載;若是是公有倉庫就不須要登陸;從上面的信息看,咱們下載的鏡像已經下載到本地,並啓動爲容器了;
九、在宿主機上訪問容器內部httpd服務,看看是否可以響應咱們提供的主頁?
[root@docker_node1 ~]# docker container inspect -f "{{.NetworkSettings.Networks.bridge.IPAddress}}" myweb1 172.17.0.2 [root@docker_node1 ~]# curl http://172.17.0.2 this test file [root@docker_node1 ~]#
提示:能夠看到是能夠訪問到內部容器的httpd服務,響應給咱們的主頁也是咱們本身製做鏡像時提供的主頁文件;
到此基於現有容器製做鏡像、分發鏡像到倉庫的過程就測試完了;