-
前言:
上一篇文章簡單使用了docker 拉取映象、啟動容器、編譯映象;其中編譯映象時,使用到了Dockerfile,那麼接下來我們就詳細的來說說Dockerfile
DockerFile是什麼:
Dockerfile 是一個用來構建映象的文字檔案,Dockerfile內容中包含了一條條構建映象所需的指令和說明。最終採用docker build 命令通過dockerfile中指令構建映象
各種指令詳情:
1、From:指定基礎映象(dockerfile第一個指令)
FROM [--platform=<platform>] <image> [AS <name>] OR FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] OR FROM [--platform=<platform>] <image>[@<digest>] [AS <name>] 例如: FROM mysql:5.8
注意:
- 有效的
Dockerfile
必須從FROM
指令開始 - ARG是Dockerfile中唯一可能位於FROM之前的指令
-
FROM可以在一個Dockerfile中多次出現,以建立多個映像或將一個構建階段用作另一個構建階段的依賴項
-
通過FROM指令新增AS name,可以選擇為新生成階段指定名稱。該名稱可以在後續的FROM和COPY--FROM=<name>指令中使用,以引用在此階段中構建的映象。
- 標記或摘要值是可選的
2、RUN:構建映象時執行的命令
兩種方式: RUN <command> ##命令在shell中執行,預設情況下/bin/sh -c在Linux或cmd /S /CWindows上執行 RUN ["executable", "param1", "param2"] ##exec 方式 例如: RUN ["/bin/bash", "-c", "echo hello"]
注意:
- 將在當前影像頂部的新層中執行所有命令,並提交結果
- 在JSON格式中,必須轉義反斜槓。
例如:RUN ["c:\\windows\\system32\\tasklist.exe"]
3、CMD:構建容器後呼叫,也就是在容器啟動時才進行呼叫。
三種格式: CMD ["executable","param1","param2"] ##執行可執行檔案,優先 CMD ["param1","param2"] ##設定了 ENTRYPOINT,則直接呼叫ENTRYPOINT新增引數 CMD command param1 param2 ##執行shell內部命令 例如: CMD ["/usr/bin/wc","--help"]
注意:
- CMD不同於RUN,CMD用於指定在容器啟動時所要執行的命令,而RUN用於指定映象構建時所要執行的命令。
- 在EXEC形式被解析為一個JSON陣列,這意味著必須使用雙引號(“)周圍的話不單引號(')
4、LABEL:設定映象標籤
新增(K-V)形式後設資料到映象中,如果標籤值中需要包含空格時,需要設定引號;反斜槓用於換號設定;示例如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
例如:
LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
注意:
- 映象中可以有多個LABLE,可以在一行指令中指定多個標籤,如以下兩種格式:
LABEL multi.label1="value1" multi.label2="value2" other="value3" LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
- 可以繼承基礎映象中包含的的標籤,如果標籤已存在時,但值不同;則最近設定的值將覆蓋以前的值
5、MAINTAINER(廢棄):設定生成映象的作者資訊,可使用更加靈活的LABEL替代
MAINTAINER <name> 例如: MAINTAINER <name> 替代: LABEL maintainer="abc"
6、EXPOSE:指定容器執行時監聽指定網路埠;可以設定埠是TCP或UDP,預設TCP;
語法:
EXPOSE <port> [<port>/<protocol>...] 例如: EXPOSE 80/tcp EXPOSE 80/udp
注意:EXPOSE並不會讓容器的埠訪問到主機。要使其可訪問,需要在docker run
執行容器時通過-p來發布這些埠,或通過-P
引數來發布EXPOSE匯出的所有埠
7、ENV:設定環境變數
語法:
ENV <key>=<value> ... ##可以設定多個環境變數,如果key中包含空格,使用""進行標識;反斜槓用於換行 ENV <key> <value> ##只能設定一個置,不推薦該寫法 例如: ENV MY_NAME="John Doe" ENV MY_DOG=Rex\ The\ Dog ENV MY_CAT=fluffy
注意:
- 從生成的映像執行容器時,使用ENV設定的環境變數將保持不變。
- 修改ENV:docker run --env <key>=<value>
8、ADD:將本地檔案新增到容器中
ADD [--chown=<user>:<group>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] ##包含空格的路徑時,使用該方式 例如: ADD test.txt relativeDir/ ADD test.txt /absoluteDir/
注意:
--chown
功能僅在用於構建Linux容器的Dockerfiles上受支援,而在Windows容器上不起作用- src可以指定讀個資源,但是如果它們是檔案或目錄,則將其路徑解釋為相對於構建上下文源的路徑。
- src支援萬用字元,匹配規則採用Go的 filepath.Match規則完成
- 目錄本身不被複制,僅其內容被複制。
- 如果
<src>
是以公認的壓縮格式(身份,gzip,bzip2或xz)作為本地tar歸檔檔案,則將其解壓縮為目錄,來自遠端URL的資源不會被解壓縮。 - 如果
<src>
直接或由於使用萬用字元而指定了多個資源,則該資源<dest>
必須是目錄,並且必須以斜槓結尾/
- 如果
<dest>
不以斜槓結尾,則將其視為常規檔案,並將其內容<src>
寫入<dest>
- 如果
<dest>
不存在,它將與路徑中所有缺少的目錄一起建立
9、COPY:複製檔案到容器指定目錄
COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] 例如: COPY test.txt /absoluteDir/ COPY test.txt relativeDir/
注意:同ADD指令差不多,區別為以下內容
- 不會自動解壓檔案,也不能訪問網路資源
- src不能為網路資源
10、ENTRYPOINT:配置容器,使其可執行化
ENTRYPOINT ["executable", "param1", "param2"] ##(可執行檔案, 優先) ENTRYPOINT command param1 param2 ##(shell內部命令) 例如: ENTRYPOINT ["top", "-b"]
CMD和ENTRYPOINT相互作用
-
Dockerfile應至少指定
CMD
或ENTRYPOINT
命令之一。 -
ENTRYPOINT
使用容器作為可執行檔案時應定義。 -
CMD
應該用作ENTRYPOINT
在容器中定義命令或執行臨時命令的預設引數的方式。 -
CMD
當使用替代引數執行容器時,將被覆蓋。
11、VOLUME:指定持久化目錄
VOLUME ["/data"] 例如: VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
注意:
- 一個卷可以存在於一個或多個容器的指定目錄,該目錄可以繞過聯合檔案系統,並具有以下功能:
- 卷可以容器間共享和重用
- 容器並不一定要和其它容器共享卷
- 修改卷後會立即生效
- 對卷的修改不會對映象產生影響
- 卷會一直存在,直到沒有任何容器在使用它
- 基於Windows的容器上的卷:使用基於Windows的容器時:除C盤目錄、不存在或空目錄
- 從Dockerfile中更改卷:如果在宣告瞭卷之後有任何構建步驟更改了卷中的資料,則這些更改將被丟棄。
- SON格式:列表被解析為JSON陣列。您必須用雙引號(
"
)而不是單引號('
)括住單詞。
12、USER:指定執行容器時的使用者名稱或 UID,後續的 RUN 也會使用指定使用者
USER <user>[:<group>]
or
USER <UID>[:<GID>]
注意:
- 使用USER指定使用者後,Dockerfile中其後的命令RUN、CMD、ENTRYPOINT都將使用該使用者。
- 映象構建完成後,通過
docker run
執行容器時,可以通過-u引數來覆蓋所指定的使用者。 - 當服務不需要管理員許可權時,可以通過該命令指定執行使用者。並且可以在之前建立所需要的使用者
13、WORKDIR:設定工作目錄
WORKDIR /path/to/workdir
注意:
-
通過WORKDIR設定工作目錄後,Dockerfile中其後的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都會在該目錄下執行。
-
在使用
docker run
執行容器時,可以通過-w引數覆蓋構建時所設定的工作目錄。
14、ARG:構建引數
ARG <name>[=<default value>] 例如: ARG user1=someuser ARG buildno=1
注意:
- ARG 設定的環境變數僅對 Dockerfile 內有效
- 不建議使用構建變數傳遞敏感資訊,構建變數值在docker history 可以檢視
- 內建Arg變數:
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
15、ONBUILD:設定映象觸發器
ONBUILD <INSTRUCTION> 例如: ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注意:
- 不允許
ONBUILD
使用連結說明ONBUILD ONBUILD
ONBUILD
指令可能不會觸發FROM
或MAINTAINER
指令
16、STOPSIGNAL: STOPSIGNAL指令設定將傳送到容器以退出的系統呼叫訊號
STOPSIGNAL signal
17、HEALTHCHECK:指定某個程式或者指令來監控 docker 容器服務的執行狀態。
兩種形式: HEALTHCHECK [OPTIONS] CMD command (通過在容器內部執行命令來檢查容器執行狀況) HEALTHCHECK NONE (禁用從基映像繼承的任何執行狀況檢查) 例如: HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
注意:
-
HEALTHCHECK
Dockerfile中只能有一條指令。如果您列出多個,則只有最後一個HEALTHCHECK
才會生效。
18、SHELL:允許重寫命令的SHELL形式所使用的預設SHELL。Linux上的預設shell為[“/bin/sh”、“-c”];Windows上的預設shell為[“cmd”、“/S”、“/c”]
語法:
SHELL ["executable", "parameters"] 例如: SHELL ["powershell", "-command"]
注意:
SHELL
可以出現多次。每個SHELL
指令將覆蓋所有先前的SHELL
指令,並影響所有後續的指令SHELL
指令在Windows上特別有用,在Windows上有兩個常用且完全不同的本機shell:cmd
和powershell
DockerFile示例:
#設定基礎映象 FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base #設定工作目錄
WORKDIR /app #設定監聽埠
EXPOSE 80
#設定映象 FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
#設定工作目錄 WORKDIR /src
#複製資料夾 COPY ["cz.IdentityServer/cz.IdentityServer.csproj", "cz.IdentityServer/"] #執行專案還原命令
RUN dotnet restore "cz.IdentityServer/cz.IdentityServer.csproj" #複製檔案
COPY . . WORKDIR "/src/cz.IdentityServer"
#執行編譯專案命令 RUN dotnet build "cz.IdentityServer.csproj" -c Release -o /app/build #執行釋出專案 FROM build AS publish RUN dotnet publish "cz.IdentityServer.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app
#複製釋出內容到docker目錄 COPY --from=publish /app/publish .
#啟動專案 ENTRYPOINT ["dotnet", "cz.IdentityServer.dll"]
參考:https://docs.docker.com/engine/reference/builder/