創建Dockerfile


https://mp.weixin.qq.com/s?__biz=MzU0Mzk1OTU2Mg==&mid=2247483900&idx=1&sn=584962b8b6f24ca4636a32a441ff2ec5&chksm=fb023e99cc75b78f6f76877cc9be169238f2e499012293dbd2d04ac95c2951a74b3e3a46b4a0&token=2002719666&lang=zh_CN&scene=21#wechat_redirect

 

本節內容很多,我們希望大家能夠了解和使用好Dockerfile。

關於dockerfile

雖然我們可以通過docker commit命令來手動創建鏡像,但是通過Dockerfile文件,可以幫助我們自動創建鏡像,並且能夠自定義創建過程。本質上,Dockerfile就是由一系列命令和參數構成的腳本,這些命令應用於基礎鏡像並最終創建一個新的鏡像。它簡化了從頭到尾的構建流程並極大的簡化了部署工作。使用dockerfile構建鏡像有以下好處:

  • 像編程一樣構建鏡像,支持分層構建以及緩存;

  • 可以快速而精確地重新創建鏡像以便於維護和升級;

  • 便於持續集成;

  • 可以在任何地方快速構建鏡像

 

Dockerfile指令

我們需要了解一些基本的Dockerfile 指令,Dockerfile 指令為 Docker 引擎提供了創建容器映像所需的步驟。這些指令按順序逐一執行。以下是有關一些基本 Dockerfile 指令的詳細信息。

1.FROM

FROM 指令用於設置在新映像創建過程期間將使用的容器映像。

格式:FROM 

示例:

FROM nginx

FROM microsoft/dotnet:2.1-aspnetcore-runtime

 

 

2.RUN

RUN 指令指定將要運行並捕獲到新容器映像中的命令。 這些命令包括安裝軟件、創建文件和目錄,以及創建環境配置等。

格式:

RUN ["", "", ""]

RUN

示例:

RUN apt-get update

RUN mkdir -p /usr/src/redis

RUN apt-get update && apt-get install -y libgdiplus

RUN ["apt-get","install","-y","nginx"]

注意:每一個指令都會創建一層,並構成新的鏡像。當運行多個指令時,會產生一些非常臃腫、非常多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。因此,在很多情況下,我們可以合並指令並運行,例如:RUN apt-get update && apt-get install -y libgdiplus。在命令過多時,一定要注意格式,比如換行、縮進、注釋等,會讓維護、排障更為容易,這是一個比較好的習慣。使用換行符時,可能會遇到一些問題,具體可以參閱下節的轉義字符。

 

3.COPY

COPY 指令將文件和目錄復制到容器的文件系統。文件和目錄需位於相對於 Dockerfile 的路徑中。

格式:

COPY

如果源或目標包含空格,請將路徑括在方括號和雙引號中。

 

COPY ["", ""]

示例:

COPY . .

COPY nginx.conf /etc/nginx/nginx.conf

COPY . /usr/share/nginx/html

COPY hom* /mydir/

 

4.ADD

ADD 指令與 COPY 指令非常類似,但它包含更多功能。除了將文件從主機復制到容器映像,ADD 指令還可以使用 URL 規范從遠程位置復制文件。

格式:

ADD<source> <destination>

示例:

ADD https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe /temp/python-3.5.1.exe

此示例會將 Python for Windows下載到容器映像的 c:\temp 目錄。

 

5.WORKDIR

WORKDIR 指令用於為其他 Dockerfile 指令(如 RUN、CMD)設置一個工作目錄,並且還設置用於運行容器映像實例的工作目錄。

格式:

WORKDIR

示例:

WORKDIR /app

 

6.CMD

CMD指令用於設置部署容器映像的實例時要運行的默認命令。例如,如果該容器將承載 NGINX Web 服務器,則 CMD 可能包括用於啟動Web服務器的指令,如 nginx.exe。 如果 Dockerfile 中指定了多個CMD 指令,只會計算最后一個指令。

格式:

CMD ["<executable", "

CMD

示例:

CMD ["c:\\Apache24\\bin\\httpd.exe", "-w"]

CMD c:\\Apache24\\bin\\httpd.exe -w

 

7.ENTRYPOINT

配置容器啟動后執行的命令,並且不可被 docker run 提供的參數覆蓋。每個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最后一個起效。

格式:

ENTRYPOINT ["", ""]

示例:

ENTRYPOINT ["dotnet", "Magicodes.Admin.Web.Host.dll"]

 

8.ENV

ENV命令用於設置環境變量。這些變量以”key=value”的形式存在,並可以在容器內被腳本或者程序調用。這個機制給在容器中運行應用帶來了極大的便利。

格式:

ENV==...

示例:

ENV VERSION=1.0 DEBUG=on \

NAME="Magicodes"

 

9.EXPOSE

EXPOSE用來指定端口,使容器內的應用可以通過端口和外界交互。

格式:

EXPOSE

示例:

EXPOSE 80

 

說了這么多,我們可以用下圖來一言以蔽之:

 

轉義字符

在許多情況下,Dockerfile 指令需要跨多個行;這可通過轉義字符完成。 默認 Dockerfile 轉義字符是反斜杠 \。 由於反斜杠在 Windows 中也是一個文件路徑分隔符,這可能導致出現問題。

以下示例顯示使用默認轉義字符跨多個行的單個 RUN 指令。

FROM microsoft/windowsservercore

 

RUN powershell.exe -Command \

$ErrorActionPreference = 'Stop'; \

wget https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; \

Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \

Remove-Item c:\python-3.5.1.exe -Force

 

要修改轉義字符,必須在 Dockerfile 最開始的行上放置一個轉義分析程序指令。 如以下示例所示:

# escape=`

 

FROM microsoft/windowsservercore

 

RUN powershell.exe -Command `

$ErrorActionPreference = 'Stop'; `

wget https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe -OutFile c:\python-3.5.1.exe ; `

Start-Process c:\python-3.5.1.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; `

Remove-Item c:\python-3.5.1.exe -Force

注意,只有兩個值可用作轉義字符:\ 和 ` 。

 

優化

篇幅有限,我們這里只進行簡單講解,后續結合實際案例再進行細說。但是有幾點值得注意的是:

  1. 不能忽視dockerfile的優化,通常情況下,我們可以忽略那些細小的優化,但是我們需要知道優化的原理,為什么要優化

  2. 不能為了優化而優化。鏡像的構建過程視業務情況情況不同,指令就有多到少的區別,在很多情況下,我們先要以滿足業務目標為准,而不是鏡像層數。如果需要減少鏡像的層數,我們一定要選擇合適的基礎鏡像,或者創建符合我們需要的基礎鏡像。

下面是一些優化的准則:

  • 選擇合適的基礎鏡像

    這點相對最為重要。為什么這么說,我們結合現實社會也可以看到,在大部分情況下,一個人一生的成就更多的是看出身。很多情況下,基因和出身決定了你的高度和終點,這點拿到技術層面來說,也是有很大道理的,因此我們需要選擇合適的父母——一個合適的鏡像。

    一個合適的基礎鏡像是指能滿足運行應用所需要的最小的鏡像,理論上是能用小的就不要用大的,能用輕量的就不要用重量級的,能用性能好的就不要用性能差的。這里有時候還需要考慮那些能夠減少我們構建層數的基礎鏡像。

     

  • 優化指令順序

     

    Docker會緩存Dockerfile中尚未更改的所有步驟,但是,如果更改任何指令,將重做其后的所有步驟。也就是指令3有變動,那么4、5、6就會重做。因此,我們需要將最不可能產生更改的指令放在前面,按照這個順序來編寫dockerfile指令。這樣,在構建過程中,就可以節省很多時間。比如,我們可以把WORKDIR、ENV等命令放前面,COPY、ADD放后面。

     

  • 合並指令

    前面其實我們提到過這點,甚至還特地講到了轉義字符,其實主要是為此服務。前面我們說到了,每一個指令都會創建一層,並構成新的鏡像。當運行多個指令時,會產生一些非常臃腫、非常多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。因此,在很多情況下,我們可以合並指令並運行,例如:RUN apt-get update && apt-get install -y libgdiplus。在命令過多時,一定要注意格式,比如換行、縮進、注釋等,會讓維護、排障更為容易,這是一個比較好的習慣。

     

  • 刪除多余文件和清理沒用的中間結果

    這點很易於理解,通常來講,體積更小,部署更快!因此在構建過程中,我們需要清理那些最終不需要的代碼或文件。比如說,臨時文件、源代碼、緩存等等。

     

     

 

  • 使用 .dockerignore

    .dockerignore文件用於忽略那些鏡像構建時非必須的文件,這些文件可以是開發文檔、日志、其他無用的文件。例如:

說了這么多,其實我們更多的還是需要根據命令的實際執行情況來進行調整。


免責聲明!

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



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