第四節:docker鏡像原理剖析和制作鏡像兩種方式 (通過容器 和 通過Dockerfile)


一. docker鏡像原理剖析

靈魂三問:

1. docker 鏡像的本質是什么?

2. docker中一個centos鏡像大約200M左右,為什么一個centos系統的iso安裝文件要好幾個G?

3. docker中一個tomcat鏡像大約500M左右,為什么一個tomcat安裝包不足100M呢?

1. 操作系統掃盲

  操作系統由:進程調度子系統、進程通信子系統、內存管理子系統、設備管理子系統、文件管理子系統、網絡通信子系統、作業控制子系統組成。

  Linux的文件管理子系統由bootfs和rootfs組成。

(1). bootfs:包含bootloader(引導加載程序)和 kernel(內核)

(2). rootfs: root文件系統,包含的就是典型 Linux 系統中的/dev,/proc,/bin,/etc等標准目錄和文件

PS: 不同的linux發行版,bootfs基本一樣,而rootfs不同,如ubuntu,centos等

2. 鏡像原理

(1). Docker鏡像是由特殊的文件系統疊加而成,最底端是 bootfs,並使用宿主機的bootfs;第二層是 root文件系統rootfs,稱為base image;然后再往上可以疊加其他的鏡像文件。

(2). 統一文件系統(Union File System)技術能夠將不同的層整合成一個文件系統,為這些層提供了一個統一的視角,這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統。

(3). 一個鏡像可以放在另一個鏡像的上面。位於下面的鏡像稱為父鏡像,最底部的鏡像成為基礎鏡像。

(4). 當從一個鏡像啟動容器時,Docker會在最頂層加載一個讀寫文件系統作為容器。

 

3. 解答靈魂三問

(1). docker 鏡像的本質是什么?

答:是一個分層的文件系統。

(2). docker中一個centos鏡像大約200M左右,為什么一個centos系統的iso安裝文件要好幾個G?

答:centos的iso文件包括bootfs和rootfs,而docker的centos鏡像復用操作系統的bootfs。

(3). docker中一個tomcat鏡像大約500M左右,為什么一個tomcat安裝包不足100M呢?

答:docker中的鏡像是分層的,tomcat雖然只有70多M,但是它需要依賴父鏡像和基礎鏡像,所有整個對外暴露的tomcat鏡像大約500M左右。

 

二. 容器轉為鏡像

1. 容器變為鏡像

(1). 指令

docker commit <containerId> 鏡像名稱:版本號

注:不加版本號的話,默認為latest

  將容器制作為鏡像,容器內掛載目錄(數據卷)下的文件不會被包含!!!其它非掛在目錄下的文件都會被一起打包轉為容器。

(2). 案例

 在一個名為mycentoscon1的centos容器中的工作目錄下,新建一個11.txt文件,然后把這個容器轉為一個鏡像,名為myowincentos1。

 

2. 如何移動遷移鏡像

(1). 把鏡像制成壓縮包

指令:

docker save -o 壓縮文件名稱 鏡像名稱:版本號

(2). 再把壓縮包轉為鏡像

 指令:

docker load -i 壓縮文件名稱

 

三. 通過Dockerfile制作鏡像

1. 制作鏡像的指令

docker build -f dockerfile文件路徑 -t 鏡像名稱:版本號 .

 (1).  -f dockerfile文件路徑 : dockerfile文件可以自定義命名,比如:ypfdockerfile,只要指定路徑即可。

 注:如果在當前目錄下,且名字就叫 Dockerfile,可以省略 【 -f dockerfile文件路徑】  簡版指令為 【docker build -t 鏡像名稱:版本號 .】

 (2). 如果不指定版本號,默認為latest

 (3). 指令最后必須有: 1個空格+1個點

2. 什么是Dockerfile文件 

Dockerfile 是一個文本文件包含了一條條的指令,每一條指令構建一層,基於基礎鏡像,最終構建出一個新的鏡像。他有以下作用

(1).對於開發人員:可以為開發團隊提供一個完全一致的開發環境。

(2).對於測試人員:可以直接拿開發時所構建的鏡像或者通過Dockerfile文件構建一個新的鏡像開始工作了。

(3).對於運維人員:在部署時,可以實現應用的無縫移植。

一張圖說明幾個核心配置

分享幾個Dockerfile案例: 

A.自己制作一個nginx鏡像

FROM centos:7.6
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
WORKDIR /nginx
COPY nginx-1.15.2.tar.gz /nginx
RUN tar -zxvf  nginx-1.15.2.tar.gz
RUN cd nginx-1.15.2 && ./configure && make && make install
EXPOSE 8080
COPY nginx.sh /nginx.sh
RUN chmod 755 /nginx.sh
CMD [“/nginx.sh”]

B.自己制作一個core webapi鏡像

#1.依賴兩個基礎鏡像
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim 
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster 

#2.制作人
MAINTAINER ypf <ypf@qq.com>

#3.指定程序運行的端口(也可以在項目中通過UseUrls指定, 或者發布容器的時候通過--env ASPNETCORE_URLS=xxx動態指定) 
ENV ASPNETCORE_URLS=http://*:9000

#4.容器對外暴露的端口
EXPOSE 9000

#5.指定默認工作目錄
WORKDIR /userapi

#6. 將當前目錄(Dockerfile文件下)的所有文件拷貝到鏡像的userapi工作目錄下
COPY . /userapi/

#7.啟動容器的時候執行shell命令:dotnet webapi1.dll,即運行該項目
ENTRYPOINT ["dotnet", "webapi1.dll"]

 

C. 自定義一個centos鏡像 

#1.定義依賴鏡像(宿主機中沒有話則去下載)
FROM centos:7

#2.定義作者信息(可以不寫)
MAINTAINER ypf <ypf@qq.com>

#3. 執行安裝vim的命令(-y表示安裝過程中不提示)
RUN yum install -y vim 

#4. 定義默認的工作目錄
WORKDIR /ypfusr

#5 定義容器啟動執行的命令
CMD /bin/bash

3. 剖析

(1). FROM 

 定義構建新鏡像所需依賴的父鏡像(基礎鏡像)。

FROM centos:7.6

(2). MAINTAINER  或 LABEL

 定義鏡像的作者。

MAINTAINER ypf <ypf@qq.com>
# 或者用 LABEL (推薦)
LABEL maintainer="ypf"

(3) .ENV

 設置環境變量

# 設置asp.net項目啟動端口為8000(程序中不設置的情況下用)
ENV ASPNETCORE_URLS=http://*:8000 
# 設置Java環境
ENV JAVA_HOME /usr/local/jdk1.11.0
# 設置mysql的密碼
ENV MYSQL_ROOT_PASSWORD 123456

(4). EXPOSE

  聲明容器運行的端口。

PS:在通過docker run 指令構建容器的要通過-p 將宿主機的端口和容器端口進行映射。

(5). RUN

 指定構建鏡像所需要運行的shell命令

#解壓並安裝
RUN tar -zxvf  nginx-1.15.2.tar.gz
RUN cd nginx-1.15.2 && ./configure && make && make install
# 安裝vim
RUN yum install -y vim

(6). WORKDIR

 指定工作目錄,發布成容器時,默認進入的就是這里指定目錄。

#定義默認的工作目錄
WORKDIR /ypfusr

(7). VOLUME

 指定生成容器時掛載宿主機的目錄

VOLUME ["/var/lib/mysql"]

注:基本上不在Dockerfile文件中使用,而是在構建容器的時候通過 -v 指令來設置。 

(8) . ADD

 拷貝文件或目錄到鏡像中  (此處要測試一下,如果鏡像中的目錄不存在是否會自動創建???)

#將當前目錄中xx1.tar.gz 復制到鏡像中的/home/test文件夾下,並自動解壓
ADD xx1.tar.gz /home/test
#下載xx2到鏡像中的/home/test文件夾中
ADD https://xxx.com/xx2.tar.gz /home/test
#將當前目錄下的start.sh 復制到鏡像中的目錄中
ADD ./start.sh  /start.sh

PS:當拷貝的是壓縮包或者URL的時候,會自動解壓或自動下載。

(9). COPY

 拷貝文件或目錄到鏡像中,同ADD,但不支持自動下載和解壓。

# 將當前目錄下的start.sh 復制到鏡像中的目錄中
COPY ./start.sh /start.sh

注:ADD和COPY的共同特點是 只能復制Dockerfile所在目錄下的文件,如果目標鏡像中的路徑不存在,會自動創建。

(10). CMD

 啟動容器時執行的shell命令。

# 啟動容器時候下面指令效果等效:
# ENTRYPOINT ["dotnet", "webapi1.dll"]
# ENTRYPOINT dotnet webapi1.dll
# CMD ["dotnet", "webapi1.dll"]
# CMD dotnet webapi1.dll

(11). ENTRYPOINT

 啟動容器時執行的shell命令。同CMD類似,只是由ENTRYPOINT啟動的程序不會被docker run命令行指定的參數所覆蓋,而且,這些命令行參數會被當作參數傳遞給ENTRYPOINT指定的程序

# 啟動容器時候下面指令效果等效:
# ENTRYPOINT ["dotnet", "webapi1.dll"]
# ENTRYPOINT dotnet webapi1.dll
# CMD ["dotnet", "webapi1.dll"]
# CMD dotnet webapi1.dll

注:如果存在多個ENTRYPOINT,僅最有一個生效。

(12).  HEALTHCHECK

 健康檢查

HEALTHCHECK --interval=5m --timeout=3s --retries=3 
CMD curl -f http:/xxxx/ || exit 1

 參數說明:

 --interval=DURATION (default: 30s):每隔多長時間探測一次,默認30秒

 -- timeout= DURATION (default: 30s):服務響應超時時長,默認30秒

 -- start-period= DURATION (default: 0s):服務啟動多久后開始探測,默認0秒

 -- retries=N (default: 3):認為檢測失敗幾次為宕機,默認3次

一些返回值的說明:

  0:容器成功是健康的,隨時可以使用

  1:不健康的容器無法正常工作

  2:保留不使用此退出代碼

(13).  USER

 為RUN、CMD、ENTRYPOINT執行shell命令指定用戶

USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER ypf

(14).  ARG

 構建參數,與 ENV 作用一至。不過作用域不一樣。ARG 設置的環境變量僅對 Dockerfile 內有效,也就是說只有 docker build 的過程中有效,構建好的鏡像內不存在此環境變量。

 構建命令 docker build 中可以用 --build-arg <參數名>=<值> 來覆蓋。

格式:ARG <參數名>[=<默認值>]
#Dockerfile文件中
ARG user=ypf #構建鏡像的時候覆蓋 docker build --build-arg user=lmr webapi1 .

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 

 


免責聲明!

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



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