Docker鏡像講解


Docker鏡像講解

鏡像是什么

鏡像是一種輕量級的,可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境的開發軟件,它包含運行某個軟件做需要的所有的內容,包括代碼,運行時,庫,環境變量和配置文件。

所有應用,直接打包docker鏡像,就可以直接跑起來!

如何讓得到鏡像:

  • 叢倉庫下載
  • 朋友拷貝給你
  • 自己制作一個鏡像DockerFile

UnionFS(聯合系統文件)

我們下載的時候看到的一層一層就是這個!

UnionFS(聯合系統文件):Union文件系統(UnionFS)是一種分層,輕量級應且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(union serveral directories into a single virtual filesystem)。Union文件系統時Docker鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),而一直做各種具體的應用鏡像。

特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統就會包含所有底層的文件和目錄

Docker鏡像加載原理

dockers的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統UnionFS。

botfs(boot file system)主要包含bootloader和kernel,bootloader主要時引導加載kerenl,Linux剛啟動時會加載bootfs文件系統,在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統是一樣的。包含boot加速器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由boots轉交給內核,此時系統也會卸載boots。

rootfs(root file system),在bootfs之上,包含的就是典型的Linux系統中的/dev,/proc,/bin,/etc等標准目錄和文件。rootfs就是各種不同的操作系統發行版,比如Ubuntu,CentOS等等

image

平時我們安裝進虛擬機的CentOS都是好幾個G,為什么Docker這里才200M?

image
對於一個精簡的OS,rootfs可以很小,只需要包含對基本的命令,工具和程序就可以了,因為底層直接用Host的kerkel,自己只需要提供rootfs就可以了,由此課件對於不同的linux發行版,bootfs基本是一致的,rootfs會有差別,因此不同的發行版本可以公用bootfs。

虛擬機是分鍾級,容器是秒級

分層理解

分層的鏡像

我們可以去下載一個鏡像,注意觀察下載的日志輸出,可以看到是一層一層的在下載!

image
思考:為什么Docker鏡像要采用這種分層的結構呢?

最大的好處,我覺得莫過於是資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那么宿主只需在磁盤上保留一份bash鏡像,同時內存中也只需要加載一份bash鏡像,這樣就可以為所有的容器服務了,而且鏡像的每一層都可以被共享。

查看鏡像分層的當時可以通過docker inspect命令!

[root@hsStudy home]# docker images inspect redis:latest
{
	//......
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:02c055ef67f5904019f43a41ea5f099996d8e7633749b6e606c400526b2c4b33",
                "sha256:ec5652c3523d96657d66169c0eb71b572ff065711c705a15ec02f60a21c212c3",
                "sha256:76d3e24d63f60e6a73af70be15959eb4021dd7a5a09da6925037d3b4a1673fca",
                "sha256:f281464c05be6822b95403339e2b7744fd1664e88ee9d118c7e89436ab094d58",
                "sha256:7fde79e38c038ef46904196710861e2c556363d723b8f8bf9b00369944d36aec",
                "sha256:6d4185a1708b677241d83683283c76703e788e41a2341b7c1bf4dbf12aebab45"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解:

所有的Docker鏡像都起始於一個基礎鏡像層,當進行修改或增加新的內容時,就會在房前鏡像層之上,床卷尋得鏡像層。

舉一個簡單的例子,加入基於Ubantu Linux 16.04創建一個新的鏡像,這就是新的鏡像的第一層;如果在該鏡像種添加個Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就會創建第三個鏡像層。

該鏡像當前已經包含三個鏡像層,如下圖所示(這只是一個用於演示的很簡單的例子)

image
在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要。下圖中舉了一個簡單的例子,每個鏡像層包含三個文件,而鏡像包含了來自兩個鏡像的六個文件。

image
上圖中的鏡像層跟之前途中的略有區別,主要目的是便於展示文件

下圖中展示了一個稍微復雜的三層經想,在外部看來整個鏡像只有6個文件,這是因為最上層中的文件7是5的一個更新版本。

image
這種情況下,上層鏡像中的文件

覆蓋了底層中的文件,這樣就使得文件的跟新版本最為一個新鏡像層添加到當前鏡像當中。

Docker通過存儲引擎(新版本采用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層鏡像層對外展示為統一的文件系統。

Linux上可用的存儲引擎AUFS,Overlay2,Device Mapper,Btrfs以及ZFS。顧名思義,每種存儲引擎都基於Linux中國對應的文件系統或者快設備技術,並且每種存儲引擎都有其獨特的性能特點。

Docker在Windows上僅支持windowsfilter以中國存儲引擎,該引擎基於NTFS文件系統之上實現了分層和CoW[1].

下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆疊合並,對外提供統一的視圖。

image

特點

Docker鏡像都是只讀的,當容器啟動時,一個新的可寫層被加載到鏡像頂部!

這一層就是我們通常說的容器層,容器之下的都叫鏡像層!

image
如何提交一個自己的鏡像

commit鏡像

docker commit 提交容器成為一個新的副本

#命令和git原理類似
docker commit -m="提交的描述信息" -a="作者" 容器id 目標鏡像名:[TAG]

實戰測試

#1.啟動一個默認的tomcat

#2.發現這個默認的tomcat是沒有默認的webapps應用,官方的鏡像默認webapps下面是沒有文件的!

#3.我自己拷貝進去了基本的文件

#4.將我們操作過的容器通過commit提交為一個鏡像!我們以后就使用我們修改過的鏡像,這就是我們自己的一個修改過的鏡像

image
學習方式說明:理解概念,但是一定要事件,最后時間和理論結合一次搞定這個知識

如果你想要保存當前容器的狀態,就可以通過commit來提交,獲得一個鏡像,
就好比我們以前學習vm的時候,快照!

到了這里我們才算是入門Docker!認真吸收聯系!

容器數據卷

什么是容器數據卷

docker的理念回顧

將我們的應用和環境打包成一個鏡像!

數據?如果數據都在容器中,那么我們容器一刪除,數據就會丟失!需求:數據可以持久化

MySQL,容器刪了,刪庫跑路!! 需求:MySQL數據可以存儲在本地!

容器之間可以由一個數據共享技術!Docker容器中產生的數據,同步到本地!

這就是卷技術!目錄的掛載,將我們容器內的目錄,掛載待Linux上面!

image
總結一句話:容器的持久化和同步操作!容器間可是可以數據共享的

使用數據卷

方式一 :直接使用命令來掛載 -v

docker run -it -v 主機目錄:容器內目錄 

#測試
[root@hsStudy home]# docker run -it -v /home/ceshi:/home centos /bin/bash

# 啟動提來的時候我們可以通過docker inspect 容器id

image

測試文件的同步

image
再來測試

1.停止容器

2.宿主機上修改文件

3.啟動容器

4.容器內的數據依舊是同步的

image
好處:我們以后修改只需要在本地修改即可,容器內會自動同步!

實戰:安裝MySQL

思考:MySQL的數據持久化的問題

#獲取鏡像
[root@hsStudy home]# docker pull mysql:5.7

#運行容器,需要做數據掛載!#安裝配置mysql,需要配置密碼的,這是要注意的
#官方測試,docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

#啟動我們的
-d 后台運行
-p 端口映射
-v 數據卷掛載
-e 環境配置
--name 容器名字
[root@hsStudy home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01  mysql:5.7

# 啟動成功過之后,我們在本地使用 navicat來測試一下
# navicat連接到服務器的3310 --- 3310 和容器內的3306映射,這個時候我們就可以連接上了

#在本地測試創建一個數據庫,查看一下我們映射的路徑是ok!

假設我們將容器刪除

image
發現,我們掛載到本地的數據卷依舊沒有丟失,這就實現了容器數據持久化功能!

具名和匿名掛載

#匿名掛載
-v 容器內路徑!
docker run -d -P --name nginx01 -v /ect/nginx nginx

#查看所有的 volume 的情況
[root@hsStudy home]# docker volume ls
DRIVER    VOLUME NAME
local     5d631b17845dc8be39af17cd67b8b521dfe64ea81fe0c6615b6438427877af43
#這里發現,這種就是匿名掛載,我們在 -v 只寫了容器內的路徑,沒有些容器外的路徑!

[root@hsStudy home]# docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx

#通過 -v 卷名:容器內路徑
#查看一下這個卷

image
所有的docker容器內的卷,沒有指定目錄的情況下都是在/var/lib/docker/volumes/xxxx/_data

我們通過具名掛載可以方便的找到我們的一個卷,大多數在使用的具名掛載

#如何確定使具名掛載還是匿名掛載,還是指定路徑掛載
-v 容器內路徑  #匿名掛載
-v 卷名       #具名掛載
-v /宿主機路徑:容器內路徑   #指定路徑掛載

拓展

#通過-v 容器內路徑:ro   rw   改變讀寫權限
ro readonly   #只讀
rw readwrite  #可讀可寫

#一旦設定了容器權限,容器對我們掛在出來的內容就有限定了
[root@hsStudy _data]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx 
[root@hsStudy _data]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx 

#ro,只要看到ro就說明這個路徑只能通過宿主機來操作,容器內部是無法操作的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM