文章目錄
一、Docker鏡像的分層
- Dockerfile中的每個指令都會創建一個新的鏡像層
- 鏡像層將被緩存和複用
- 當Dockerfile的指令修改了,複製的文件變化了,或者構建鏡像時指定的變量不同了,對應的鏡像層緩存就會失效
- 某一層的鏡像緩存失效之後,它之後的鏡像層緩存都會失效
- 鏡像層是不可變的,如果在某一層中添加一個文件,然後在下一層中刪除它,則鏡像中依然會包含該文件
二、Docker鏡像的創建
Docker鏡像是應用發佈的標準格式。可支撐一個Docker容器的運行
- 基於已有鏡像創建
- 基於本地模板創建
- 基於Dockerfile創建
1、基於Dockerfile創建
Dockerfile創建鏡像並在容器中運行。
Dockerfile是由一組指令組成的文件,其中每條指令對應Linux中的一條命令,Docker程序將讀取Dockerfile中的的指令生成指定鏡像使用
1)結構組成(四部分)
- 基礎鏡像信息
- 維護者信息
- 鏡像操作指令
- 容器啓動時執行指令
Dockerfile操作指令
在編寫Dockerfile時,有嚴格的格式需要遵循:第一行必須使用FROM指令指明所基於的鏡像名稱;之後使用MAINTAINER指令說明維護該鏡像的用戶信息;然後是鏡像操作相關指令,如RUN指令,每運行一條指令,都會給基礎鏡像添加新的一層;最後使用CMD指令,來指定啓動容器時要運行的命令操作。
常見的指令表如下:
指令 | 含義 |
---|---|
FROM鏡像 | 指定新鏡像所基於的鏡像,第一條指令必須爲FROM指令, 每創建一個鏡像就需要一條FROM指令。 |
MAINTAINER名字 | 說明新鏡像的維護人信息 |
RUN命令 | 在所基於的鏡像上執行命令,並提交到新的鏡像中 |
CMD [ “要運行的程序”,”參數1, “參數2”] | 指令啓動容器時要運行的命令或者腳本,Dockerfile只能有一條CMD命令,如果指定多條則只能最後一條被執行 |
EXPOSE 端口號 | 指定新鏡像加載到Docker時要開啓的端口 |
ENV 環境變量 變量值 | 設置一個環境變量的值,會被後面的RUN使用 |
ADD 源文件/目錄 目標文件/目錄 | 將源文件複製到目標文件,源文件要與Dockerfile位於相同目錄中,或者是一個URL |
COPY 源文件/目錄 目標文件/目錄 | 將本地主機上的文件/目錄複製到目標地點,源文件/目錄要 與Dockerfile在相同的目錄中 |
VOLUME[“目錄"] | 在容器中創建一個掛載點 |
USER 用戶名/UID | 指定運行容器時的用戶 |
WORKDIR 路徑 | 爲後續的RUN、CMD、ENTRYPOINT指定工作目錄 |
ONBUILD 命令 | 指定所生成的鏡像作爲一個基礎鏡像時所要運行的命令 |
HEALTHCHECK | 健康檢查 |
3) 示例
首先需要創建目錄,作爲生成鏡像的工作目錄,然後分別創建並編寫Dockerfile文件、需要運行的腳本文件以及要複製到容器的文件
① 創建工作目錄
[root@localhost~]# mkdir apache
[root@localhost~]# cd apache
② 創建並編寫Dockerfile文件
[root@localhost apache]# vim Dockerfile
#基礎鏡像
FROM centos:7
#用戶信息
MAINTAINER test
#基於基礎鏡像安裝軟件
RUN yum -y update
RUN yum install -y httpd
#開啓端口
EXPOSE 80
#複製首頁到指定站點
ADD index.html /var/www/html/index.html
#複製啓動腳本到鏡像中
ADD run.sh /run.sh
#設置 run.sh執行權限
RUN chmod 755 /run.sh
#啓動容器時執行腳本
CMD ["/run.sh"]
③ 編寫執行腳本內容
[root@localhost apache]# vim run.sh
#!/bin/bash
rm -rf /run/httpd/* #清理httpd的緩存
exec /usr/sbin/apachectl -D FOREGROUND #啓動apache服務
④ 創建web測試首頁
[root@localhost apache]# echo "test web" > index.html
#創建的三個文件都在/apache目錄中
#目前容器及鏡像都沒有
⑤ 使用Dockerfile生成鏡像
編寫完成Dockerfile以及相關內容之後,可以通過docker build命令來創建鏡像。
命令格式:
docker build [選項] 路徑
常用選項:
- -t:指定鏡像的標籤信息
#使用Dockerfile自動生成鏡像
[root@localhost apache]# docker build -t httpd:centos .
Sending build context to Docker daemon 4.096kB
Step 1/9 : FROM centos:7
7: Pulling from library/centos
ab5ef0e58194: Pull complete
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7
---> 5e35e350aded
Step 2/9 : MAINTAINER test
---> Running in 671d3fa20a48
Removing intermediate container 671d3fa20a48
………………省略內容
Step 9/9 : CMD ["/run.sh"]
---> Running in 16cc2e1b490e
Removing intermediate container 16cc2e1b490e
---> 4fd096d992ec
Successfully built 4fd096d992ec
Successfully tagged httpd:centos
整個創建過程中,每運行一次Dockerfile中的指令,都會給初始鏡像加上新的一層(docker是分層的,每一層run執行都會產生一個臨時容器,執行完成後就會被remove掉)
⑥ 使用新的鏡像運行容器
#將新生成的鏡像加載到容器中運行
[root@localhost apache]# docker run -d --name web1 -p 12345:80 httpd:centos
- -p:指定固定本地端口,實現從本地端口到容器中80端口的映射
- -P:隨機生成本地端口,實現從本地端口到容器中80端口的映射
#可以看到該鏡像已在容器中加載運行
⑦驗證
#訪問容器中的apache服務
2、基於已有鏡像容器創建
基於已有鏡像創建主要使用docker commit命令。實質就是把一個容器裏面運行的程序以及該程序的運行環境打包起來生成新的鏡像
命令格式:
docker commit [選項] 已有容器ID/名稱 倉庫名稱:標籤
常用選項:
- -m:說明信息
- -a:作者信息
- -p:生成過程中停止容器的運行
① 創建並查看已有容器,需要記住容器ID
② 使用docker commit命令創建鏡像
[root@localhost ~]# docker commit -m "new” -a ''daoke" 9e22619aa48d daoke:test
[root@localhost ~]# docker images
創建完成後,會返回新創建鏡像的ID信息。查看本地鏡像列表可以看到新創建的鏡像信息
3、基於本地模板創建
通過導入操作系統模板文件可以生成鏡像,模板可以從OPENVZ開源項目下載,下載地址爲:http://openvz.org/Download/template/precreated
① 下載模板
這裏我是已經有這個包了,直接使用
使用wget下載
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
② 使用docker的導入命令將下載的模板壓縮包導入爲本地鏡像
[root@localhost ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - daoke:debian
③ 導入完成後會返回生成鏡像的ID。查看本地鏡像列表可以看到新創建的鏡像信息
[root@localhost ~]# docker images
三、建立私有倉庫
隨着創建的鏡像日益增多,就需要有一個保存鏡像的地方,就是倉庫。目前有兩種倉庫:公有倉庫和私有倉庫。最方便的就是使用公有倉庫上傳和下載鏡像,下載公有倉庫中的鏡像不需要註冊,但是上傳鏡像到公有倉庫是需要註冊的。公有倉庫網址:https://hub.docker.com,填寫完成倉庫的ID號、郵箱以及登錄倉庫的密碼並在郵箱中進行激活就可以上傳自己的鏡像。
這裏我們來構建一個簡單的本地私有倉庫registry(沒有圖形化界面)
① 下載 registry倉庫鏡像
[root@localhost ~]# docker pull registry
② 客戶終端配置加速
#不配置加速在上傳鏡像時會報錯
[root@localhost ~]# vim /etc/docker/daemon.json
{
"insecure-registries":["192.168.11.141:5000"], #指明倉庫節點IP以及端口
"registry-mirrors": ["https://7rp8a2t8.mirror.aliyuncs.com"]
}
[root@localhost ~]# systemctl restart docker #改過配置,需要重啓
③ 創建registry容器並掛載
#在本地啓動一個私有倉庫服務,監聽端口號爲5000
#宿主機的/data/registry自動創建掛載容器中的/tmp/registry
創建容器時-v掛載 宿主機上的/data/registry提供給容器中的/tmp/registry使用。
-v指定外部路徑是會自動創建的,不需要自己去mkdir手動創建
[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
④ 更改標籤爲192.168.11.141:5000/nginx(docker tag 原鏡像名 倉庫IP:端口/鏡像名)
[root@localhost ~]# docker pull nginx
[root@localhost ~]# docker images
[root@localhost ~]# docker tag nginx:latest 192.168.11.141:5000/nginx
標籤是必須要更改的,否則鏡像不知道往哪傳
⑤ 上傳鏡像至私有倉庫(docker push 倉庫IP:端口/鏡像名)
[root@localhost ~]# docker push 192.168.11.141:5000/nginx
⑥ 獲取私有倉庫列表
[root@localhost ~]# curl -XGET http://192.168.11.141:5000/v2/_catalog
#顯示上傳成功
{“repositories”:[“nginx”]}
⑦ 測試私有倉庫下載
可以另外打開節點測試下載
[root@localhost ~]# docker pull 192.168.11.141:5000/nginx
這裏直接將原來的nginx鏡像刪除並重新下載測試
小結:
registry私有倉庫設置步驟
1、下載registry鏡像 (字符終端)
2、生成registry容器,開放5000端口
3、客戶端設置daemon.json文件 (指定私有倉庫位置)
4、鏡像打標籤 docker tag 原鏡像名 倉庫IP:端口/鏡像名
5、上傳鏡像docker push 倉庫IP:端口/鏡像名
6、下載鏡像 docker pull
7、查看鏡像 docker images
生產環境中使用harbor (圖形化界面)
四、數據卷
在Docker中,爲了方便查看容器內產生的數據或者將多個容器中的數據實現共享,就涉及到容器的數據管理操作。管理Docker容器中數據主要有兩種方式:數據卷(Data Volumes)和數據卷容器(Data Valumes Containers)。
數據卷:掛載宿主系統的存儲空間(宿主與容器間的共享)
數據卷容器:掛載容器的存儲空間(容器與容器間的共享)
1、Docker數據卷
數據卷是一個供容器使用的特殊目錄,位於容器中,可將宿主機的目錄掛載到數據捲上,對數據卷的修改操作立刻可見,並且更新數據不會影響鏡像,從而實現數據在宿主機與容器之間的遷移。數據卷的使用類似於Linux下對目錄進行mount操作
在docker run命令中使用-v選項可以在容器內創建數據卷。多次使用-v選項可創建多個數據卷。使用-v選項可以在創建數據卷的同時,將宿主機的目錄掛載到數據捲上使用,以實現宿主機與容器之間的數據遷移。使用–name選項可以給容器創建自定義名稱
注意:宿主機本地目錄的路徑必須使用絕對路徑,如果路徑不存在,Docker會自動創建相應的路徑
① 創建容器並掛載
使用centos鏡像創建一個名爲web1的容器,並且將宿主機的/var/www目錄掛載到容器的/data1目錄上
[root@localhost var]#docker run -v /var/www:/data1 --name web1 -it centos /bin/bash
② 創建文件測試
[root@1ef71c70ea80 /]# cd /data1/
[root@1ef71c70ea80 data1]# touch test01
③ 返回宿主機進行查看
[root@localhost var]# cd www/
[root@localhost www]# ls
test01
同理,在宿主機相應的掛載目錄中創建數據,在數據卷中也可以訪問
2、數據卷容器
如果需要在容器之間共享一些數據,最簡單的方法就是使用數據卷容器。數據卷容器就是一個普通的容器,專門提供數據卷給其他容器掛載使用。使用方法:① 首先需要創建一個容器作爲數據卷容器 ②之後再其他容器創建時使用–volumes-from掛載數據卷容器中的數據卷使用
#創建數據卷容器
[root@localhost ~]# docker run --name web2 -v /data1 -v /data2 -it centos /bin/bash
#新容器掛載數據卷容器web2
[root@localhost ~]#docker run -it --volumes-from web2 --name db1 centos /bin/bash
新容器掛載了數據卷容器web2,與其共享data1和data2目錄
這樣就可以通過數據卷同期實現容器之間的數據共享
通過這些機制,即使容器再運行過程中出現故障,用戶也不必擔心數據發生丟失,如果發生意外,只需快速重新創建容器即可。
五、端口映射
Docker提供了映射容器端口到宿主機和容器互聯機制來爲容器提供網絡服務
在啓動容器的時候,如果不指定對應的端口,在容器外將無法通過網絡來訪問容器內的服務。Docker提供端口映射機制來將容器內的服務提供給外部網絡訪問,實質上就是將宿主機的端口映射到容器中,使得外部網絡訪問宿主機的端口便可以訪問容器內的服務
實現端口映射,需要在運行docker run命令時使用**-P(大寫)選項實現隨機映射**,Docker會隨機映射一個端口範圍在49000~49900的端口到容器內部開放的網絡端口
[root@localhost ~]# docker run -d -P httpd:latest
在運行docker run命令時使用**-p(小寫)選項指定要映射的端口**
[root@localhost ~]# docker run -d -p 11111:80 httpd:latest
六、容器互聯
容器互聯是通過容器的名稱在容器間建立一條專門的網絡通信隧道從而實現容器的互聯。簡單點說,就是會在源容器和接收容器之間建立一條隧道,接受容器可以看到源容器指定的信息。在運行docker run命令時使用–link選項可以實現容器之間的互聯通信。
格式爲:–link name:alias
其中name是要連接的容器名稱,alias是這個連接的別名
注意:容器互聯是通過容器的名稱來執行的,–name選項可以給容器創建一個友好的名稱,這個名稱是唯一的,如果已經命名了一個相同名稱的容器,當要再次使用這個名稱的時候,需要先使用docker rm命令來刪除之前創建的同名容器
① 創建源容器
#創建並運行容器取名web1,端口號自動映射
[root@localhost ~]# docker run -itd -P --name web1 centos /bin/bash
② 創建接收容器
#創建並運行容器取名web2, 使用–link指定web1連接容器以實現容器互聯
[root@localhost ~]# docker run -itd -P --name web2 --link web1:web1 centos /bin/bash
③ 測試容器互聯
#進web2容器,使用ping命令查看容器是否能互聯互通
此時,可以看到web2與web2已經建立互聯關係。Docker在兩個互聯的容器之間創建了一條安全隧道,而且不用映射他們的端口到宿主機上,從而避免暴露端口給外部網絡。