Dockerfile基本指令

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#dockerfile-instructions

Dockerfile 是 text document

A Dockerfile is a text document that contains all the commands you would normally execute manually in order to build a Docker image. Docker can build images automatically by reading the instructions from a Dockerfile.

A Docker image consists of read-only layers each of which represents a Dockerfile instruction. The layers are stacked and each one is a delta of the changes from the previous layer. Consider this?Dockerfile:

FROM ubuntu:15.04

COPY. /app

RUN make/app

CMD python/app/app.py

Each instruction creates one layer:

FROM?creates a layer from the?ubuntu:15.04?Docker image.

COPY?adds files from your Docker client’s current directory.

RUN?builds your application with?make.

CMD?specifies what command to run within the container.

When you run an image and generate a container, you add a new?writable layer?(the “container layer”) on top of the underlying layers. All changes made to the running container, such as writing new files, modifying existing files, and deleting files, are written to this thin writable container layer.


基本指令13個:

FROM MAINTAINER RUN CMD EXPOSE? ENV ADD COPY ENTRYPOINT VOLUME USER WORKDIR ONBUILD


FROM


指定Base鏡像(parent image)并且必須是第一條指令。

如果不以任何鏡像為基礎,那么寫法為:FROM scratch。

同時意味著接下來所寫的指令將作為鏡像的第一層開始

語法:

FROM <image>

FROM <image>:<tag>

FROM <image>:<digest>

三種寫法,其中<tag>和<digest> 是可選項,如果沒有選擇,那么默認值為latest


MAINTAINER


設置鏡像的作者,可以是任意字符串。

MAINTAINER <name>


WORKDIR


為后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY?設置鏡像中的當前工作目錄。如果不存在則會創建,也可以設置多次。


語法:

WORKDIR /path/to/workdir

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

pwd執行的結果是/a/b/c

WORKDIR也可以解析環境變量

ENV DIRPATH /path

WORKDIR $DIRPATH/$DIRNAME

RUN pwd

pwd的執行結果是/path/$DIRNAME

RUN


在容器中運行指定的命令

RUN命令有兩種格式

1. RUN <command>? (后邊直接跟shell命令)

在linux操作系統上默認 /bin/sh -c

在windows操作系統上默認 cmd /S /C

2. RUN ["executable", "param1", "param2"]

類似于函數調用。

可將executable理解成為可執行文件,后面就是兩個參數。

兩種寫法對比:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME

RUN ["/bin/bash", "-c", "echo hello"]

注意:

· 多行命令不要寫多個RUN,原因是Dockerfile中每一個指令都會建立一層.

·??多少個RUN就構建了多少層鏡像,會造成鏡像的臃腫、多層,不僅僅增加了構件部署的時間,還容易出錯。

·??RUN書寫時的換行符是\


CMD


容器啟動時要運行的命令

語法·三種寫法

1. CMD ["executable","param1","param2"]

2. CMD ["param1","param2"]

3. CMD command param1 param2

第三種比較好理解了,就是shell這種執行方式和寫法

第一種和第二種其實都是可執行文件加上參數的形式

寫法一: CMD [ "sh", "-c", "echo $HOME"]

寫法二: CMD [ "echo", "$HOME" ]

注意:

· 這里邊包括參數的一定要用雙引號,就是",不能是單引號。千萬不能寫成單引號。

原因是參數傳遞后,docker解析的是一個JSON array

·? Dockerfile 中可以有多個 CMD 指令,但只有最后一個生效。CMD 可以被 docker run?之后的參數替換。

?

RUN 與 CMD


不要把RUN和CMD搞混了。

RUN是構件容器時就運行的命令以及提交運行結果

CMD是容器啟動時執行的命令,在構件時并不運行,構件時僅僅指定了這個命令到底是個什么樣子


EXPOSE


功能為暴漏容器運行時的監聽端口給外部

但是EXPOSE并不會使容器訪問主機的端口

指定容器中的進程會監聽某個端口,Docker 可以將該端口暴露出來

如果想使得容器與主機的端口有映射關系,必須在容器啟動的時候加上 -P參數


ENV


功能為設置環境變量

語法有兩種

1. ENV <key> <value>

2. ENV <key>=<value> ...

兩者的區別就是第一種是一次設置一個,第二種是一次設置多個


ADD


?一個復制命令,把文件復制到鏡像中。

如果把虛擬機與容器想象成兩臺linux服務器的話,那么這個命令就類似于scp,只是scp需要加用戶名和密碼的權限驗證,而ADD不用。

語法:

1. ADD <src>... <dest>

2. ADD ["<src>",... "<dest>"]

<dest>路徑的填寫可以是容器內的絕對路徑,也可以是相對于工作目錄的相對路徑

<src>可以是一個本地文件或者是一個本地壓縮文件,還可以是一個url

如果把<src>寫成一個url,那么ADD就類似于wget命令

以下寫法都是可以的:

ADD test relativeDir/?

ADD test /relativeDir

ADD http://example.com/foobar /

盡量不要把<scr>寫成一個文件夾,如果<src>是一個文件夾了,復制整個目錄的內容,包括文件系統元數據


COPY


看這個名字就知道,又是一個復制命令

語法如下:

1. COPY <src>... <dest>

2. COPY ["<src>",... "<dest>"]

與ADD的區別

COPY的<src>只能是本地文件,其他用法一致


ENTRYPOINT


設置容器啟動時的默認命令

Dockerfile 中可以有多個 ENTRYPOINT 指令,但只有最后一個生效。

CMD 或 docker run?之后的參數會被當做參數傳遞給 ENTRYPOINT。


語法如下:

1. ENTRYPOINT ["executable", "param1", "param2"]

可執行文件加參數

2. ENTRYPOINT command param1 param2

寫shell


?ENTRYPOINT與CMD比較

(二者很類似,可配合使用):

1. 相同點:

只能寫一條,如果寫了多條,那么只有最后一條生效

容器啟動時才運行,運行時機相同

2. 不同點:

?ENTRYPOINT不會被運行的command覆蓋,而CMD則會被覆蓋

如果我們在Dockerfile種同時寫了ENTRYPOINT和CMD,并且CMD指令不是一個完整的可執行命令,那么CMD指定的內容將會作為ENTRYPOINT的參數。?

FROM ubuntu

ENTRYPOINT ["top", "-b"]

CMD ["-c"]

如果我們在Dockerfile種同時寫了ENTRYPOINT和CMD,并且CMD是一個完整的指令,那么它們兩個會互相覆蓋,誰在最后誰生效

FROM ubuntu

ENTRYPOINT ["top", "-b"]

CMD ls -al

那么將執行ls -al?

top -b不會執行


CMD 與 ENTRYPOINT

VOLUME


將文件或目錄聲明為 volume

可實現掛載功能,可以將內地文件夾或者其他容器種得文件夾掛在到這個容器種

語法為:

VOLUME ["/data"]


說明:

? ?["/data"]可以是一個JsonArray ,也可以是多個值。所以如下幾種寫法都是正確的

VOLUME ["/var/log/"]

VOLUME /var/log

VOLUME /var/log /var/db

一般的使用場景為需要持久化存儲數據時

容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉后,所有的更改都會丟失。

所以當數據需要持久化時用這個命令。



USER


設置啟動容器的用戶,可以是用戶名或UID,所以,只有下面的兩種寫法是正確的

USER daemo

USER UID

注意:如果設置了容器以daemon用戶去運行,那么RUN, CMD 和 ENTRYPOINT 都會以這個用戶去運行


ONBUILD


語法:

ONBUILD [INSTRUCTION]

這個命令只對當前鏡像的子鏡像生效。

比如當前鏡像為A,在Dockerfile種添加:

ONBUILD RUN ls -al

這個 ls -al 命令不會在A鏡像構建或啟動的時候執行

此時有一個鏡像B是基于A鏡像構建的,那么這個ls -al 命令會在B鏡像構建的時候被執行。


其他命令?


STOPSIGNAL

語法:

STOPSIGNAL signal

STOPSIGNAL命令是的作用是當容器推出時給系統發送什么樣的指令



HEALTHCHECK

?容器健康狀況檢查命令

語法有兩種:

1. HEALTHCHECK [OPTIONS] CMD command

2. HEALTHCHECK NONE

第一個的功能是在容器內部運行一個命令來檢查容器的健康狀況

第二個的功能是在基礎鏡像中取消健康檢查命令


[OPTIONS]的選項支持以下三中選項:

? ? --interval=DURATION 兩次檢查默認的時間間隔為30秒

? ? --timeout=DURATION 健康檢查命令運行超時時長,默認30秒

? ? --retries=N 當連續失敗指定次數后,則容器被認為是不健康的,狀態為unhealthy,默認次數是3


注意:

HEALTHCHECK命令只能出現一次,如果出現了多次,只有最后一個生效。


CMD后邊的命令的返回值決定了本次健康檢查是否成功,具體的返回值如下:

0: success - 表示容器是健康的

1: unhealthy - 表示容器已經不能工作了

2: reserved - 保留值


例子:

HEALTHCHECK --interval=5m --timeout=3s \

CMD curl -f http://localhost/ || exit 1


健康檢查命令是:curl -f http://localhost/ || exit 1

兩次檢查的間隔時間是5秒

命令超時時間為3秒



LABEL

功能是為鏡像指定標簽

語法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

?一個Dockerfile種可以有多個LABEL,如下:

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."

?但是并不建議這樣寫,最好就寫成一行,如太長需要換行的話則使用\符號

如下:

LABEL multi.label1="value1" \

multi.label2="value2" \

other="value3"

說明:LABEL會繼承基礎鏡像種的LABEL,如遇到key相同,則值覆蓋



ARG

語法:

ARG <name>[=<default value>]

設置變量命令,ARG命令定義了一個變量,在docker build創建鏡像的時候,使用 --build-arg <varname>=<value>來指定參數

如果用戶在build鏡像時指定了一個參數沒有定義在Dockerfile種,那么將有一個Warning

提示如下:

[Warning] One or more build-args [foo] were not consumed.

我們可以定義一個或多個參數,如下:

FROM busybox

ARG user1

ARG buildno

...

也可以給參數一個默認值:

FROM busybox

ARG user1=someuser

ARG buildno=1

...

如果我們給了ARG定義的參數默認值,那么當build鏡像時沒有指定參數值,將會使用這個默認值

轉載自:https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容