Docker的學習總結二:Docker鏡像、容器數據卷和Dockerfile解析

本節(jié)記錄一下Docker鏡像、容器數據卷和Dockerfile解析

一、Docker鏡像

首先我們明確一下docker鏡像的定義: 鏡像是一種輕量級、可執(zhí)行的獨立軟件包,用來打包軟件運行環(huán)境和基于運行環(huán)境開發(fā)的軟件,它包含運行某個軟件所需的所有內容,包括代碼、運行時、庫、環(huán)境變量和配置文件。
這里就需要提到提幾個概念了:

  • UnionFS(聯合文件系統(tǒng)):它是是一種分層、輕量級并且高性能的文件系統(tǒng),它支持對文件系統(tǒng)的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem)。Union 文件系統(tǒng)是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基于基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
  • Docker鏡像加載原理:docker的鏡像實際上由一層一層的文件系統(tǒng)組成,這種層級的文件系統(tǒng)UnionFS。
    bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引導加載kernel, Linux剛啟動時會加載bootfs文件系統(tǒng),在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統(tǒng)是一樣的,包含boot加載器和內核。當boot加載完成之后整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統(tǒng)也會卸載bootfs。rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系統(tǒng)中的 /dev, /proc, /bin, /etc 等標準目錄和文件。rootfs就是各種不同的操作系統(tǒng)發(fā)行版,比如Ubuntu,Centos等等。


    image.png

到這里了就有個問題,平時我們安裝進虛擬機的CentOS都是好幾個G,為什么docker這里才200M?因為對于一個精簡的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序庫就可以了,因為底層直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可見對于不同的linux發(fā)行版, bootfs基本是一致的, rootfs會有差別, 因此不同的發(fā)行版可以公用bootfs。Ubuntu和centos相比而言,就是內核相同,但是定制的軟件不相同而已。
采用分層結構的優(yōu)點:共享資源

二、容器數據卷

容器數據卷的存在就是為做數據的持久化。


Docker Volume

卷就是目錄或文件,存在于一個或多個容器中,由docker掛載到容器,但不屬于聯合文件系統(tǒng),因此能夠繞過Union File System提供一些用于持續(xù)存儲或共享數據的特性。 卷的設計目的就是數據的持久化,完全獨立于容器的生存周期,因此Docker不會在容器刪除時刪除其掛載的數據卷
特點:
1:數據卷可在容器之間共享或重用數據
2:卷中的更改可以直接生效
3:數據卷中的更改不會包含在鏡像的更新中
4:數據卷的生命周期一直持續(xù)到沒有容器使用它為止
數據卷的添加方式:
(1)直接命令添加

  • docker run -it -v /宿主機絕對路徑目錄:/容器內目錄 鏡像名
?  ~  docker run -it -v /HostDataVolume:/ContainerDataVolume centos

經過這樣的一個命令之后,我們在host的根目錄下面就有了HostDataVolume文件夾,在容器里面就有了ContainerDataVolume這個文件夾了。

  • 現在我們看看數據卷是不是掛在成功:
docker inspect + 鏡像ID
  • 宿主機與容器之間數據的共享
    在HostDataVolume里面增加一個文本host.txt。我們可以發(fā)現在ContainerDataVolume里面也出先了host.txt。

  • 容器退出之后,主機修改后數據是否同步
    首先是采用exit,先退出容器。然后隨便在HostDataVolume文件夾中建立一個文本,然后看看再去容器里面看看有什么變化沒有。

?  ~  docker start 容器ID
?  ~  docker attach 容器ID

就能去容器centos里面發(fā)現,我們還是有這個文本。就算是容器關閉了,但是我們在主機里面進行的操作,都同步到了容器里面。

  • docker run -it -v /宿主機絕對路徑目錄:/容器內目錄: ro鏡像名
    這里的ro就是read only 的意思,也就是說我們在host里面做的增刪改能夠同步到容器里面去,但是容器所對應的文件里面的是不能進行一個增刪改的。

(2)Dockerfile添加
Dockerfile會在第三個部分進行一個詳細的說明。
采用Dockerfile添加的步驟一個例子如下:
Step 1:現在根目錄下面建立一個文件夾mydocker
Step 2:使用vim創(chuàng)建一個Dockerfile文件,內容如下:

FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "Finished, -------success1"
CMD /bin/bash

Step 3:采用Docker build來生成一個新的鏡像。

docker build -f /mydocker/Dockerfile -t User/centos .

建立完成之后,我們用docker ps發(fā)現我們自動生成的鏡像。
Step 4:可以采用docker run了

docker run - it User/centos

三、Dockerfile解析

Dockerfile就是用來構建Docker鏡像的構建文件,由一系列命令和參數構成的腳本。注意它的本質就是一個腳本。

3.1、Dockerfile的內容基礎知識
  • 每個保留字命令必須是大寫,而且后面至少要跟一個參數
  • 指令從上到下的順序執(zhí)行
  • 每條指令都會創(chuàng)建一個新的鏡像層,并且對鏡像進行一個提交的操作
    Docker執(zhí)行Dockerfile的大致流程如下:
    (1)docker從基礎的鏡像實例出一個容器
    (2)執(zhí)行一條指令,同時對容器進行修改
    (3)執(zhí)行類似docker commit的操作提交一個新的鏡像層
    (4)docker再基于剛剛創(chuàng)建的新的鏡像實例出一個新的容器
    (5)經過這樣的循環(huán)過程,一層一層的建立,我們的鏡像就建立ok了。
    從應用軟件的角度來看待Dockerfile、Docker鏡像和Docker容器,它們三個就代表了不同的階段,是Docker體系的基石。
名稱 類比1 類比2
Dockerfile 軟件的原材料 面向開發(fā)
Docker鏡像 軟件的交付品 交付的標準
Docker容器 軟件的運行態(tài) 涉及部署與運維
3.2、Dockerfile的保留字命令

Dockerfile的保留字命令的總結見下面的思維導圖:

Dockerfile保留字命令

四、案例學習、動手實踐

Case1

Flask的docker打包
step1:先建立文件 identidock,里面放Dockerfile文件,app文件夾下面放 identidock.py文件

├── identidock
│   ├── Dockerfile
│   └── app
│       └── identidock.py

step2:寫Dockerfile和 identidock.py
identidock.py如下:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return "hello_world"

if  __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

Dockerfile文件如下

FROM python:3.4
 
RUN pip install FLask==0.10.1

WORKDIR /app
COPY app /app

CMD ["python","identidock.py"]

step3:構建鏡像docker build -t flask-test .

?  identidock  docker build -t  flask-test .
Sending build context to Docker daemon  3.584kB
Step 1/5 : FROM python:3.4
 ---> 8c62b065252f
Step 2/5 : RUN pip install FLask==0.10.1
 ---> Running in cee1dd8c54de
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
Collecting FLask==0.10.1
  Downloading https://files.pythonhosted.org/packages/db/9c/149ba60c47d107f85fe52564133348458f093dd5e6b57a5b60ab9ac517bb/Flask-0.10.1.tar.gz (544kB)
Collecting Werkzeug>=0.7 (from FLask==0.10.1)
  Downloading https://files.pythonhosted.org/packages/24/4d/2fc4e872fbaaf44cc3fd5a9cd42fda7e57c031f08e28c9f35689e8b43198/Werkzeug-0.15.1-py2.py3-none-any.whl (328kB)
Collecting Jinja2>=2.4 (from FLask==0.10.1)
  Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting itsdangerous>=0.21 (from FLask==0.10.1)
  Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->FLask==0.10.1)
  Downloading https://files.pythonhosted.org/packages/99/c9/5d5dcf2aa90f1d4500e92467a04f63b3708ee6e5764b40b2445e767ab8dc/MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl
Building wheels for collected packages: FLask
  Building wheel for FLask (setup.py): started
  Building wheel for FLask (setup.py): finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/e1/f2/be/1c4f307a41aad7e632f79c0242a2714ecde24b663da3519665
Successfully built FLask
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, FLask
Successfully installed FLask-0.10.1 Jinja2-2.10 MarkupSafe-1.1.1 Werkzeug-0.15.1 itsdangerous-1.1.0
Removing intermediate container cee1dd8c54de
 ---> 84afa5451c1b
Step 3/5 : WORKDIR /app
 ---> Running in 91bad6e440ab
Removing intermediate container 91bad6e440ab
 ---> 3a3b34824bf1
Step 4/5 : COPY app /app
 ---> caee6e674596
Step 5/5 : CMD ["python","identidock.py"]
 ---> Running in 3d0cdf7d7a81
Removing intermediate container 3d0cdf7d7a81
 ---> 7dc330367971
Successfully built 7dc330367971
Successfully tagged flask-test:latest

采用docker images看一下驗證一下就行了。

?  app  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
flask-test          latest              7dc330367971        12 minutes ago      935MB

step4:運行容器了

?  identidock  docker run -it -p 5000:5000 7dc330367971
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 337-801-390

最后我們去網頁看看就知道,現在運行ok了。

Case2

需求如下:
自己定義一個centos的鏡像,當我們采用該鏡像生成容器的時候,滿足下面的要求:
1、登錄的路徑是/usr/local
2、安裝vim、net-tools等工具(容器里面是沒有這些,所以我們在這里的話就進行一個安裝的操作)

step 1:寫Dockerfile如下

FROM centos
MAINTAINER   yourname<yourname@gmail.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim net-tools

EXPOSE 80

CMD /bin/bash

step 2:構建鏡像
注意后面那個點表明了我們是在當前的目錄下面build的。

docker build -t newcentos:8.0 .

現在我們就來看看生成的新的鏡像是不是出來了。這里可以看出來我們新生成的鏡像比原來的鏡像大了150mb。

?  mydocker  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
newcentos           8.0                 e7784fdf444b        17 seconds ago      352MB
centos              latest              9f38484d220f        2 months ago        202MB

step 3:實例化鏡像,生成一個容器

?  mydocker  docker run -it newcentos:8.0
[root@674942d556fa local]#
[root@674942d556fa local]# pwd
/usr/local

現在我們就看到了,一進入到了容器,那么我么你的當前路徑就是/usr/local。

這樣我們就生成了一個自己定義的一個centos鏡像了。
Case 3:一個比較綜合的例子

參考資料:
1、https://www.docker.com/
2、https://www.bilibili.com/video/av17854410?from=search&seid=2496603295204351706

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容