帶你深入瞭解DockerFile命令

2022-02-22 19:00:57
本篇文章給大家帶來了關於命令的相關知識,該命令包含一條條指令,每條指令構建一層的映象製作檔案,希望對大家有幫助。

推薦學習:《》

DockerFile 命令詳解

Dockerfile 是包含一條條指令,每條指令構建一層的映象製作檔案。

構建映象

docker build [選項] <上下文路徑/URL/->

docker build -t nginx:v3 .           # . 表示Dockerfile在當前目錄

FROM 指定基礎映象

通過FROM指定基礎映象,因此一個 Dockerfile 中 FROM 是必備的指令,並且必須是第一條指令。

FROM scratch,這個映象是虛擬的概念,並不實際存在,它表示一個空白的映象,接下來的指令將作為映象第一層開始存在。

RUN 執行命令

RUN 用來執行命令列命令,其格式有兩種:

shell 格式:

RUN <命令>

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

exec 格式:

RUN ["可執行檔案", "引數1", "引數2"]

Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層,相同功能應該使用 && 將各個所需命令串聯起來簡化映象的層數

COPY 複製檔案

COPY [--chown=<user>:<group>] <宿主機源路徑> <映象內的目標路徑>
COPY [--chown=<user>:<group>] ["<宿主機源路徑1>",... "<映象內的目標路徑>"]
# 把當前目錄的a.txt檔案複製到映象的根目錄
COPY a.txt /a.txt

ADD 複製檔案(下載檔案或解壓檔案)

ADD [--chown=<user>:<group>] http://xxx <目標路徑>       # 下載檔案到映象的目標路徑
ADD [--chown=<user>:<group>] ./a.tar.gz <目標路徑>       # 複製壓縮包,並自動解壓到目標路徑

CMD 指定預設的容器主程序的啟動命令

CMD ["可執行檔案", "引數1", "引數2"...]
# 指定進入容器馬上指定 cat /a.txt

CMD ["sh","-c", "cat /a.txt"]

執行 docker run -it 映象的時候,如果不指定命令類似 /bin/bash ,會自動執行 sh -c cat /a.txt,否則會按使用者指定的CMD

ENTRYPOINT 指定容器主程序的啟動命令,類似CMD

格式與CMD一致,差異點

1、使用ENTRYPOINT可以傳參

在Dockerfile中指定ENTRYPOINT [ "curl", "-s", "http://myip.ipip.net" ],命令列通過 docker run myip -i 時,會把 -i 引數傳給 ENTRYPOINT 的命令,最後進入
容器時,容器會執行 curl -s http://myip.ipip.net -i

2、執行一些與 CMD 無關的初始化工作,與容器 CMD 無關的,無論 CMD 為什麼,都需要事先進行一個預處理的工作。

類似 ENTRYPOINT ["docker-entrypoint.sh"] 這個指令碼裡檢查使用者的身份是否合法等

ENV 設定環境變數

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

ARG 構建引數

ARG <引數名>[=<預設值>]

ARG 指令有生效範圍,如果在 FROM 指令之前指定,那麼只能用於 FROM 指令中。

ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

如果在FROM之後指定,對於在各個階段中使用的變數都必須在每個階段分別指定

FROM ${DOCKER_USERNAME}/alpine

# 在FROM 之後使用變數,必須在每個階段分別指定
ARG DOCKER_USERNAME=library

RUN set -x ; echo ${DOCKER_USERNAME}

VOLUME 匿名卷

VOLUME ["<路徑1>", "<路徑2>"...]
VOLUME <路徑>

為了防止執行時使用者忘記將動態檔案所儲存目錄掛載為卷,在 Dockerfile 中,可以事先指定某些目錄掛載為匿名卷,這樣在執行時如果使用者不指定掛載,其應用也可以正常執行,不會向容器儲存層寫入大量資料

這裡的 /data 目錄就會在容器執行時自動掛載為匿名卷,任何向 /data 中寫入的資訊都不會記錄進容器儲存層,從而保證了容器儲存層的無狀態化。

EXPOSE 暴露埠

EXPOSE <埠1> [<埠2>...]

EXPOSE 指令是宣告容器執行時提供服務的埠,EXPOSE 僅僅是宣告容器打算使用什麼埠而已,並不會自動在宿主進行埠對映。

在 Dockerfile 中寫入這樣的宣告有兩個好處,一個是幫助映象使用者理解這個映象服務的守護埠,以方便設定對映;

另一個用處則是在執行時使用隨機埠對映時,也就是 docker run -P 時,會自動隨機對映 EXPOSE 的埠。

要將 EXPOSE 和在執行時使用 -p <宿主埠>:<容器埠> 區分開來。

-p,是對映宿主埠和容器埠,換句話說,就是將容器的對應埠服務公開給外界存取。

WORKDIR 指定工作目錄,如該目錄不存在,WORKDIR 會建立目錄

WORKDIR <工作目錄路徑>

例子1:

WORKDIR /app

RUN echo "hello" > world.txt

例子2:

WORKDIR /a
WORKDIR b
WORKDIR c

RUN pwd

## RUN pwd 的工作目錄為 /a/b/c

USER 指定當前使用者

USER <使用者名稱>[:<使用者組>]

如果以 root 執行的指令碼,在執行期間希望改變身份,比如希望以某個已經建立好的使用者來執行某個服務程序,不要使用 su 或者 sudo,這些都需要比較麻煩的設定,而且在 TTY 缺失的環境下經常出錯。建議使用 gosu。

# 建立 redis 使用者,並使用 gosu 換另一個使用者執行命令
RUN groupadd -r redis && useradd -r -g redis redis

# 下載 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64" \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
    
# 設定 CMD,並切換到redis使用者執行
CMD [ "exec", "gosu", "redis", "redis-server" ]

HEALTHCHECK 告訴 Docker 如何進行判斷容器的狀態是否正常

HEALTHCHECK [選項] CMD <命令>:設定檢查容器健康狀況的命令
HEALTHCHECK NONE:如果基礎映象有健康檢查指令,使用這行可以遮蔽掉其健康檢查指令

選項:

--interval=<間隔>:兩次健康檢查的間隔,預設為 30 秒;
--timeout=<時長>:健康檢查命令執行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,預設 30 秒;
--retries=<次數>:當連續失敗指定次數後,則將容器狀態視為 unhealthy,預設 3 次

當在一個映象指定了 HEALTHCHECK 指令後,用其啟動容器,初始狀態會為 starting,在 HEALTHCHECK 指令檢查成功後變為 healthy,如果連續一定次數失敗,則會變為 unhealthy。

HEALTHCHECK 只可以出現一次,如果寫了多個,只有最後一個生效

CMD 命令的返回值決定了該次健康檢查的成功與否:0:成功;1:失敗

ONBUILD 指定某些命令只有當以當前映象為基礎映象,去構建下一級映象的時候才會被執行

ONBUILD <其它指令>
# 舉例如下Dockerfile,初次構建為映象my-node時,ONBUILD的三行命令不會執行

FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

# 只要當其他映象 FROM my-node 從上面映象作為基礎映象進行構建時,ONBUILD 的命令開始執行

LABEL 為映象新增後設資料

LABEL <key>=<value> <key>=<value> <key>=<value> ...
# 標註映象的作者

LABEL org.opencontainers.image.authors="yeasy"

SHELL 指定執行shell命令的引數

SHELL ["可執行程式", "引數"]
SHELL ["/bin/sh", "-c"]

RUN lll ; ls             # 這裡的shell命令將通過 /bin/sh -c 的方式執行

推薦學習:《》

以上就是帶你深入瞭解DockerFile命令的詳細內容,更多請關注TW511.COM其它相關文章!