Docker環境參數化 - Arg VS Env
Docker Variable control 我們在Docker Image的打包時,最簡單當然就是每個步驟都使用最新版本。例如Docker Base Image,大家可能選用latest tag,安裝linux package (Linux包),也可能就apt install yum 安裝最新的穩定版本。但如果我們想要更好地做測試,就要使用指定版本,方便追蹤問題。而Docker在打包和運行時,都有不同的方式讓大家定義或覆寫指定參數。 Docker build arg 我們先從打包Image開始。 例如我們需要使用一個Base image為 ubuntu,版本預設為22.04,但有需要時可以經build指令覆寫,可以這樣寫 ARG ubuntu_version=22.04 FROM ubuntu$ubuntu_version # default ubuntu_version=22.04 docker image build t test2204 . # or overwrite by buildarg docker image build t test2404 buildarg=quot;ubuntu_version=24.04quot; 雖然Dockerfile的RUN指令都是使用linux shell,但在Dockerfile中想表達條件控制(if else statment)就不太易看。在外部加入script做控制,是另一個可行的後備選擇,它更可以連image名字也進行參數化。 # in bash script, you also can if $beta == true then ubuntu_version=24.04 else ubuntu_version=22.04 fi docker image build t test$ubuntu_version buildarg ubuntu_version=$ubuntu_version Docker Container Run and Docker Compose 一般來講,Linux Container 在執行時,就等於進入Linux Shell。也就是,我們可以使用Shell中的環境變數。 我們在打包Image前,已經可以在Dockerfile中定義自己的ENV數參(也就是環境變數)。與前面的Build Arg有所不同的是,ENV是定義在Dockerfile中,在Container運行時以環境變數的形式存在,它也可以在運行中被改變。而Arg,則只在打包Image時存在,運行期間就不存在了。(當然,你在打包時,用Arg傳入Env,以運到這個目的。) 另一個更特別的性質是,那怕ENV沒有定義在Dockerfile中,我們運行時也可以加入更多的環境變數,大家就當成是一般Linux操作,隨時在自己的shell中加入變數。 # e, env for inline variable # envfile for file docker container run e MYVAR1 env MYVAR2=foo envfile .env.list ubuntu bash 同樣地Docker compose,也支援環境變數。筆者建議environment可以使用Array格式,日後可以更方便地直接改為env_file。 # dockercompose.yaml services ubuntu image ubuntu22.04 environment RACK_ENV=development SHOW=true USER_INPUT 上述的寫法沒有任何問題,不過如果你的dockercompose.yaml是放在git等版本控制中,你更新環境變數就有可能會影響到其他人,這時你就會想轉成env_file。 dockercompose.yaml預設就會讀當前資料夾的.env,就算不存在,也可以正常運行。(當然,大家的ImageContainer應該要有預設值) # dockercompose.yaml services ubuntu image ubuntu22.04 # if env_file is not defined, it will load .env. # or you can load the specific file. # env_file # .a.env env_file內,每一行就是一個變數 # .env or a.env RACK_ENV=development SHOW=true USER_INPUT 使用預設的.env還有一個好處,就是我們可以把dockercompose.yaml也變成受環境變數控制。 # dockercompose.yaml with variable control, only works in default .env services ubuntu image ubuntu$ubuntu_version # .env ubuntu_version=22.04