您好,登錄后才能下訂單哦!
本章架構:
- Docker的創建方法
- Docker的數據管理
- Docker的網絡通信
Docker鏡像除了是Docker的核心技術之外,也是應用發布的標準格式。一個完整的Docker鏡像可以支撐一個Docker容器的運行,在Docker的整個使用過程中,進入一個已經定型的容器后,就可以在容器中進行操作,最常見的操作技術在容器中安裝應用服務,如果要把已經安裝的服務進行遷移,就要把環境及搭建的服務生成新的鏡像。下面介紹這三種創建鏡像的方法:
基于已有鏡像創建主要使用docker commit 命令。其實質就是把一個容器里面運行的程序及該程序的運行環境打包起來生成新的鏡像。
命令格式:
docker commit 【選項】容器id/名稱 倉庫名稱:【標簽】
常用選項:
-m:說明信息
-a:作者信息
-p:生成過程中停止容器的運行
方法如下:
(1)使用鏡像創建一個新的容器,并進行修改。
[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”命令創建一個新的鏡像。
[root@localhost ~]# docker commit -m "vsftpd" -a "xxf" centos xxf: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時,有嚴格的格式需要遵循:第一行必須使用FROM指令指明所基于的鏡像名稱;之后再使用MAINTAINER指令說明維護該鏡像的用戶信息;然后是鏡像操作相關指令,如RUN指令,每運行一條指令,都會給基礎鏡像添加新的一層;最后使用CMD指令來指定啟動容器時要運行的命令操作。
Dockerfile有十幾條命令可以用于構建鏡像;其中常見的指令如下表:
案例:
1.建立工作目錄
[root@localhost ~]# mkdir apache
[root@localhost ~]# cd apache/
2.創建并編寫Dockerfile文件
[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” 獲取鏡像,之后的容器運行才會有效;
3.編寫執行腳本內容
[root@localhost apache]# vim run.sh
#!/bin/bash
rm -rf /run/httpd/* //清理httpd的緩存
exec /usr/sbin/apachectl -D FOREGROUND //啟動apache服務
//啟動容器時,進程、腳本必須在前臺啟動
4.創建測試頁面
[root@localhost apache]# echo "weclome" > index.html //創建首頁文件
[root@localhost apache]# ls
Dockerfile index.html run.sh //這三個文件最好是在同一目錄下
5.使用Dockerfile生成鏡像
編寫完成Dockerfile及相關內容后,可以通過“docker build”命令來創建鏡像。
命令格式:
docker build [選項] 路徑
//常用選項“-t”指定鏡像的標簽信息
[root@localhost apache]# docker build -t httpd:centos .
使用剛才創鍵的Dockerfile 自動生成鏡像,最后必須要有一個“.”表示當前路徑
6.使用新的鏡像運行容器
[root@localhost ~]# docker run -d -p 12345:80 httpd:centos
ee9adf324443b006ead23f2d9c71f86d1a4eb73358fb684ee3a2d058a0ac4243
//使用新生成的鏡像加載到容器中運行
//“-p”選項實現從本地端口12345到容器中80端口的映射
[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
//查看該鏡像已經在容器中的狀態
驗證訪問結果:
7.將鏡像上傳到倉庫中
隨著創鍵的鏡像增多,就需要有一個保存鏡像的地方,這就是倉庫。目前有兩種倉庫:公共倉庫和私有倉庫。最方便的就是使用公共倉庫上傳和下載,下載公共倉庫的鏡像是不需要注冊的,但是上傳時,是需要注冊的。下面介紹如何創建私有倉庫。
方法如下:
(1)在構建私有倉庫的服務器上下載registry鏡像;
[root@localhost ~]# docker pull registry
(2)修改配置文件指定私有路徑的URL,否則在自定義的私有倉庫中上傳鏡像時會報錯,修改完畢后重啟Docker服務。
[root@localhost ~]# vim /etc/sysconfig/docker
[root@localhost ~]# systemctl restart docker //重啟docker服務
(3)使用下載好的registry鏡像啟動一個容器,默認情況下倉庫存放于容器內的/tmp/registry目錄下,使用“-v”選項可以將本地目錄掛載到容器內的/tmp/registry目錄下使用,這樣就不怕容器被刪除后鏡像也會隨之丟失。
[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
d5ecd77aa852df0c67935888009116325025cab49b7a4807196d251ce35a2b3b
//本地的目錄不用事先創建
(4)使用“docker tag”命令將要上傳的鏡像docker.io/registry 標記為
192.168.1.1:5000/registry 。
[root@localhost ~]# docker tag docker.io/registry 192.168.1.1:5000/registry
[root@localhost ~]# docker push 192.168.1.1:5000/registry //上傳本地鏡像到服務器上
[root@localhost registry]# curl -XGET http://192.168.1.1:5000/v2/_catalog
{"repositories":["registry"]} //查看倉庫類的鏡像
[root@localhost registry]# curl -XGET http://192.168.1.1:5000/v2/registry/tags/list
{"name":"registry","tags":["latest"]} //獲取鏡像的標簽列表
[root@localhost registry]# docker rmi -f 192.168.1.1:5000/registry //刪除本地鏡像進行測試
[root@localhost registry]# docker pull 192.168.1.1:5000/registry //從本地私有倉庫進行下載
[root@localhost registry]# docker images | grep 192.168.1.1:5000/registry
192.168.1.1:5000/registry latest f32a97de94e1 8 months ago 25.8 MB
//本地進行驗證
私有倉庫搭建完成,驗證成功!
在docker中,為了方便查看容器內產生的數據或者將多個容器之間的數據實現共享,會涉及到容器的數據管理操作,管理docker容器中的數據主要有兩種方式:數據卷和數據卷容器。
1、數據卷
數據卷是一個供容器使用的特殊目錄,位于容器中,可將宿主機的目錄掛載到數據卷上,對數據卷的修改操作立即可見,并且更新數據不會影響鏡像,從而實現數據在宿主機與容器之間的遷移,數據卷的使用類似于Linux下對目錄進行的mount掛載操作(注意:是將宿主機本地的目錄掛載到容器中,舉例:若宿主機本地/data目錄掛載的是/dev/sdb1,那么要將/data做數據卷映射時,容器中指定的目錄使用的文件系統也是/dev/sdb1,我不知道這樣解釋,你們能不能理解它的工作原理)。
掛載宿主機目錄作為數據卷舉例:
使用-v選項可以創建數據卷(只是運行容器時,創建一個目錄),創建數據卷的同時將宿主機的目錄掛載到數據卷上使用,以實現宿主機與容器之間的數據遷移。
需要注意的是,宿主機本地目錄的路徑必須是使用絕對路徑,如果路徑不存在,Docker會自動創建相應的路徑。
[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry/:/tmp/registry docker.io/registry
#這是運行了一個私有倉庫的容器,其中-p是端口映射的選項,這里不做解釋。
# -v才是目錄映射,將本地/data/registry/目錄映射到容器中的/tmp/registry目錄。
#然后容器中的/tmp/registry目錄下的內容就和宿主機的/data/registry/內容一樣了。
[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
2、數據卷容器
如果需要在容器之間共享一些數據,最簡單的方法就是使用數據卷容器。數據卷容器就是一個普通的容器,專門提供數據卷給其他容器掛載使用。使用方法如下:首先,需要創建一個容器作為數據卷容器,之后在其他容器創建時用--volumes-from掛載數據卷容器中的數據卷使用。
容器卷創建及使用舉例:
[root@localhost ~]# docker run -itd --name datasrv -v /data1 -v /data2 docker.io/sameersbn/bind /bin/bash
#創建運行一個容器,容器名為datasrv,并創建兩個數據卷:data1和data2。
d9e578db8355da35637d2cf9b0a3406a647fe8e70b2df6172ab41818474aab08
[root@localhost ~]# docker exec -it datasrv /bin/bash #進入創建的容器
root@d9e578db8355:/# ls | grep data #查看是否有對應的數據卷
data1
data2
[root@localhost ~]# docker run -itd --volumes-from datasrv --name ftpsrv docker.io/fauria/vsftpd /bin/bash
#運行一個名為ftpsrv的容器,使用--volumes-from來將datasrv容器中的數據卷掛載到這個ftpsvr新容器上。
eb84fa6e85a51779b652e0058844987c5974cf2a66d1772bdc05bde30f8a254f
[root@localhost ~]# docker exec -it ftpsrv /bin/bash #進入新創建的容器
[root@eb84fa6e85a5 /]# ls | grep data #查看新的容器是否可以看到datasrv提供的數據卷
data1
data2
[root@eb84fa6e85a5 /]# echo " data volumes test" > /data1/test.txt #在ftpsrv容器中向data1目錄寫入文件進行測試
[root@eb84fa6e85a5 /]# exit #退出該容器
exit
[root@localhost ~]# docker exec -it datasrv /bin/bash #進入提供數據卷的datasrv容器
root@d9e578db8355:/# cat /data1/test.txt #可以看到剛在ftpsrv容器創建的文件,OK。
data volumes test
注意,生產環境中最注重的就是存儲的可靠性,以及存儲的可動態擴展性,一定要在做數據卷時考慮到這一點,在這方面比較出色的還要數GFS文件系統了,我上面只是做了簡單的配置,若在生產環境中,一定要好好考慮,就比如上面做的鏡像卷容器,就可以在宿主機本地掛載GFS文件系統,然后創建鏡像卷容器時,將掛載GFS的目錄映射到容器中的鏡像卷,這樣才是一個合格的鏡像卷容器。
1、端口映射
docker提供了映射容器端口到宿主機和容器互聯機制來為容器提供網絡服務。
在啟動容器的時候,如果不指定對應的端口,在容器外是無法通過網絡來訪問容器內的服務的。docker提供端口映射機制來將容器內的服務提供給外部網絡訪問,實質上就是將宿主機的端口映射到容器中,使外部網絡訪問宿主機的端口可訪問容器內的服務。
實現端口映射,需要在運行docker run命令時使用-P(大寫)選項實現隨機映射,Docker一般會隨機映射到一個端口訪問在49000~49900的端口到容器內部開放的網絡端口,但不是絕對的,也有例外情況不會映射到這個范圍;也可以使用在運行docker run命令時使用-p(小寫)選項實現指定要映射的端口(常用此種方法)。
端口映射舉例:
[root@localhost ~]# docker run -d -P docker.io/sameersbn/bind #隨機映射端口
9b4b7c464900df3b766cbc9227b21a3cad7d2816452c180b08eac4f473f88835
[root@localhost ~]# docker run -itd -p 68:67 docker.io/networkboot/dhcpd /bin/bash
#將容器中的67端口映射到宿主機的68端口
6f9f8125bcb22335dcdb768bbf378634752b5766504e0138333a6ef5c57b7047
[root@localhost ~]# docker ps -a #查看發現沒問題咯
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f9f8125bcb2 docker.io/networkboot/dhcpd "/entrypoint.sh /b..." 2 seconds ago Up 1 second 0.0.0.0:68->67/tcp keen_brattain
9b4b7c464900 docker.io/sameersbn/bind "/sbin/entrypoint...." 4 minutes ago Up 4 minutes 0.0.0.0:32768->53/udp, 0.0.0.0:32769->53/tcp, 0.0.0.0:32768->10000/tcp coc_gates
#此時,訪問宿主機的68端口就相當于訪問第一個容器的67端口;訪問宿主機的32768端口,就相當于訪問容器的53端口。
2、容器互聯
容器互聯是通過容器的名稱在容器之間建立一條專門的網絡通信隧道從而實現的互聯。簡單說,就是會在源容器和接收容器之間建立一條隧道,接收容器可以看到源容器指定的信息。
在運行docker run命令時,使用--link選項實現容器之間的互聯通信,格式如下:
--link name: alias #其中name是要連接的容器名稱,alias是這個連接的別名。
容器互聯是通過容器的名稱來執行的,--name選項可以給容器創建一個友好的名稱,這個名稱是唯一的,如果已經命名了一個相同名稱的容器,當要再次使用這個名稱的時候,需要先使用docker rm命令來刪除之前創建的同名容器。
容器互聯舉例:
[root@localhost ~]# docker run -tid -P --name web1 docker.io/httpd /bin/bash #運行容器web1
c88f7340f0c12b9f5228ec38793e24a6900084e58ea4690e8a847da2cdfe0b
[[root@localhost ~]# docker run -tid -P --name web2 --link web1:web1 docker.io/httpd /bin/bash
#運行容器web2,并關聯web1容器
c7debd7809257c6375412d54fe45893241d2973b7af1da75ba9f7eebcfd4d652
[root@localhost ~]# docker exec -it web2 /bin/bash #進入web2容器
root@c7debd780925:/usr/local/apache2# cd
root@c7debd780925:~# ping web1 #對web1進行ping測試
bash: ping: command not found #sorry,提示沒有ping命令,下載一個咯
root@c7debd780925:~#apt-get update #更新一下
root@c7debd780925:~#apt install iputils-ping #安裝ping命令
root@c7debd780925:~#apt install net-tools #這個是安裝ifconfig命令,可以不安裝,我這里只是做個筆記
root@c7debd780925:~# ping web1 #再對web1進行ping測試
PING web1 (172.17.0.2) 56(84) bytes of data.
64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.114 ms
..............#省略部分內容
#ping通了,所以可以說這兩個容器肯定是互聯的咯
#若此時又創建了web3這個新容器,要同時和web1、web2進行互聯,命令如下:
[root@localhost ~]# docker run -dit -P --name web3 --link web1:web1 --link web2:web2 docker.io/httpd /bin/bash
#運行容器時,關聯web1和web2。
#以下是進入web3
[root@localhost ~]# docker exec -it web3 /bin/bash
root@433d5be6232c:/usr/local/apache2# cd
#以下是安裝ping命令
root@433d5be6232c:~# apt-get update
root@433d5be6232c:~# apt install iputils-ping
#以下是分別對web1,web2進行ping測試
root@433d5be6232c:~# ping web1
PING web1 (172.17.0.2) 56(84) bytes of data.
64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.112 ms
..............#省略部分內容
root@433d5be6232c:~# ping web2
PING web2 (172.17.0.3) 56(84) bytes of data.
64 bytes from web2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.165 ms
64 bytes from web2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.115 ms
..............#省略部分內容
#OK,沒問題
———————— 本文至此結束,感謝閱讀 ————————
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。