博文大綱:
1、Docker鏡像的建立方法
1.基於已有鏡像建立
2.基於本地模板建立
3.基於Dockerfile建立
2、Docker的數據管理
1.數據卷
2.數據卷容器
3、Docker網絡通訊
1.端口映射
2.容器互聯html
Docker鏡像除了是Docker的核心技術以外,也是應用發佈的標準格式。一個完整的Docker鏡像能夠支撐一個Docker容器的運行,在Docker的整個使用過程當中,進入一個已經定型的容器以後,就能夠在容器中進行操做,最多見的操做就是在容器中安裝應用服務,若是要把已經安裝的服務進行遷移,就須要把環境及搭建的服務生成新的鏡像。nginx
建立最多見的三種方法:web
- 基於已有鏡像建立;
- 基於本地模板建立;
- 基於Dockerfile建立;
基於已有鏡像建立主要使用「docker commit」命令,其實質就是把一個容器裏面運行的程序及該程序的運行環境打包起來生成新的鏡像。docker
命令格式:shell
docker commit [選項] 容器ID/名稱 倉庫名稱:[標籤]
經常使用的選項:
-m:說明信息;
-a:做者信息;
-p:生成過程當中中止容器的運行;apache
方法以下:
(1)使用鏡像建立一個新的容器,並進行修改。vim
[root@localhost ~]# docker images //查看本地的Docker鏡像 REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/centos latest 0f3e07c0138f 6 weeks ago 220 MB [root@localhost ~]# docker run --privileged -d -it --name centos docker.io/centos init 794df7dc4cebeb43afb2a1d7cf424578a4f10c2344bcdb7208d6632609ce087c //使用centos鏡像生成一個名爲centos的容器,讓容器以root的身份權限加載init守護進程 [root@localhost ~]# docker exec -it centos /bin/bash //指定一個shell進入容器 [root@794df7dc4ceb /]# yum -y install vsftpd //在容器中安裝一個ftp服務 [root@794df7dc4ceb /]# systemctl start vsftpd //安裝完成後,啓動服務 [root@794df7dc4ceb /]# exit //退出容器
(2)使用「docker commit」命令建立一個新的鏡像。centos
[root@localhost ~]# docker commit -m "vsftpd" -a "lzj" centos lzj:ftp sha256:ccba2c39b90a56373139196c3dc079b6df5c7f4f280bc35a7f1abf578962b52 //基於剛纔建立的容器生成一個新的鏡像,名稱爲lzj:ftp
(3)建立完成後,查看本地鏡像是否已經有新生成的鏡像。緩存
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE lzj ftp ccba2c39b90a 57 seconds ago 279 MB docker.io/centos latest 75835a67d134 13 months ago 200 MB
經過導入操做系統模板文件能夠生成鏡像。模板能夠從OPENVZ開源項目下載,或者 https://wiki.openvz.org/Download/template/precreated ,優先使用OPENVZ開源項目那個連接。安全
其實,就把使用「docker load < 文件名」將一個文件導入成鏡像而已,這裏就很少介紹了!
除了手動生成docker鏡像以外,還可使用Dockerfile自動生成鏡像。Dockerfile是由一組指令組成的文件,其中每條指令對應Linux中的一條命令,Docker程序將讀取Dockerfile中的指令生成指定鏡像。
Dockerfile結構大體分爲4個部分:基礎鏡像信息、維護者信息、鏡像操做指令和容器啓動時候執行指令。Dockerfile每行支持一條指令,每條指令可攜帶多個參數,支持使用以「#」號開頭的註釋。
一個簡單的小例子:
[root@localhost ~]# vim Dokerfile FROM centos #第一行必須指明基於的基礎鏡像 MAINTAINER The CentOS project <cloud-ops@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有十幾條命令可用於構建鏡像,其中指令如圖:
Dockerfile經常使用的指令有:
1)FROM:構建鏡像基於哪一個鏡像; 2)MAINTAINER:鏡像維護者姓名或郵箱地址; 3)RUN:構建鏡像時運行的shell指令; 4)CMD:運行容器時執行的shell環境; 5)EXPOSE:聲明容器的服務端口(僅僅是聲明); 6)ENV:設置容器環境變量; 7)ADD:拷貝文件或目錄到容器中,若是是URL或壓縮包便會自動下載或自動解壓; 8)COPY:拷貝文件或目錄到容器中,跟ADD相似,但不具有自動下載或解壓的功能; 9)ENTRYPOINT:運行容器時執行的shell命令; 10)VOLUME:指定容器掛載點到宿主機自動生成的目錄或其餘容器; 11)USER:爲RUN、CMD、和ENTRYPOINT執行命令指定運行用戶; 12)WORKDIR:爲RUN、CMD、ENTRYPOINT、COPY和ADD設置工做目錄,意思爲切換目錄; 13)HEALTHCHECH:健康檢查; 14)ARG:構建時指定的一些參數;
編寫Dockerfile的注意事項
(1)RUN在building時運行,能夠寫多條; (2)CMD和ENTRYPOINT在運行container時,只能寫一條,若是寫多條,最後一條生效; (3)CMD在構建容器時能夠被COMMAND覆蓋,ENTRYPOINT不會被COMMAND覆蓋,但能夠指定——entrypoint覆蓋; (4)若是在Dockerfile文件中須要往鏡像中導入文件,則該文件必須在Dockerfile所在目錄或子目錄中; (5)每一個目錄下最好就只有一個Dockerfile,若是有多個Dockerfile文件時,使用Dockerfile生成鏡像時便須要使用「-f」來指定具體的Dockerfile文件; (6)指令必須所有爲大寫; (7)使用Dockerfile生成鏡像時,保證Dockerfile中所需的軟件、文件與Dockerfile在同一個目錄下;
案例:
[root@localhost ~]# mkdir apache [root@localhost ~]# cd apache/
[root@localhost apache]# vim Dockerfile FROM docker.io/centos MAINTAINER The CentOS Projects <cloud-ops@centos.org> RUN yum -y update RUN yum -y install httpd EXPOSE 80 ADD index.html /var/www/html/index.html ADD run.sh /run.sh RUN chmod 775 /run.sh RUN systemctl disable httpd CMD ["/run.sh"]
此Dockerfile文件使用的基礎鏡像是centos,因此要保證首先獲取此基礎鏡像,使用「docker pull docker.io/centos」 獲取鏡像,以後的容器運行纔會有效;
[root@localhost apache]# vim run.sh #!/bin/bash rm -rf /run/httpd/* //清理httpd的緩存 exec /usr/sbin/apachectl -D FOREGROUND //啓動apache服務 //啓動容器時,進程、腳本必須在前臺啓動
[root@localhost apache]# echo "weclome" > index.html //建立首頁文件 [root@localhost apache]# ls Dockerfile index.html run.sh //這三個文件最好是在同一目錄下
編寫完成Dockerfile及相關內容後,能夠經過「docker build」命令來建立鏡像。
命令格式:
docker build [選項] 路徑 //經常使用選項「-t」指定鏡像的標籤信息
[root@localhost apache]# docker build -t httpd:centos . 使用剛纔創鍵的Dockerfile 自動生成鏡像,最後必需要有一個「.」表示當前路徑
[root@localhost ~]# docker run -d -p 12345:80 httpd:centos ee9adf324443b006ead23f2d9c71f86d1a4eb73358fb684ee3a2d058a0ac4243 //使用新生成的鏡像加載到容器中運行 //「-p」選項實現從本地端口12345到容器中80端口的映射 [root@localhost web]# docker run -itd --name nginx centos:nginx nginx -g "daemon off;" //不進入容器,便可開啓容器中的Nginx服務
[root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ee9adf324443 httpd:centos "/run.sh" About a minute ago Up About a minute 0.0.0.0:12345->80/tcp admiring_bardeen //查看該鏡像已經在容器中的狀態
驗證訪問結果:
隨着創鍵的鏡像增多,就須要有一個保存鏡像的地方,這就是倉庫。目前有兩種倉庫:公共倉庫和私有倉庫。最方便的就是使用公共倉庫上傳和下載,下載公共倉庫的鏡像是不須要註冊的,可是上傳時,是須要註冊的。下面介紹如何建立私有倉庫。
方法以下:
[root@localhost ~]# docker pull registry:2 //下載registry:2的鏡像 [root@localhost ~]# docker run -itd --name registry --restart=always -p 5000:5000 -v /registry:/var/lib/registry registry:2 //-p:端口映射(前面是宿主機端口:後面是容器暴露的端口) //-v:掛載目錄(前面是宿主機的目錄:後面的是容器的目錄)自動建立宿主機的目錄 [root@localhost ~]# docker tag centos:nginx 192.168.1.1:5000/centos:nginx [root@localhost ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.1:5000 //修改本來的配置文件添加不安全的倉庫,地址是宿主機的IP地址與5000端口 [root@localhost ~]# systemctl daemon-reload [root@localhost ~]# systemctl restart docker //從新啓動docker服務 [root@localhost ~]# docker ps //確認registry容器正常運行 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2645c31b2306 registry:2 "/entrypoint.sh /etc…" 21 minutes ago Up 42 seconds 0.0.0.0:5000->5000/tcp registry [root@localhost ~]# docker push 192.168.1.1:5000/centos:nginx //上傳鏡像到私有倉庫
私有倉庫搭建完成,驗證成功!這時打開另外一臺docker主機下載進行測試:
[root@localhost ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecure-registry 192.168.1.1:5000 //修改本來的配置文件添加不安全的倉庫,地址是registry主機的IP地址與5000端口 [root@localhost ~]# systemctl daemon-reload [root@localhost ~]# systemctl restart docker //從新啓動docker服務 [root@localhost ~]# docker run -itd --name nginx 192.168.1.1:5000/centos:nginx nginx -g "daemon off;" //基於鏡像建立容器 [root@localhost ~]# docker inspect nginx //查看容器的詳細信息 [root@localhost ~]# curl 172.17.0.3 //測試訪問
私有倉庫這是纔算搭建完成!測試完成!
在Docker中,爲了方便查看容器內產生的數據或者將多個容器之間的數據實現共享,會涉及容器的數據管理操做。
管理Docker容器中的數據主要有兩種方式:數據卷和數據卷容器。
數據卷是一個供容器使用的特殊目錄,位於容器中,可將宿主機的目錄掛載到數據捲上,對數據卷的修改操做馬上可見,而且更新數據不會影響鏡像,從而實如今宿主機與容器之間的遷移,數據卷的使用相似於Linux下對目錄進行的掛載操做。
在「docker run」命令中使用「-v」選項能夠在容器內建立數據卷。屢次使用「-v」選項能夠建立多個數據卷。使用「--name」選項能夠給容器建立一個友好的自定義名稱。
[root@localhost ~]# docker run -itd -v /data1 -v /data2 --name web httpd:centos /bin/bash 27f2f2dad06de5685d253da6baab3808165e0f02fb99ed3fefbdd68e231f7c1b //使用httpd:centos鏡像建立一個名爲web的容器,並建立兩個數據卷掛載到/data1和/data2目錄上 [root@localhost ~]# docker exec -it web /bin/bash //進入容器並查看兩個目錄是否存在 [root@27f2f2dad06d /]# ls | grep data data1 data2
使用「-v」選項能夠在建立數據卷的同時,將宿主機的目錄掛載到數據捲上使用,以實現宿主機與容器之間的數據遷移。
注意:宿主機本地目錄的路徑必須使用絕對路徑,若是路徑不存在,Docker會自動建立相應的路徑。
[root@localhost ~]# docker run -itd -v /var/www:/data1 --name web1 httpd:centos /bin/bash ded73d50ff68ac43e789d8acf3bf9d0135f43bec28e99e14739e4085fb2ce802 //使用httpd:centos鏡像建立一個名爲web1的容器,並將宿主機的/var/www目錄掛載到容器的/data1目錄上 [root@localhost ~]# touch /var/www/file //宿主機本地建立測試文件 [root@localhost ~]# docker exec -it web1 /bin/bash [root@ded73d50ff68 /]# ls /data1 //容器中相應的目錄也會存在相應的文件 file
宿主機的目錄發生的變化會自動同步到容器中,相反也是同樣!
若是須要在容器之間共享一些數據,最簡單的方法就是使用數據卷容器。數據卷容器就是一個普通的容器,專門提供數據卷給其餘容器掛載使用。
[root@localhost ~]# docker run -it --volumes-from web1 --name db1 httpd:centos /bin/bash //使用實現建立好的容器web1,使用「--volumes-from」來掛載web1容器中的數據間到新的容器db1 [root@fb4b0f01b102 /]# ls /data1 file [root@fb4b0f01b102 /]# touch /data1/file1 //db1容器在/data1目錄下建立一個新的文件 [root@fb4b0f01b102 /]# exit exit [root@localhost ~]# docker exec -it web1 /bin/bash [root@ded73d50ff68 /]# ls /data1 //進入web1容器查看 file file1
這樣就能夠經過數據卷容器實現容器之間的數據共享。
經過這些機制,即便容器在運行過程當中出現故障,用戶也不用擔憂數據發生丟失。若是發生意外,只需快速從新建立容器便可!
注意:生產環境中最注重的就是存儲的可靠性,以及存儲的可動態擴展性,必定要在作數據卷時考慮到這一點,在這方面比較出色的還要數GFS文件系統了,我上面只是作了簡單的配置,若在生產環境中,必定要好好考慮,就好比上面作的鏡像卷容器,就能夠在宿主機本地掛載GFS文件系統,而後建立鏡像卷容器時,將掛載GFS的目錄映射到容器中的鏡像卷,這樣纔是一個合格的鏡像卷容器。
Docker提供了映射容器端口到宿主機和容器互聯機制來爲容器提供網絡服務。
在啓動容器的時候,若是不指定對應的端口,在容器外是沒法經過網絡來訪問容器內的服務的。Docker提供端口映射機制來將容器內的服務提供給外部網絡訪問,實質上就要將宿主機的端口映射到容器中,使得外部網絡訪問宿主機的端口能夠訪問容器內的服務。
實現端口映射,須要在運行「docker run」命令時使用「-P(大寫)」選項能夠實現隨機映射,Docker會隨機映射一個端口範圍在49000~49900的端口到容器內部開放的網絡端口,可是不是絕對的,也有例外不會映射到這個範圍內。這種狀況並非很經常使用。
[root@localhost ~]# docker run -d --name httpd -P httpd:centos //建立容器httpd,並隨即生成一個端口 52791358bfbb6d054e3d5ea65ad6e87c68c538328ceef66c7398571eddd2b066 [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 52791358bfbb httpd:centos "/run.sh" 8 seconds ago Up 7 seconds 0.0.0.0:32769->80/tcp httpd //查詢得知,內部的80端口映射到本機的32769端口
這種方法並不經常使用。通常都使用「-p(小寫)」指定要映射的端口。
[root@localhost ~]# docker run -d --name httpd -p 49888:80 httpd:centos //將容器的80端口映射到本機的49888端口 f015df59a80b2e7048f63dacebd35b75db033bcb3bb529074849912bc7e7003f [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f015df59a80b httpd:centos "/run.sh" 3 seconds ago Up 3 seconds 0.0.0.0:49888->80/tcp httpd
容器互聯是經過容器的名稱在容器間創建一條專門的網絡通訊隧道從而實現的互聯。
注意:容器互聯是經過容器的名稱來執行的,「--name」選項能夠給容器建立一個友好的名稱,這個名稱是惟一的,若是已經命名了一個相同名稱的容器,當要再次使用這個名稱的時候,需先使用「docker run」來刪除以前建立的同名容器。
[root@localhost ~]# docker run -tid -P --name w1 httpd:centos /bin/bash fb8f64661062565e48a969b30759eb781ffddc60913aa93ff6b63f098e8f2c6a //使用「docker run」命令建立容器A,指定名稱爲web1
[root@localhost ~]# docker run -tid -P --name w2 --link w1:w1 httpd:centos /bin/bash fda898cc44e1c5415679c92e7b2ab65f3dfb56a0bc5b8563086c988070a02a3a //使用「docker run」命令建立容器B,指定名稱爲web2,使用「--link」選項與web1互聯
[root@localhost ~]# docker exec -it w2 /bin/bash [root@fda898cc44e1 /]# ping w1 PING w1 (172.17.0.2) 56(84) bytes of data. 64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.051 ms 64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.072 ms //這時能夠看出web2容器已經和web1容器創建互聯關係
若是如今還要在加入一個容器C,使容器C與容器A和容器B進行互聯,進行一下操做:
[root@localhost ~]# docker run -dit -P --name w3 --link w1:w1 --link w2:w2 httpd:centos /bin/bash bfedb9d94d18d07af2eda92d06e176479e22f342cfad7f5d8b034116e05040fd //建立容器C,使其與容器A、容器B進行互聯 [root@localhost ~]# docker exec -it b3 /bin/bash [root@bfedb9d94d18 /]# ping w1 PING w1 (172.17.0.2) 56(84) bytes of data. 64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.052 ms 64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.166 ms ^C --- web1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.052/0.109/0.166/0.057 ms [root@bfedb9d94d18 /]# ping w2 PING w2 (172.17.0.3) 56(84) bytes of data. 64 bytes from web2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.051 ms 64 bytes from web2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.063 ms ^C --- web2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.051/0.057/0.063/0.006 ms //測試成功
———————— 本文至此結束,感謝閱讀 ————————