【docker】 Dockerfile

Dockerfile鏡像構建命令

指令:FROM 
功能描述:設置基礎鏡像 
語法:FROM < image>[:< tag> | @< digest>] 
說明:

  • FROM指定構建鏡像的基礎源鏡像,如果本地沒有指定的鏡像,則會自動從 Docker 的公共庫 pull 鏡像下來。
  • FROM必須是 Dockerfile 中非註釋行的第一個指令,即一個 Dockerfile 從FROM語句開始。
  • FROM可以在一個 Dockerfile 中出現多次,如果有需求在一個 Dockerfile 中創建多個鏡像。
  • 如果FROM語句沒有指定鏡像標籤,則默認使用latest標籤。 

指令:COPY
功能描述:COPY 指令將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置
語法:

  • COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
  • COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]

注意:使用 COPY 指令,源文件的各種元數據都會保留。比如讀、寫、執行權限、文件變更時間等。這個特性對於鏡像定製很有用。特別是構建相關文件都在使用 Git 進行管理的時候

  • 如果<源路徑>爲文件,則複製文件和元數據 
  • 如果<目標路徑>不存在,指令會自動創建<目標路徑>和缺失的上級目錄

指令:ADD
功能描述:ADD 指令和 COPY 的格式和性質基本一致。但是在 COPY 基礎上增加了一些功能。
語法:

  • COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
  • COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"]

說明:自動解壓縮的功能非常有用,因此在 COPY 和 ADD 指令中選擇的時候,可以遵循這樣的原則,所有的文件複製均使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD

  • <源路徑>爲URL時,docker自動下載下載到<目標路徑>路徑,並且默認權限爲600。可以使用RUN命令調整權限。
  • <源路徑>爲壓縮文件時,並且壓縮方式爲gzip,bzip2或xz時,指令會將其解壓爲目錄 

指令:CMD 
功能描述:Docker 不是虛擬機,容器就是進程。既然是進程,那麼在啓動容器的時候,需要指定所運行的程序及參數。CMD 指令就是用於指定默認的容器主進程的啓動命令的,在運行時可指定新的命令來替代鏡像設置中的默認命令
語法:

  • shell 格式: CMD <命令>
  • exec 格式: CMD ["可執行文件", "參數1", "參數2"...]
  • 參數列表格式: CMD ["參數1", "參數2"...] 。在指定了 ENTRYPOINT 指令後,用 CMD 指定具體的參數。

注意:

  • Docker 不是虛擬機,容器中的應用都應該以前臺執行,而不是像虛擬機、物理機裏面那樣,用 systemd 或者systemctl去啓動後臺服務,容器內沒有後臺服務的概念
  • Dockerfile中只能有一條CMD命令,如果多條則最後一條生效,如果用戶啓動容器時指定了運行的命令,則會覆蓋掉CMD指定的命令。

指令:ENTRYPOINT 
功能描述:指定鏡像的默認入口命令,該入口命令會在啓動容器時作爲根命令執行,所有傳入值作爲該命令的參數
語法:

  • exec方式:ENTRYPOINT [“executable”,”param1”,”param2”] 
  • shell方式:ENTRYPOINT command param1 param2

說明:

  • 入口程序是容器啓動時執行的程序,docker run中最後的命令將作爲參數傳遞給入口程序 
  • 入口程序有兩種格式:exec、shell,其中shell使用/bin/sh -c運行入口程序,此時入口程序不能接收信號量 
  • 當Dockerfile有多條ENTRYPOINT時只有最後的ENTRYPOINT指令生效 
  • 如果使用腳本作爲入口程序,需要保證腳本的最後一個程序能夠接收信號量,可以在腳本最後使用exec或gosu啓動傳入腳本的命令 
  • 通過shell方式啓動入口程序時,會忽略CMD指令和docker run中的參數 
  • 爲了保證容器能夠接受docker stop發送的信號量,需要通過exec啓動程序;如果沒有加入exec命令,則在啓動容器時容器會出現兩個進程,並且使用docker stop命令容器無法正常退出(無法接受SIGTERM信號),超時後docker stop發送SIGKILL,強制停止容器 
  • Dockerfile中只能有一條ENTRYPOINT 命令,如果多條則最後一條生效,如果用戶啓動容器時指定了運行的命令,則會覆蓋掉ENTRYPOINT 指定的命令。

例子:FROM ubuntu <換行> ENTRYPOINT exec top -b


指令:MAINTAINER 
功能描述:指定創建鏡像的用戶 
語法:MAINTAINER < name> 


指令:RUN 
功能描述: 運行構建鏡像的命令
語法:

  • shell 格式:RUN < command>    使用/bin/sh -c < command>運行腳本,可以在其中使用 \ 將腳本分爲多行以及行首 # 進行註釋
  • exec 格式:RUN [“executable”,”param1”,”param2”] 

說明:每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像,後續的RUN都在之前RUN提交後的鏡像爲基礎,鏡像是分層的,可以通過一個鏡像的任何一個歷史提交點來創建,類似源碼的版本控制。
例子:


指令:LABEL 
功能描述:用於生成鏡像的元數據的標籤信息
語法:LABEL < key>=< value> < key>=< value> … 
說明:每條指令都會生成一個鏡像層,Docker中鏡像最多只能有127層,如果超出Docker Daemon就會報錯,如LABEL ..=.. <假裝這裏有個換行> LABEL ..=..合在一起用空格分隔就可以減少鏡像層數量,同樣,可以使用連接符\將腳本分爲多行,鏡像會繼承基礎鏡像中的標籤,如果存在同名標籤則會覆蓋。


指令:EXPOSE 
功能描述:設置鏡像暴露端口,聲明鏡像內服務所監聽的端口
語法:EXPOSE < port> [< port> … ]
說明:

  • 容器啓動時,Docker Daemon會掃描鏡像中暴露的端口,在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口 
  • EXPOSE只是起到聲明租用的作用,只有啓動容器時使用-P/-p纔是端口映射,這個時候才能通過外部訪問容器提供的服務

例子:-p <宿主端口>:<容器端口>


指令:ENV 
功能描述:設置鏡像中的環境變量 
語法:

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

說明:環境變量在整個編譯週期都有效,通過${變量名}或者 $變量名使用變量,使用方式${變量名}時可以用${變量名:-default} ${變量名:+cover}設定默認值或者覆蓋值,ENV設置的變量值在整個編譯過程中總是保持不變的,但指令指定的環境變量在運行時可以被覆蓋掉,如docker run --env <key>=<value> built_image

例子:

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"

指令:VOLUME 
功能描述:設置容器的掛載點 
語法:

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

說明:啓動容器時,Docker Daemon會新建掛載點,並用鏡像中的數據初始化掛載點,可以將主機目錄或數據卷容器掛載到這些掛載點,一般用來存放數據庫和需要保存的數據等。


指令:USER 
功能描述:指定當前用戶
語法:USER <用戶名>[:<用戶組>]


指令:WORKDIR 
功能描述:設置RUN CMD ENTRYPOINT ADD COPY指令的工作目錄 
語法:WORKDIR <工作目錄路徑>
說明:如果工作目錄不存在,則Docker Daemon會自動創建 
          Dockerfile中多個地方都可以調用WORKDIR,如果後面跟的是相對位置,則會跟在上條WORKDIR指定路徑後(如WORKDIR /A   WORKDIR B   WORKDIR C,最終路徑爲/A/B/C)


指令:ARG 
功能描述:指定一些鏡像內使用的參數(例如版本號信息等)
語法:ARG < name>[=< defaultValue>] 
說明:ARG 所設置的構建環境的環境變量,在將來容器運行時是不會存在這些環境變量的。

  • Dockerfile 中的 ARG 指令是定義參數名稱,以及定義其默認值。該默認值可以在構建命令 docker build 中用 --build-arg <參數名>=<值> 來覆蓋
  • ARG從定義它的地方開始生效而不是調用的地方,在ARG之前調用編譯變量總爲空,在編譯鏡像時,可以通過docker build --build-arg < var>=< value>設置變量,如果var沒有通過ARG定義則Daemon會報錯 
  • 可以使用ENV或ARG設置RUN使用的變量,如果同名則ENV定義的值會覆蓋ARG定義的值,與ENV不同,ARG的變量值在編譯過程中是可變的,會對比使用編譯緩存造成影響(ARG值不同則編譯過程也不同) 

指令:ONBUILD 
功能描述:ONBUILD 是一個特殊的指令,它後面跟的是其它指令,比如 RUNCOPY 等,而這些指令,在當前鏡像構建時並不會被執行。只有當以當前鏡像爲基礎鏡像,去構建下一級鏡像的時候纔會被執行
語法:ONBUILD [INSTRUCTION] 
提示:從該鏡像生成子鏡像,在子鏡像的編譯過程中,首先會執行父鏡像中的ONBUILD指令,所有編譯指令都可以成爲鉤子指令


指令:STOPSIGNAL 
功能描述:指定所創建鏡像啓動的容器接收退出的信號值,設置容器退出時,Docker Daemon向容器發送的信號量 
語法:STOPSIGNAL signal 
提示:信號量可以是數字或者信號量的名字,如9或者SIGKILL。 


指令:HEALTHCHECK 
功能描述:健康檢查
語法:

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

說明:當在一個鏡像指定了 HEALTHCHECK 指令後,用其啓動容器,初始狀態會爲 starting,在 HEALTHCHECK 指令檢查成功後變爲 healthy,如果連續一定次數失敗,則會變爲 unhealthy

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

 

 鏡像構建

1.全流程都在同一個Dockerfile中構建

2.分爲多個Dockerfile+腳本構建

3.多階段構建

只構建某一階段的鏡像

我們可以使用 as 來爲某一階段命名,例如

FROM golang:1.9-alpine as builder

例如當我們只想構建 builder 階段的鏡像時,增加 --target=builder 參數即可

$ docker build --target builder -t username/imagename:tag .

構建時從其他鏡像複製文件

上面例子中我們使用 COPY --from=0 /go/src/github.com/go/helloworld/app . 從上一階段的鏡像中複製文件,我們也可以複製任意鏡像中的文件。

$ COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

 

常見問題 

1.CMD ENTRYPOINT和RUN的區別

    RUN指令是設置編譯鏡像時執行的腳本和程序,鏡像編譯完成後,RUN指令的生命週期結束

    容器啓動時,可以通過CMD和ENTRYPOINT設置啓動項,其中CMD叫做容器默認啓動命令,如果在docker run命令末尾添加command,則會替換鏡像中CMD設置的啓動程序;ENRTYPOINT叫做入口程序,不能被docker run命令末尾的command替換,而是將command當作字符串,傳遞給ENTRYPOINT作爲參數

FROM ubuntu
ENTRYPOINT ["ps"]

//通過命令docker run --rm test啓動容器,打印ps的輸出
//通過命令docker run --rm test -ef啓動容器,打印ps -ef的輸出

在docker run中,可以通過–entrypoint替換鏡像中的入口程序,在Dockerfile中,應該至少有一條CMD或者ENTRYPOINT指令,如果同時定義了CMD和ENTRYPOINT則CMD會作爲參數傳遞給ENTRYPOINT

FROM ubuntu
ENTRYPOINT ["ps"]
CMD ["-ef"]

//通過命令docker run --rm test啓動容器,打印ps -ef的輸出

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章