###### tags: `docker` # Dockerfile 詳細說明 - [FROM](#FROM) - [ENV](#ENV) | [ARG](#ARG) - [ADD](#ADD) | [COPY](#COPY) - [RUN](#RUN) | [CMD](#CMD) | [ENTRYPOINT](#ENTRYPOINT) - [LABEL](#LABEL) - [EXPOSE](#EXPOSE) - [WORKDIR](#WORKDIR) - [HEALTHCHECK](#HEALTHCHECK) ## 指令說明 ### FROM ```dockerfile FROM [--platform=<platform>] <image> [AS <name>] FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] FROM [--platform=<platform>] <image>[@<digest>] [AS <name>] ``` - 用來指定要引進的基礎image,會先從本地搜尋,若無則到網路上的[DockerHub](https://hub.docker.com/)找。可以用自定義的image檔。 - Ex: ```dockerfile FROM mariadb ``` 此指令就是指令指定引入mariadb當作基礎image。 ### ENV ```dockerfile ENV <key>=<value> ... ``` - 新增環境變數到該image裡。 - Ex: ```dockerfile ENV my_env=your_variable ``` ![]() <img src="https://i.imgur.com/PP0xN01.png" width="75%"/> 在裡面就可以呼叫了 ### ARG ```dockerfile ARG <name>[=<default value>] ``` - ARG在build時候是可以從外部以--build-arg帶入的變數,讓build的動作可結合外部的指令給定一些建構時候所需的參數。 - Ex: ```dockerfile ARG MY_FILE ADD ./${MY_FILE} / ``` ```shell docker build -build-arg MY_FILE=./file.txt . ``` 用-build-arg把MY_FILE這個變數帶入Dockerfile裡來使用 - ARG不能在CMD或ENTRYPOINT裡使用。 >在ENV與ARG參數的設定上,可以透過下面方式增加一些變化... > - ${variable:-word} 代表,如果variable有給值,則以variable設定的文字為主,如未設定,則以word字串為主。 > - ${variable:+word} 代表,如果variable有給值,則值為word;如果variable未給值,則最後結果為空字串(empty)。 ### ADD ```dockerfile ADD [--chown=<user>:<group>] [--checksum=<checksum>] <src>... <dest> ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] ``` - src: 不限於本地路徑,可以用網址之類的。 - Ex: ```dockerfile ADD http://example.com/font.js /opt/ ADD my_big_lib.tar.gz /var/lib/myapp ``` 第1行示範從遠端下載檔案到/opt/,第2行則示範使用ADD傳送tar檔會自動解壓縮到目的地(僅限於tar檔)。 ### COPY ```dockerfile COPY [--chown=<user>:<group>] <src>... <dest> COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] ``` - COPY與ADD類似,但COPY只支援本地路徑 - Ex: ```dockerfile COPY ./file.txt /home/user/folder ``` 上面範例則是將本地路徑的file.txt複製到image的/home/user/folder ### RUN ```dockerfile RUN [command,param1,param2,...] RUN command param1, param2 ... ``` - 支援shell格式或exec格式 - 每次執行RUN都會多建立一層layer,所以盡量減少執行RUN的次數以增加效能。Ex: ```dockerfile RUN ["apt-get", "update"] RUN ["apt-get", "-y", "install", "cron"] RUN crontab -l | { cat; echo "0 4 * * * ${JAVA_EXE} -jar ${CRON_FILE} >> ${CRON_PATH}/cronlog.log";} | crontab - ``` 下面的寫法相對上面還要好 ```dockerfile RUN apt-get update \ && apt-get -y install cron \ && crontab -l | { cat; echo "0 4 * * * ${JAVA_EXE} -jar ${CRON_FILE} >> ${CRON_PATH}/cronlog.log";} | crontab - ``` > COPY ,ADD ,RUN三者在執行時皆會多產生一層layer,layer越多效能就越差,所以能越少越好。 ### CMD ```dockerfile CMD ["command", "param1", "param2"] #exec form CMD command param1 param2 #shell form CMD ["param1","param2"] ``` - CMD 主要用途是為執行容器(container)時提供預設值,預設值可以是一個可執行檔(executable)以及其需要的參數;也可以只是單純提供參數的部分,不過這種用法一定要搭配 ENTRYPOINT 使用,也就是 CMD 只是作為 ENTRYPOINT 所需的預設參數。 - exex form:使用exec來執行 - Ex:`CMD ["/usr/bin/wc","--help"]`實際上會長這樣`exec /usr/bin/wc --help` > <p style="color: red; font-weight:bold">exec 會替代當前shell並重新啟動一個shell,所以無法使用現有的環境變數</p> - shell form: 使用`/bin/sh -c`來執行 - Ex: `CMD echo "This is a test." | wc -`實際上會長這樣`/bin/sh -c echo "This is a test." | wc -` ### ENTRYPOINT ```dockerfile ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2 ``` - exec form與shell form需要注意的點和CMD一樣。 ### LABEL ```dockerfile LABEL <key>=<value> <key>=<value> <key>=<value> ... ``` - 用於記載作者、版本之類的metadata。 ### EXPOSE ```dockerfile EXPOSE <port> [<port>/<protocol>...] ``` - EXPOSE 指令通知 Docker container在運行時監聽指定的port。可以指定port監聽TCP還是UDP,不指定則預設為TCP。 - 此指令僅僅聲明要使用的port,並不會自動將port映射出來。 ### WORKDIR ```dockerfile WORKDIR /path/to/workdir ``` - WORKDIR 指令為 跟在它後面的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令指定當前工作目錄。如果 WORKDIR不存在,即使它沒有在任何後續的指令中使用,也會被建立。 ### HEALTHCHECK ```dockerfile HEALTHCHECK [OPTIONS] CMD command ``` - healthCheck用於檢查container是否運行中。 - option: ```dockerfile --interval=DURATION (default: 30s) --timeout=DURATION (default: 30s) --start-period=DURATION (default: 0s) --retries=N (default: 3) ``` - healthCheck會先檢查然後等interval時間後再次檢查,若單次檢查時間超過timeout時間,則該次檢查視為失敗。 - 當累積失敗次數達retries次時,則回傳unhealthy並關閉container。 - Ex: ```dockerfile HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1 ``` ## 參考文獻 [Dockerfile reference](https://docs.docker.com/engine/reference/builder/) [《Docker —— 從入門到實踐­》正體中文版](https://philipzheng.gitbook.io/docker_practice) [linux exec用法總結](https://www.796t.com/p/1390349.html)