Docker容器進階--建立映象、資料管理、網路、儲存型別
一、Docker映象建立方法--基於已有映象、基於本地模板;
基於已有映象:
1.準備映象:
2.準備容器:
3.將容器建立成為docker映象檔案:
基於本地模板:
1.下載本地作業系統模板:
https://download.openvz.org/template/precreated/ ##openvz開源專案
2.上傳模板,匯入到docker映象中:
[[email protected] ~]# ls ubuntu-14.04-x86_64-minimal.tar.gz
ubuntu-14.04-x86_64-minimal.tar.gz
3.使用映象建立容器:
二、Docker映象建立方法--基於dockerfile建立;
概述:除了手動生成docker映象之外,還可以通過dockerfile自動生成映象,dockerfile是由一組指定組成的檔案,其中每條指令對應linux中的一條命令,docker程式將讀取dockerfile中的指令生成指定映象;
結構:
1.基礎映象資訊;
2.維護者資訊;
3.映象操作指令;
4.容器啟動時執行指令;
規則:dockerfile每行支援一條指令,每條指令可攜帶多個引數,支援使用以#號開頭的註釋;
樣例檔案:
註解:
FROM 映象 |
指定一個基礎的映象源,在此基礎上,進行封裝; |
MAINTAINER 作者 |
指定新映象的作者 |
RUN 命令 |
在所基於映象的基礎上執行命令並且提交到新的映象中; |
WORKDIR 目錄位置 |
類似於cd命令,更改執行命令時的基礎環境; |
EXPOSE 埠號 |
指定映象建立後容器開啟時中監聽的埠,用於外界宿主機互聯訪問; |
ENV 環境變數 變數值 |
設定容器的環境變數的值,被後邊的RUN所使用; |
ADD 原始檔 /源目錄 目標檔案 /目標目錄 |
將宿主機的檔案或者目錄複製到映象的位置,注意:宿主機的檔案或者目錄必須與Dockerfile檔案位於同位置,如若原始檔是一個壓縮包,會自動解壓,原始檔可以是一個URL; |
COPY 原始檔 /源目錄 目標檔案 /目標目錄 |
與ADD功能類似,注:壓縮包不能自動解壓,也不能訪問網路URL資源; |
VOLUME ["目錄"] |
實現資料卷資源持久化,將宿主機的目錄資源掛載到容器中; |
USER 使用者名稱 |
指定執行該容器的使用者; |
CMD ["命令","引數1","引數2"] |
指定容器在開啟時載入的命令,通常設定為一些自啟動的服務; |
ONBUILD |
指定當前映象作為其他新映象建立時指定基礎映象時,所需要指定的命令; |
在編寫dockerfile時,有嚴格的格式需要遵循:
1.第一行必須使用FROM指定所基於映象名稱;
2.之後使用MAIN指定映象的使用者資訊;
3.然後都是映象操作相關指令,如RUN、ADD等,每執行一條,就會給基礎映象新增上新的一層;
4.最後指定CMD指令,用來指定容器執行時執行的命令操作;
案例:
1.編輯Dockerfile檔案:
[[email protected] ~]# mkdir apache
[[email protected] ~]# cd apache/
[[email protected] apache]# vi Dockerfile
FROM centos
MAINTAINER The Centos Project <[email protected]>
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 755 /run.sh
CMD ["/run.sh"]
2.準備Dockerfile檔案中呼叫的指令碼:
[[email protected] apache]# vi run.sh
#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND
[[email protected] apache]# echo "welcome to docker" >index.html
3.使用Dockfile檔案生成映象:
4.使用已經存在的映象檔案建立新的容器:
5.使用docker節點測試訪問容器的httpd服務:
6.將容器的80埠對映到docker節點的8080埠進行釋出,外網客戶端測試連線:
7.將容器的當前狀態製作成為映象檔案:
8.將上述映象檔案上傳到docker hub公共倉庫:
三、構建本地私有倉庫:
概述:搭建本地私有倉庫容器,進行存放本地映象;
1.下載私有倉庫映象:
2.編輯json檔案指定私有倉庫http地址和埠:
[[email protected] ~]# vi /etc/docker/daemon.json
{"insecure-registries": ["192.168.100.101:5000"]}
[[email protected] ~]# systemctl restart docker
3.使用下載好的私有倉庫的映象檔案建立容器:
選項:-v /tmp/registry指定私有倉庫容器中存放映象的位置;
/data/registry 將私有倉庫容器中的上述位置對映到docker節點的本地目錄;
4.上傳映象檔案到私有倉庫容器中並刪除映象檔案驗證;
四、Docker的資料管理:
概述:在docker中,為了方便檢視容器內產生的資料或者將多個容器內的資料進行共享,就會涉及到容器的資料管理概念;
方式:
1.資料卷:data volumes
2.資料卷容器:data volumes containers
方式一:資料卷
概述:資料卷是供容器使用的特殊目錄,位於容器中,可將宿主機的目錄掛載到資料捲上,對資料卷的修改操作立即可見,並且更新資料不會影響映象,從而實現資料在宿主機與容器之間的遷移,資料卷的使用類似於linux系統中的mount操作;
1.建立資料卷的容器基於centos映象:
[[email protected] ~]# docker run -itd -v /linuxfan/data1:/data1 -v /linuxfan/data2:/data2 --name linuxcon centos /bin/bash
b43ef13d7ce8f57ddafe3aa2d35e497fe5947c92aa1123502c3e389e16698119
[[email protected] ~]# docker ps |grep linuxcon
b43ef13d7ce8 centos "/bin/bash" 15 seconds ago Up 15 seconds linuxcon
[[email protected] ~]# ls /linuxfan/
data1 data2
選項:-v指定容器內的資料卷,將本地目錄/linuxfan/data1和/linuxfan/data2掛載到容器目錄/data1和/data2中;
2.連線容器,檢視資料卷目錄:
[[email protected] ~]# docker exec -it b43ef13d7ce8 /bin/bash
[[email protected] /]# ls -ld /data1/
drwxr-xr-x 2 root root 6 Sep 14 22:53 /data1/
[[email protected] /]# ls -ld /data2/
drwxr-xr-x 2 root root 6 Sep 14 22:53 /data2/
[[email protected] /]# exit
3.在宿主機建立檔案驗證容器內的檔案變化:
[[email protected] ~]# touch /linuxfan/data1/data1.file
[[email protected] ~]# touch /linuxfan/data2/data2.file
[[email protected] ~]# docker exec -it b43ef13d7ce8 /bin/bash
[[email protected] /]# ls /data1/
data1.file
[[email protected] /]# ls /data2/
data2.file
[[email protected] /]# exit
4.在容器內建立檔案驗證宿主機內的檔案變化:
[[email protected] ~]# docker exec -it b43ef13d7ce8 /bin/bash
[[email protected] /]# touch /data1/data1.txt
[[email protected] /]# touch /data2/data2.txt
[[email protected] /]# exit
exit
[[email protected] ~]# ls /linuxfan/data1/
data1.file data1.txt
[[email protected] ~]# ls /linuxfan/data2/
data2.file data2.txt
方式二:資料卷容器
概述:資料卷容器就是一個普通的容器,專門提供資料卷給其他容器掛載使用;
使用方法:首先需要建立一個容器作為資料卷(可以在方式一資料卷的基礎上),之後在其他容器建立時使用--volumes-from掛載源資料卷容器使用,如此就可以實現多個容器之間的資料共享;
1.基於centos映象建立容器linuxcon-1,建立時指定linuxcon容器作為資料卷容器;
[[email protected] ~]# docker run -itd --volumes-from linuxcon --name linuxcon-1 centos /bin/bash
e4b9e0ef5063133aaf088cbc03b10c6788d21974c91b4f2c20f649f34f576b5e
[[email protected] ~]# docker ps |grep linuxcon
e4b9e0ef5063 centos "/bin/bash" 7 seconds ago Up 6 seconds linuxcon-1
b43ef13d7ce8 centos "/bin/bash" 11 minutes ago Up 11 minutes
2.進入linuxcon-1容器,檢視目錄是否存在;
[[email protected] ~]# docker exec -it e4b9e0ef5063 /bin/bash
[[email protected] /]# ls -ld /data1/
drwxr-xr-x 2 root root 39 Sep 14 22:57 /data1/
[[email protected] /]# ls -ld /data2/
drwxr-xr-x 2 root root 39 Sep 14 22:58 /data2/
[[email protected] /]# exit
3.在宿主機和linuxcon容器分別建立檔案驗證通過“宿主機--linuxcon資料卷容器--linuxcon-1”容器是否同步資料;
[[email protected] ~]# touch /linuxfan/data1/data1.bak
[[email protected] ~]# docker exec -it b43ef13d7ce8 /bin/bash
[[email protected] /]# touch /data2/data2.bak
[[email protected] /]# exit
exit
[[email protected] ~]# docker exec -it e4b9e0ef5063 /bin/bash
[[email protected] /]# ls /data1/
data1.bak data1.file data1.txt
[[email protected] /]# ls /data2/
data2.bak data2.file data2.txt
[[email protected] /]# exit
五、Docker的網路管理;
網路模式:
1.Bridge模式:預設的網路模式,在啟動docker程序後,宿主機會建立名為docker0的虛擬網橋,ip地址為172.17.0.1,所有容器的預設網路會自動獲取一個172.17.0.0網路的地址,實際上宿主機在此模式預設自動做了一條NAT轉換規則並且開啟路由轉發;
2.Host模式:如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的IP等,而是使用宿主機的IP和埠。但是,容器的其他方面,如檔案系統、程序列表等還是和宿主機隔離的;
3.Container模式:指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網絡卡,配置自己的 IP,而是和一個指定的容器共享 IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。兩個容器的程序可以通過 lo 網絡卡裝置通訊;
4.None模式: Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網絡卡、IP、路由等資訊。需要我們自己為Docker容器新增網絡卡、配置IP等;
配置網路模式:
- 配置預設橋接模式:預設;
- 配置host模式:使用 --net=host指定;
[[email protected] ~]# docker run -itd --net=host --name centos7-3 centos /bin/bash
[[email protected] ~]# docker ps |grep centos7-3
8b8585dd3ec2 centos "/bin/bash" 3 minutes ago Up 3 minutes centos7-3
[[email protected] ~]# docker exec -it 8b8585dd3ec2 /bin/bash
[[email protected] /]# yum -y install iproute net-tools httpd
[[email protected] /]# /usr/sbin/httpd
[[email protected] /]# netstat -utpln |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 127/httpd
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN -
[[email protected] /]# exit
exit
[[email protected] ~]# netstat -utpln |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 10684/httpd
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 9202/docker-proxy
- 配置自定義橋接模式:容器與宿主機處於同一網路;
[[email protected] ~]# yum -y install bridge-utils
[[email protected] ~]# cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-br0
[[email protected] ~]# vi /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=yes
NAME=br0
DEVICE=br0
ONBOOT=yes
NM_CONTROLLED=no
IPADDR=192.168.100.101
PREFIX=24
GATEWAY=192.168.100.100
DNS1=192.168.100.100
:wq
[[email protected] ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=yes
NAME=eth0
DEVICE=eth0
ONBOOT=yes
NM_CONTROLLED=no
BRIDGE=br0
:wq
[[email protected] ~]# systemctl restart network
[[email protected] ~]# git clone https://github.com/jpetazzo/pipework
正克隆到 'pipework'...
remote: Counting objects: 501, done.
remote: Total 501 (delta 0), reused 0 (delta 0), pack-reused 501
接收物件中: 100% (501/501), 172.97 KiB | 161.00 KiB/s, done.
處理 delta 中: 100% (264/264), done.
[[email protected] ~]# cp pipework/pipework /usr/local/bin/
[[email protected] ~]# vi /etc/sysconfig/docker
OPTIONS=' --selinux-enabled -b=br0 --fixed-cidr=192.168.100.0/24 --log-driver=journald --signature-verification=false'
:wq
[[email protected] ~]# systemctl restart docker
[[email protected] ~]# docker run -itd --net=none --name centos7-101 centos /bin/bash ##注意建立容器時指定--net=none不採用預設橋接方式自動產生ip,使用pipeword工具設定ip地址
ade2fb172937c97516c500d0b05284069b7e67b385aae84672e498594a82ea4d
[[email protected] ~]# docker ps |grep centos7-101
ade2fb172937 centos "/bin/bash" 9 seconds ago Up 9 seconds centos7-101
[[email protected] ~]# pipework br0 centos7-101 192.168.100.110/[email protected] ##使用pipework命令為容器配置ip地址。指定橋接網絡卡、容器ID、ip地址、子網掩碼、閘道器
,pipeword工具功能強大,劃分vlan等;
[[email protected] ~]# docker exec -it centos7-101 /bin/bash
[[email protected] /]# yum -y install iproute httpd net-tools
[[email protected] /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
119: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether a6:a6:92:78:01:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.100.110/24 brd 192.168.100.255 scope global eth1
valid_lft forever preferred_lft forever
[[email protected] /]# ping -c 2 www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=128 time=2.62 ms
[[email protected] /]# /usr/sbin/httpd
[[email protected] /]# netstat -utpln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 106/httpd
[[email protected] /]# exit
exit
- 配置container模式:使用 --net=container:container_id/container_name;
- 配置none模式:使用 --net=none;
方式:
一、埠對映:將容器內部的埠號碼對映到docker宿主節點的埠,實現外部主機訪問docker容器內的服務;
二、容器互聯:通過容器的名稱在容器之間建立一條專門的網路通訊隧道從而實現容器的互聯,簡單點說:就是在源容器和接收容器之間建立一條隧道,接收容器可以看到源容器指定的資訊;
方式一:埠對映:
注:在run 容器時,-P選項可以將docker容器內的埠隨機對映到宿主機的49000-49900範圍;
1.建立基於centos映象的容器並且實現埠對映,將容器的httpd的80埠對映到宿主機的8081埠;
[[email protected] ~]# docker run -itd -e"container=docker" --privileged=true -p 8081:80 centos /usr/sbin/init
727fd0bea64f5b7e28903d727dc23f61b2b7a065818bf03417a4d2c072728b5d
[[email protected] ~]# docker ps |grep init
bfc36fcc7857 centos "/usr/sbin/init" About a minute ago Up About a minute 0.0.0.0:8081->80/tcp pensive_lovelace
2.為容器安裝httpd服務並且啟動服務;
[[email protected] ~]# docker exec -it 727fd0bea64f /bin/bash
[[email protected] /]# yum -y install net-tools iproute httpd
[[email protected] /]# systemctl start httpd
[[email protected] /]# ip a |grep 172
inet 172.17.0.5/16 scope global eth0
[[email protected] /]# netstat -utpln |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 183/httpd
[[email protected] /]# exit
[[email protected] ~]# docker ps |grep init
bfc36fcc7857 centos "/usr/sbin/init" About a minute ago Up About a minute 0.0.0.0:8081->80/tcp pensive_lovelace
[[email protected] ~]# netstat -utpln |grep 8081
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 14123/docker-proxy
4.外部節點訪問測試服務;
[[email protected] ~]# elinks --dump http://192.168.100.101:8081
...
4. http://www.centos.org/
5. http://www.internic.net/whois.html
6. http://www.centos.org/
方式二:容器互聯:
1.建立源容器:
[[email protected] ~]# docker images |grep centos |grep latest
centos latest 5182e96772bf 5 weeks ago 200MB
[[email protected] ~]# docker run -itd --name centos7-1 centos /bin/bash
12a1d1312abf261bae7036143b5a8575851b99a42e05b769ff428b5f8698f14f
[[email protected] ~]# docker ps |grep centos7-1
12a1d1312abf centos "/bin/bash" 54 seconds ago Up 53 seconds
2.建立接收容器,指定centos容器為源容器:
[[email protected] ~]# docker run -itd --name centos7-2 --link centos7-1:centos7-1 centos /bin/bash
ea4baf4bdd1d041620a31c47fa32b37b4e4d3511d64fb0333c1c9ca39c7c0367
[[email protected] ~]# docker ps |grep centos7-2
ea4baf4bdd1d centos "/bin/bash" 5 seconds ago Up 4 seconds
3.連線到接收容器進行測試容器之間的連通性:
[[email protected] ~]# docker exec -it ea4baf4bdd1d /bin/bash
[[email protected] /]# ping centos7-1
PING centos7-1 (172.17.0.6) 56(84) bytes of data.
64 bytes from centos7-1 (172.17.0.6): icmp_seq=1 ttl=64 time=0.121 ms
64 bytes from centos7-1 (172.17.0.6): icmp_seq=2 ttl=64 time=0.036 ms
^C
--- centos7-1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.036/0.078/0.121/0.043 ms
[[email protected] /]# exit
六、Docker的儲存型別:
儲存型別:https://blog.csdn.net/vchy_zhao/article/details/70238690#1
- aufs:AUFS是Docker最先使用的storage driver,Docker在Debian,Ubuntu系的系統中預設使用aufs,它技術很成熟,社群支援也很好,特點如下: - 容器啟動速度很快 - 儲存空間利用很高效 - 記憶體的利用很高效
AUFS是一種聯合檔案系統,意思是它將同一個主機下的不同目錄堆疊起來(類似於棧)成為一個整體,對外提供統一的檢視。AUFS是用聯合掛載來做到這一點。 AUFS使用單一掛載點將多個目錄掛載到一起,組成一個棧,對外提供統一的檢視,棧中的每個目錄作為一個分支。棧中的每個目錄包括聯合掛載點都必須在同一個主機上。 在Docker中,AUFS實現了映象的分層。AUFS中的分支對應映象中的層。 此外,容器啟動時建立的讀寫層也作為AUFS的一個分支掛載在聯合掛載點上。
- Devicemapper:在RedHat系中使用device mapper。device mapper在Linux2.6核心中被併入核心,它很穩定,也有很好的社群支援。device mapper將所有的映象和容器儲存在它自己的虛擬裝置上,這些虛擬裝置是一些支援寫時複製策略的快照裝置。device mapper工作在塊層次上而不是檔案層次上,這意味著它的寫時複製策略不需要拷貝整個檔案。 device mapper建立映象的過程如下: - 使用device mapper的storge driver建立一個精簡配置池;精簡配置池由塊裝置建立;- 接下來建立一個基礎裝置; - 每個映象和映象層都是基礎裝置的快照;這寫快照支援寫時複製策略,這意味著它們起始都是空的,當有資料寫入時才耗費空間。在device mapper作為storage driver的系統中,容器層container layer是它依賴的映象的快照。與映象一樣,container layer也支援寫時複製策略,它儲存了所有對容器的更改。當有資料需要寫入時,device mapper就為它們在資源池中分配空間;
讀取資料:
寫入資料:
對容器的寫操作由“需要時分配”策略完成。更新已有資料由“寫時複製”策略完成,這些操作都在塊的層次上完成,每個塊的大小為64KB; 向容器寫入56KB的新資料的步驟如下: - 程序向容器發出寫56KB資料的請求; - device mapper的“需要時分配”策略分配一個64KB的塊給容器快照(container snapshot);如果要寫入的資料大於64KB,就分配多個大小為64KB的塊。 - 將資料寫入新分配的塊中;
- overlay儲存驅動:與AUFS相似,也是一種聯合檔案系統(union filesystem),與AUFS相比,其穩定性還有待測試;
OverlayFS在Linux主機上有兩個目錄但呈現給使用者就像只有一個目錄一樣。這些目錄稱之為層(layers),這些層的統一呈現通過聯合掛載實現。OverlayFS將底層目錄視作lowerdir,將上層目錄稱作upperdir,通過叫做merged目錄對外暴露統一的檢視。
以下圖片展示了Docker的映象和Docker容器的分層結構。 映象層就是lowerdir目錄,而uppperdir目錄就是容器層。統一對外暴露的檢視就是merged目錄,該目錄也是容器的掛載點。Docker結構對映OverlayFS結構圖如下;
讀取資料:
如果檔案在容器層不存在,則從lowdir中讀取;
只在容器層存在,則直接從容器中讀取該檔案;
檔案存在容器和映象層,容器層upperdir會覆蓋映象層lowdir中的檔案;
修改資料:
首次寫入: 在upperdir中不存在,overlay和overlay2執行copy_up操作,把檔案從lowdir拷貝到upperdir,由於overlayfs是檔案級別的(即使檔案只有很少的一點修改,也會產生的copy_up的行為); copy_up操作只發生在檔案首次寫入,以後都是隻修改副本 ; overlayfs只適用兩層,因此效能很好,查詢搜尋都更快;
效能測試:
總體上,overlay要比aufs和device mapper快一點。下面是對overlay效能影響較大的幾個方面: - 頁快取(page caching):overlayfs支援頁快取的共享,這意味著多個使用同一檔案的容器可以共享同一頁快取,這使得overlayfs具有很高的記憶體使用效率; - copy-up操作:overlay的拷貝操作工作在檔案層面上,也就是對檔案的第一次修改需要複製整個檔案,這回帶來一些效能開銷,在修改大檔案時尤其明顯; 但overlay的拷貝操作比aufs還是快一點,因為aufs有很多層,而overlay只有兩層,所以overlay在檔案的搜尋方面相對於aufs具有優勢; - i節點限制:使用overlay作為storage driver會消耗大量的i節點,隨著映象和容器數量的增長這種消耗尤其顯著,這在一定程度上限制了overlay的使用;
- overlay2儲存驅動:與overlay儲存模式的本質區別是映象層之間共享資料的方法不同
overlay共享資料方式是通過硬連線,而overlay2是通過每層的 lower檔案;