Docker 構建腳本 Dockerfile 指令全解析

1. 前言

Dockerfile 是用來構建自定義 Docker 鏡像的文本文檔。咱們經過docker build 命令用於從Dockerfile 文件構建鏡像。 若是你要構建自定義鏡像,Dockerfile 是你必須學會的技能之一。java

2. Dockerfile 的基本結構

Dockerfile 通常分爲:基礎鏡像、鏡像元信息、鏡像操做指令和容器啓動時執行指令,#Dockerfile 中的註釋。python

3. Dockerfile 文件說明

Docker 從上到下的順序運行Dockerfile 的指令,每個指令都以 step 爲步驟。並且文件的命名也必須爲 Dockerfilemysql

4. Dockerfile 經常使用的指令。

接下來對經常使用的 Dockerfile 指令進行總結。spring

4.1 FROM 指令

FROM是指定基礎鏡像,必須爲第一個命令,格式:sql

FROM <image>:<tag>docker

其中 tagdigest 是可選的,若是不使用這兩個值時,會使用 latest 版本的基礎鏡像。 shell

示例: FROM mysql:5.6apache

4.2 MAINTAINER 指令

MAINTAINER 用來聲明維護者信息,該命令已通過期,推薦使用 LABEL ,格式:ubuntu

MAINTAINER <name>緩存

4.3 LABEL 指令

LABEL:用於爲鏡像添加元數據,多用於聲明構建信息,做者、機構、組織等。格式:

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

示例: LABEL version="1.0" description="felord.cn" by="Felordcn"

使用LABEL 指定元數據時,一條LABEL指定能夠指定一或多條元數據,指定多條元數據時不一樣元數據之間經過空格分隔。推薦將全部的元數據經過一條LABEL指令指定,以避免生成過多的中間鏡像。

4.4 ENV 指令

ENV 用來設置環境變量,格式:

ENV <key> <value>  
 
ENV <key>=<value>

示例: ENV version 1.0.0 或者 ENV version=1.0.0

能夠經過 ${key} 在其它指令中來引用變量,如 ${version} 。咱們也能夠經過 docker run 中的 -e <ENV> 來動態賦值

4.5 ARG 指令

ARG 用於指定傳遞給構建運行時的變量,格式:

ARG <name>[=<default value>]

經過 docker run 中的 --build-arg <key>=<value> 來動態賦值,不指定將使用其默認值。

4.6 WORKDIR 指令

WORKDIR 用來指定工做目錄,相似於咱們一般使用的cd 命令,格式:

WORKDIR <PATH>

經過 WORKDIR 設置工做目錄,Dockerfile 中的其它指令 RUNCMDENTRYPOINTADDCOPY等命令都會在該目錄下執行。在使用 docker run 運行容器時,能夠經過 -w 參數覆蓋構建時所設置的工做目錄。

4.7 ADD 指令

ADD 用於將本地文件添加到鏡像中,tar 類型文件會自動解壓(網絡壓縮資源不會被解壓),能夠訪問網絡資源,相似 wget,格式:

ADD <src>... <dest>
 # 用於支持包含空格的路徑
 ADD ["<src>",... "<dest>"]

示例:

ADD home /path/ # 支持通配符 添加全部以"home"開頭的文件 到/path/ 下

4.8 COPY 指令

COPY 的功能相似於 ADD,可是不會自動解壓文件,也不能訪問網絡資源

4.9 RUN 指令

RUN 用來執行構建鏡像時執行的命令,有如下兩種命令執行方式:

  • shell 執行格式:

RUN <command>

示例: RUN apk update

  • exec 執行格式:

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

示例: RUN ["/dev/file", "p1", "p2"]

須要注意的是: RUN 指令建立的中間鏡像會被緩存,並會在下次構建中使用。若是不想使用緩存鏡像,可在構建時指定 --no-cache 參數,示例:docker build --no-cache

4.10 CMD 指令

CMD 構建容器後執行的命令,也就是在容器啓動時才執行的命令。格式:

# 執行可執行文件,優先執行
 CMD ["executable","param1","param2"]  
 # 設置了 ENTRYPOINT,則直接調用ENTRYPOINT添加參數  參見 CMD 講解 
 CMD ["param1","param2"] 
 # 執行shell命令
 CMD command param1 param2

示例: CMD ["/usr/bin/bash","--help"]

CMD 不一樣於 RUNCMD 用於指定在容器啓動時所要執行的命令,而RUN用於指定鏡像構建時所要執行的命令。

4.11 ENTRYPOINT 指令

ENTRYPOINT 用來配置容器,使其可執行化。配合 CMD可省去 application,只使用參數。格式:

#可執行文件, 優先
 ENTRYPOINT ["executable", "param1", "param2"]  
 # shell內部命令
 ENTRYPOINT command param1 param2

示例:

FROM ubuntu

    ENTRYPOINT ["top", "-b"]

    CMD ["-c"]

ENTRYPOINTCMD 很是相似,不一樣的是經過 docker run 執行的命令不會覆蓋 ENTRYPOINT ,而 docker run 命令中指定的任何參數都會被當作參數再次傳遞給 ENTRYPOINT 指令。Dockerfile 中只有最後一個 ENTRYPOINT 命令起做用,也就是說若是你指定多個ENTRYPOINT,只執行最後的 ENTRYPOINT 指令。

4.12 EXPOSE 指令

EXPOSE 指定與外界交互的端口,格式:

EXPOSE [<port>...]

示例: EXPOSE 8080 443 EXPOSE 80EXPOSE 11431/tcp 12551/udp

EXPOSE 並不會直接讓容器的端口映射主機。宿主機訪問容器端口時,須要在 docker run 運行容器時經過 -p 來發布這些端口,或經過 -P 參數來發布EXPOSE 導出的全部端口

4.13 VOLUME 指令

VOLUME 用於指定持久化目錄, 格式:

VOLUME ["<src>",...]

示例:VOLUME ["/data"]VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]

一個卷能夠存在於一個或多個容器的指定目錄,該目錄能夠繞過聯合文件系統,並具備如下功能:

  1. 卷能夠容器間共享和重用
  2. 容器並不須要要和其它容器共享卷
  3. 修改卷後會當即生效
  4. 對卷的修改不會對鏡像產生影響
  5. 卷會一直存在,直到沒有任何容器在使用它

EXPOSE 指令相似, VOLUME 並不會掛載的宿主機,須要經過 docker run 運行容器時經過 -v 來映射到宿主機的目錄中。參見另外一個命令 docker volume create

4.14 USER 指令

USER 指定運行容器時的用戶名或 UID,後續的 RUN 也會使用指定用戶。使用 USER 指定用戶時,可使用用戶名、UIDGID,或是二者的組合。當服務不須要管理員權限時,能夠經過該命令指定運行用戶。而且能夠在以前建立所須要的用戶,格式:

USER user
USER user:group
USER uid:group
USER uid
USER user:gid
USER uid:gid

使用 USER 指定用戶後,Dockerfile 中其後的命令 RUNCMDENTRYPOINT 都將使用該用戶。你能夠經過 docker run 運行容器時,能夠經過 -u 參數來覆蓋指定用戶。

4.15 ONBUILD 指令

ONBUILD 做用是其當所構建的鏡像被用作其它鏡像的基礎鏡像,該鏡像中的 ONBUILD 中的命令就會觸發,格式:

ONBUILD [INSTRUCTION]

示例:

ONBUILD ADD . /application/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

5. 總結

今天對構建 Docker 鏡像腳本 Dockerfile 基本命令進行的詳細的總結,並加以舉例說明,相信能解決你在構建鏡像中的一些困惑。敬請多多關注微信公衆號:Felordcn ,後續將會有更多幹貨奉上。

附: Spring Boot Dockerfile

# 使用 aws 的java jdk 8
   FROM amazoncorretto:8
   # 做者等相關的元信息
   LABEL AUTHOR=Felordcn OG=felord.cn
   # 掛載卷 
   VOLUME ["/tmp","/logs"]
   # 時區
   ENV TZ=Asia/Shanghai
   # 啓用配置文件 默認爲 application.yml  
   ENV ACTIVE=defualt
   # 設置鏡像時區
   RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
   # 修改成打包後的jar文件名稱
   ADD /target/flyway-spring-boot-1.0.0.jar app.jar
   ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=${ACTIVE}","-jar","app.jar"]

關注公衆號:Felordcn 獲取更多資訊

我的博客:https://felord.cn

相關文章
相關標籤/搜索