博文大綱:html
- 1、docker鏡像的建立方法
一、基於已有鏡像建立
二、基於本地模板建立
三、基於dockerfile建立
四、搭建私有倉庫及其使用方法
docker鏡像是除了docker的核心技術以外,也是應用發佈的標準格式。一個完整的docker鏡像能夠支撐一個docker容器的運行,在docker的整個使用過程當中,進入一個已經定型的容器以後,就能夠在容器中進行操做,最多見的操做就是在容器中安裝應用服務,若是要把已經安裝的服務進行遷移,就須要把環境及搭建的服務生成新的鏡像。node
建立鏡像的方法有三種,分別是基於已有鏡像建立、基於本地模板建立及基於dockerfile建立。接下來會將這幾種方法依次寫下來。linux
基於已有鏡像建立主要是使用docker commit命令,本質上就是把一個容器裏面運行的程序及該程序的運行環境打包起來生成新的鏡像。docker
命令格式以下:apache
docker commit [選項] 容器ID/名稱 倉庫名稱:[標籤]
經常使用選項以下:json
- -m:說明信息;
- -a:做者信息;
- -p:生成過程當中中止容器的運行
基於已有鏡像建立新的鏡像舉例:vim
(1)啓動一個鏡像,在容器裏作修改,而後將修改後的容器提交爲新的鏡像,須要記住該容器的ID號,以下:centos
[root@localhost ~]# docker ps -a #查看當前運行的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c037e7a5734b docker.io/sameersbn/bind "/sbin/entrypoint...." 19 seconds ago Up 7 seconds 53/tcp, 10000/tcp, 53/udp hopeful_clarke [root@localhost ~]# docker exec -it c037e7a5734b /bin/bash #進入該容器 root@c037e7a5734b:/# echo 11111111111 > /etc/a.txt #隨便寫入一個文件 root@c037e7a5734b:/# exit #退出該容器 exit [root@localhost ~]# docker commit -m "newnamed" -a "ljz" c037e7a5734b docker:mynamed #使用docker commit命令建立一個新的鏡像 sha256:e178f320e4821642bed66d0e61e8a85eedd841cb8a3a84db3d38e7d92d844eae [root@localhost ~]# docker images | grep mynamed #查看新建立的鏡像 docker mynamed e178f320e482 11 seconds ago 323 MB [root@localhost ~]# docker create -it docker:mynamed /bin/bash #基於新建立的鏡像建立一個容器 dc37cf2d6ef754200aea067d7a15c83713f2488dac0913013373809633266f07 [root@localhost ~]# docker ps -a #獲取剛剛建立的容器ID號,下面標紅的就是 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 'dc37cf2d6ef7' docker:mynamed /sbin/entrypoint.... 11 seconds ago Created pensive_williams c037e7a5734b docker.io/sameersbn/bind /sbin/entrypoint.... 6 minutes ago Up 5 minutes 53/tcp, 10000/tcp, 53/udp hopeful_clarke [root@localhost ~]# docker start dc37cf2d6ef7 #啓動剛建立的容器 dc37cf2d6ef7 [root@localhost ~]# docker exec -it dc37cf2d6ef7 /bin/bash #查看在以前容器裏寫入的文件是否存在 root@dc37cf2d6ef7:/# cat /etc/a.txt 11111111111 #能夠看到新建立的容器中,有在以前容器中建立的文件,說明鏡像更改爲功
經過導入操做系統模板文件能夠生成鏡像,模板能夠從OPENVZ開源項目下載,或者 https://wiki.openvz.org/Download/template/precreated ,優先使用OPENVZ開源項目那個連接;緩存
基於本地模板建立舉例:bash
一、下載centos 7的迷你版系統模板,使用docker導入命令導入爲本地鏡像:
[root@localhost ~]# wget https://download.openvz.org/template/precreated/centos-7-x86_64-minimal.tar.gz #下載centos7的模板壓縮包 .................. #省略部份內容 [root@localhost ~]# ls | grep centos* #確認已經下載centos7的模板壓縮包 centos-7-x86_64-minimal.tar.gz [root@localhost ~]# cat centos-7-x86_64-minimal.tar.gz | docker import - docker:new #使用docker導入命令導入爲本地鏡像 sha256:c065d5c0571df48eba3b95b1302494b596cf9f67c24eacc82ff75a9e9c2b7622 [root@localhost ~]# docker images | grep new #查看導入的鏡像 docker new c065d5c0571d 56 minutes ago 435 MB #至此,可以使用這個鏡像建立容器並部署須要的功能,進行使用了。
dockerfile是由一組指令組成的文件,其中每條指令對應Linux中的一條命令,docker程序將讀取dockerfile中的指令生成指定鏡像。
dockerfile結構大體分爲四個部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時執行指令。dockerfile每行支持一條指令,每條指令可攜帶多個參數,支持使用「#」號開頭的註釋。
dockerfile中的配置項介紹:
[root@localhost ~]# docker tag docker:new centos7:system #將上面下載的centos 7迷你鏡像更改下名字及標籤,以便區分 [root@localhost ~]# docker images | grep system #確認基礎鏡像已經準備好(就是一個centos 7的迷你係統進行) centos7 system c065d5c0571d About an hour ago 435 MB [root@localhost ~]# vim Dockerfile #編輯一個Dockerfile文件,注意:文件名最好就是Dockerfile FROM centos #第一行必須指明基於的基礎鏡像(該鏡像必須存在) MAINTAINER The centos project <ljz@centos.org> #維護該鏡像的用戶信息 #如下是鏡像的操做指令 RUN yum -y update RUN yum -y install openssh-server RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key EXPOSE 22 #開啓22端口 CMD ["/usr/sbin/sshd","-D"] #啓動容器時執行指令
在編寫dockerfile時,有嚴格的格式須要遵循:第一行必須使用FROM指令指明所基於的鏡像名稱;以後使用MAINTAINER指令說明維護該鏡像的用戶信息;而後是鏡像操做相關指令,如RUN指令,每運行一條指令,都會給基礎鏡像添加新的一層;最後使用CMD指令來指定啓動容器時要運行的命令操做。
dockerfile有十幾條命令可用於構建鏡像,其中常見的指令以下:
dockerfile使用舉例——使用dockerfile建立apache鏡像並在容器中運行
(1)建立鏡像並加載到容器中運行:
[root@localhost ~]# mkdir apache #創建工做目錄 [root@localhost ~]# cd apache/ #切換至新建的目錄 [root@localhost apache]# vim Dockerfile #編寫dockerfile文件 FROM centos #基於的基礎鏡像centos MAINTAINER the centos project <ljz@163.com> #維護該鏡像的用戶信息 RUN yum -y update #使用yum進行更新 RUN yum -y install httpd #鏡像操做指令安裝apache軟件包 EXPOSE 80 #開啓80端口 ADD index.html /var/www/html/index.html #將本地的首頁文件index.html複製到鏡像中 ADD run.sh /run.sh #將本地的運行腳本run.sh複製到鏡像中 RUN chmod 775 /run.sh #賦予腳本執行權限 RUN systemctl disable httpd #設置apache服務不自行啓動 CMD ["/run.sh"] #啓動容器時執行腳本 #輸入上述信息後,保存退出 [root@localhost apache]# docker images | grep centos #確保本地有centos的基礎鏡像,由於在dockerfile文件中指定了該鏡像 centos7 system c065d5c0571d About an hour ago 435 MB [root@localhost apache]# vim run.sh #編寫執行腳本內容 #!/bin/bash rm -rf /run/httpd/* #清理httpd的緩存 exec /usr/sbin/apachectl -D FOREGROUND #啓動apache服務 [root@localhost apache]# echo "dockerfile test" >index.html #編寫一個首頁文件 [root@localhost apache]# ls #確保當前目錄下的文件有如下三個 Dockerfile index.html run.sh #當以上準備完成後,就可使用docker build命令來建立鏡像,以下: [root@localhost apache]# docker build -t httpd:centos . #注意上面命令的末尾有個「.」,表示當前路徑,若不加則會報錯。 #其中「-t」選項用來指定鏡像的標籤信息 Sending build context to Docker daemon 4.096 kB Step 1/10 : FROM centos Trying to pull repository docker.io/library/centos ... latest: Pulling from docker.io/library/centos .................. #省略部份內容,此處須要靜等幾分鐘,此時系統在執行dockerfile文件中的指令。 #若在顯示信息中有報紅的信息,只要配置文件無誤,通常屬於正常(是有關yum的信息)。 Removing intermediate container 81a3d6c9d3db Step 10/10 : CMD /run.sh ---> Running in 5cdc467fd874 ---> 5d56b826432d Removing intermediate container 5cdc467fd874 Successfully built 5d56b826432d #當出現以上提示,則表示新的鏡像已經建立成功了。 #在整個建立過程當中,能夠看到每運行一次dockerfile中的指令,都會以給初始鏡像加上新的一層。 [root@localhost apache]# docker run -d -p 81:80 httpd:centos #將新生成的鏡像加載到容器中運行。 #其中「-p」選項實現從本地端口81到容器中80端口的映射。 192cd783028dcb3013ebb40b65ba8450e695e424e700a13cb8a44bb84af3e71a [root@localhost apache]# docker ps -a #查詢容器是否運行 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 192cd783028d httpd:centos "/run.sh" About a minute ago Up About a minute 0.0.0.0:81->80/tcp gallant_khorana #省略部份內容
至此,能夠看到新生成的鏡像已經在容器中加載運行了,本機(宿主機,不是docker容器)的IP地址爲192.168.1.1,此時client訪問192.168.1.1的81端口,就至關於訪問了剛運行的容器的80端口,以下:
(2)將鏡像上傳到倉庫中:
隨着建立的鏡像增多,就須要有一個保存鏡像的地方,這就是倉庫,目前有兩種倉庫:公共倉庫和私有倉庫,公司的生產環境中大多數都是保存到私有倉庫的,最簡單的仍是在公共倉庫上下載鏡像,如果上傳鏡像至公共倉庫,還須要註冊並登錄,關於公共倉庫的上傳,能夠參考博文Docker的概念及安裝配置中的上傳鏡像部分。
那麼怎麼構建私有倉庫呢?可使用registry來搭建本地私有倉庫。以下:
[root@localhost ~]# docker search registry #查詢關鍵字「registry」 INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED docker.io docker.io/registry The Docker Registry 2.0 implementation for... 2679 [OK] ..................#省略部份內容 [root@localhost ~]# docker pull docker.io/registry #下載排名靠前的鏡像 ..................#省略部份內容 Status: Downloaded newer image for docker.io/registry:latest #下載成功 [root@localhost ~]# vim /etc/sysconfig/docker #修改docker配置文件指定私有倉庫URL,不然在自定義的私有倉庫中上傳鏡像時會報錯 # /etc/sysconfig/docker # Modify these options if you want to change the way the docker daemon runs OPTIONS='--selinux-enabled --insecure-registry=192.168.1.1:5000' #更改上面一行內容,其中的IP地址是做爲私有倉庫服務器的IP地址,這裏就是本機的IP地址。 ..................#省略部份內容 #修改完畢後保存退出 [root@localhost ~]# systemctl restart docker #重啓docker服務
使用下載好的registry鏡像啓動一個容器,默認狀況下倉庫存放於容器內的/tmp/registry目錄下,使用-v選項能夠將本地目錄掛載到容器內的/tmp/registry目錄下使用,這樣就不怕容器被刪除後鏡像也會隨之丟失。在本地啓動一個私有倉庫服務,監聽端口號爲5000。
注意:我本地有一個/data/registry目錄(掛載的是一個高可用的GFS文件系統,也可使用NFS,自行選擇便可,可是建議對於重要的數據存放目錄,必定要保證容量的動態擴展以及磁盤損壞形成數據丟失的問題),將要掛載到私有倉庫容器中的/tmp/registry目錄中用於存放上傳到私有倉庫的鏡像文件。
[root@localhost ~]# df -hT /data/registry/ #查看我這個目錄所使用的文件系統 文件系統 類型 容量 已用 可用 已用% 掛載點 node4:dis-stripe fuse.glusterfs 80G 130M 80G 1% /data/registry [root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry/:/tmp/registry docker.io/registry #啓動私有倉庫,並作端口映射到主機的5000端口,將本地的/data/registry目錄掛載到容器中的/tmp/registry目錄 #docker.io/registry是剛纔下載的私有倉庫鏡像。 a6bf726c612b826e203d6a5bc9eaba26c36195913d3ea546c2111ce290a5524d [root@localhost ~]# docker tag docker.io/registry 192.168.1.1:5000/registry #使用docker tag命令將要上傳的鏡像docker.io/registry改一下標記,其中的IP及端口爲固定的,不然沒法鏈接到私有倉庫 #由於在上面運行容器時,作了端口映射,將私有倉庫的端口號映射到了宿主機的5000端 口, #因此直接訪問宿主機的5000端口,就至關於訪問了私有倉庫。 [root@localhost ~]# docker images | grep 5000 #找到要上傳的鏡像 192.168.1.1:5000/registry latest f32a97de94e1 6 months ago 25.8 MB [root@localhost ~]# docker push 192.168.1.1:5000/registry #上傳至剛剛運行的私有倉庫 The push refers to a repository [192.168.1.1:5000/registry] 73d61bf022fd: Pushed 5bbc5831d696: Pushed d5974ddb5a45: Pushed f641ef7a37ad: Pushed d9ff549177a9: Pushed latest: digest: sha256:b1165286043f2745f45ea637873d61939bff6d9a59f76539d6228abf79f87774 size: 1363 #下面再上傳一個鏡像,進行測試。 [root@localhost ~]# docker images | grep mynamed #就上傳它了 docker mynamed e178f320e482 4 hours ago 323 MB [root@localhost ~]# docker tag docker:mynamed 192.168.1.1:5000/named:test #老規矩,必須改倉庫名,注意:若標籤不是默認的latest,那麼還須要在倉庫名後面接上標籤名 [root@localhost ~]# docker images | grep 192.168.1.1:5000/named #肯定更改爲功 192.168.1.1:5000/named test e178f320e482 4 hours ago 323 MB [root@localhost ~]# docker push 192.168.1.1:5000/named:test #上傳至私有倉庫 The push refers to a repository [192.168.1.1:5000/named] c756b9ec7fb0: Pushed 7d8d01394159: Pushed 72b7cd87d69b: Pushed 3be48ef75683: Pushed 9b28c58ad64b: Pushed 75e70aa52609: Pushed dda151859818: Pushed fbd2732ad777: Pushed ba9de9d8475e: Pushed test: digest: sha256:44894a684eac72a518ae5fa66bcbe4e4a9429428ef7ac6f4761022f8ac45ac5f size: 2403
至此,測試就完畢了,可是,如何證實私有倉庫使用的是本地的/data/registry這個目錄呢?以及如何查看上傳的鏡像呢?(上傳至私有倉庫的鏡像是沒法使用普通的ls命令查看的)。
[root@localhost ~]# df -hT /data/registry/ #先查看本地/data/registry/ 掛載的文件系統 文件系統 類型 容量 已用 可用 已用% 掛載點 node4:dis-stripe fuse.glusterfs 80G 130M 80G 1% /data/registry [root@localhost ~]# docker exec -it a6bf726c612b /bin/sh #進入私有倉庫的容器中,該容器沒有/bin/bash,因此使用的是/bin/sh。 / # df -hT /tmp/registry/ #查看發現,該目錄掛載的和宿主機掛載的文件系統是同一個,說明沒問題。 Filesystem Type Size Used Available Use% Mounted on node4:dis-stripe fuse.glusterfs 80.0G 129.4M 79.8G 0% /tmp/registry ——————————我是分割線—————————— #那麼如何查看上傳至私有倉庫的鏡像呢?請看下面: [root@localhost ~]# curl -XGET http://192.168.1.1:5000/v2/_catalog #查看已經上傳的鏡像,能夠看到剛剛上傳的那兩個鏡像 {"repositories":["named","registry"]} #只知道鏡像名還不夠,若要下載,還須要鏡像對應的標籤,那麼怎麼查看某個鏡像的標籤呢? [root@localhost ~]# curl -XGET http://192.168.1.1:5000/v2/named/tags/list #就這樣查看咯,上面URL路徑中的named就是鏡像名,查看的就是鏡像named對應的標籤 {"name":"named","tags":["test"]} [root@localhost ~]# docker pull 192.168.1.1:5000/named:test #將私有倉庫中的鏡像下載下來 #前面必須指定私有倉庫的訪問地址,就是上傳時的名字是什麼,下載時就是什麼,哪怕查詢的鏡像名中沒有IP地址。 Trying to pull repository 192.168.1.1:5000/named ... sha256:44894a684eac72a518ae5fa66bcbe4e4a9429428ef7ac6f4761022f8ac45ac5f: Pulling from 192.168.1.1:5000/named Digest: sha256:44894a684eac72a518ae5fa66bcbe4e4a9429428ef7ac6f4761022f8ac45ac5f Status: Downloaded newer image for 192.168.1.1:5000/named:test
附加:
若須要在其餘服務器上下載私有倉庫的鏡像,須要在那個其餘服務器上執行如下命令,以便指定私有倉庫服務器地址:
[root@node1 ~]# echo '{ "insecure-registries":["xxx.xxx.xxx.xxx:5000"] }' > /etc/docker/daemon.json #其中xxx.xxx.xxx.xxx:5000表明訪問私有倉庫的IP地址及端口,根據本身的服務器狀況來定 [root@node1 ~]#systemctl restart docker #重啓docker服務
上面的方法是我百度到的,親測有效,也但是嘗試下這種方法(我沒試過):
[root@node1 ~]# vim /etc/sysconfig/docker #修改docker配置文件指定私有倉庫URL # /etc/sysconfig/docker # Modify these options if you want to change the way the docker daemon runs OPTIONS='--selinux-enabled --insecure-registry=192.168.1.1:5000' #修改此行 [root@node1 ~]#systemctl restart docker #重啓docker服務
———————— 本文至此結束,感謝閱讀 ————————