活用 ENV 與 ARG
ENV 與 ARG 是 Dockerfile 的指令,它們能定義變數並且在後面的流程中使用。
ENV 的設計
ENV 比較容易理解,它其實就是設定 environment,因此概念上,它會是一個全域變數--直到 docker run
的時候都還會存在的變數。
Docker 官方的底層 image,如 PHP 或 Java 等,會版本資訊、安裝路徑等設定成 ENV,在後續的流程可以拿來使用。
至於是應用層級的 image 如 Laravel image,environment 大多都會是執行時期才提供,而 Dockerfile 則可以設定預設值。至於要怎麼設定,則是看 image 最終是否有要拿到線上部署,如果有的話,建議預設 production 設定會比較好:
ENV APP_ENV=production |
而連線設定則建議不要有預設值,否則部署錯環境加上設定也錯,若網路層沒有防呆的話,將會發生錯寫資料的悲劇。
ARG 的設計
ARG 是一個很像 ENV 的指令,不一樣的點主要在於,它只能活在 build image 的過程裡。可以從下面這個例子看得出來:
FROM alpine |
build image 過程可以看到 ENV 與 ARG 有正常取值,但 docker run
的時候,則只剩下 ENV 而 ARG 不見了。這代表 ARG 只能活在 build image 階段而已。
ARG 不只是 build image 階段的變數,它可以在下指令的時候一併設值:
docker build --build-arg bar=3 . |
ARG 的使用情境在,有時候需要寫很多 Dockerfile,如:
FROM php:7.3-alpine |
FROM php:7.4-alpine |
兩個 Dockerfile 差異只在於 PHP 版本,若以這個寫法來看,若未來新增 PHP 版本,就得多一個 Dockerfile。
這個情境就很適合使用 ARG 改寫:
ARG PHP_VER |
docker build --build-arg PHP_VER=7.4 . |
這裡的 ARG 寫法是沒有預設值的,這時 ${PHP_VER}
會取到的是空值。以這個例子,FROM
指令會出現 image 名稱格式錯誤訊息(php:-alpine
):
$ docker build . |
ARG 與 ENV 混用
如果在 ARG 設值的時候使用 ENV 的值,或是反過來的話,可以正常 work 的:
FROM alpine |
可以看到 ARG 有正常取得 ENV,ENV 也有正常取得 ARG。
另一種情境是撞名:
FROM alpine |
若取一樣的名字會發現,它最後都會以 ENV 為主。雖然不會出錯,但建議還是盡可能不要撞名比較好。
與 Multi-stage build 合併使用
下面做一個簡單的實驗,在第一個 stage 設定好值後,在第二個 stage 使用:
FROM alpine |
這個實驗非常簡單,一做就馬上理解:每個 stage 要用的 ARG 與 ENV 都需要各自定義的,因此兩個 stage 可以設定兩個同名不同值的 ENV;若兩個 stage 都使用同名的 ARG,則兩個 ARG 在 --build-arg
給值的時候都拿得到。
FROM alpine |
今日自我回顧
今天一連串的實作,相信讀者能更了解 ENV 與 ARG 的差異,以及適用的情境。
使用 ENV 可以讓 Dockerfile 更好維護,而 ARG 則是可以讓同一份 Dockerfile 產生更多不一樣的 image。讀者可以視情況運用這兩個指令。