AboutDockerProfessional illustrations
Dockerfile ENV指令詳解2026
好啦,各位開發者,今次我哋就深入淺出噉講下 Dockerfile ENV指令 喺2026年嘅應用同細節。你可能會諗,ENV指令咪就係設定環境變量咁簡單,有乜好詳解?但係喺實際鏡像構建同容器運行嘅過程中,點樣用好ENV,直接影響到你個鏡像嘅大小、安全性、同配置靈活性,當中使用嘅技巧同陷阱都唔少。
首先,我哋要搞清楚 ENV指令 最基本嘅作用。佢就係喺Docker 鏡像嘅構建階段,設定一啲持久嘅環境變量。呢啲變量唔單止喺 docker build 嘅時候可以用到,更重要係當你個鏡像變成一個運行緊嘅容器實例時,呢啲變量都會存在。呢個係佢同 ARG指令(構建參數)最大嘅分別。ARG只係喺構建階段有效,完成構建後就會消失,而ENV就會一直跟住個鏡像。舉個實用例子,假如你整一個 Node.js 應用嘅鏡像,你好可能會用 ENV NODE_ENV=production 去設定運行環境,咁樣你嘅應用喺容器入面就會知道用生產模式嘅配置。
咁點樣用先至叫用得精明呢?一個好關鍵嘅概念係層同緩存。Dockerfile 入面每一行指令都會為鏡像增加一個新嘅層。如果你喺Dockerfile好早期就用ENV設定咗一堆變量,之後嘅指令(例如RUN去安裝套件)如果因為呢啲變量嘅改變而失效,就會導致Docker嘅構建緩存被打破,要重新構建之後所有層,浪費時間同頻寬。所以,一般最佳實踐係將環境變量嘅設定,擺喺Dockerfile比較後嘅位置,尤其係喺複製應用程式碼之前。除非某個ENV係前面RUN指令所必需嘅,例如要設定一個路徑比安裝腳本用。
另外,ENV指令仲有一個好常用嘅功能,就係擴展PATH設置。例如你安裝咗一個軟件去一個非標準目錄,你可以用 ENV PATH=/usr/local/xyz/bin:$PATH 將佢加入PATH。咁樣之後喺容器入面,你就可以直接喺命令行打該軟件嘅名嚟執行。不過要留意,每用一次ENV去改PATH,都會產生一個新嘅層。2026年嘅 Docker 引擎 同 BuildKit 喺緩存處理上已經好聰明,但保持指令簡潔清晰依然係好習慣。
講到變量引用,ENV指令好支援用 $VARIABLE_NAME 或者 ${VARIABLE_NAME} 嘅格式去引用其他已經定義咗嘅環境變量。呢個特性可以令你嘅Dockerfile更有彈性。例如,你可以先定義一個基礎版本,再喺後面引用佢:ENV APP_VERSION=1.2.3 跟住 ENV APP_PACKAGE=myapp-$APP_VERSION.tar.gz。呢種配置管理方式,令維護同更新變得容易。不過要小心,呢種引用通常喺同一個構建階段內有效,如果你玩多階段構建,就要留意變量嘅作用域範圍。
同 ARG 指令嘅配合亦係一大重點。ARG係從外面傳入嚟嘅構建參數,你可以用 --build-arg 參數喺 docker build 嗰陣傳入。一個常見模式係,用ARG去接收一啲敏感或者會經常變動嘅值(例如版本號、下載URL),然後喺Dockerfile入面,將呢個ARG值賦值俾一個ENV變量。例如 ARG CODE_VERSION=latest 跟住 ENV APP_VERSION=${CODE_VERSION}。咁樣做,外面傳入嘅參數就可以「固化」到最終嘅鏡像環境變量入面。但切記,千祈唔好用ARG去傳密碼之類嘅敏感資料然後存入ENV,因為佢哋會留喺鏡像層歷史度,好易被睇到。2026年大家更傾向用Docker Secret或者運行時先注入嘅方式處理秘密資料。
最後提下一啲實際應用同常見錯誤。例如,好多人會用ENV去設定啲好似 DEBIAN_FRONTEND=noninteractive 呢類變量,令到喺用 alpine 或者Ubuntu等基礎鏡像安裝軟件時,唔會出現互動提示卡住個構建過程。又或者,設定 LANG=C.UTF-8 等區域設定,避免容器入面出現亂碼。至於錯誤方面,有時你會見到啲人將成個應用嘅配置文件內容,用一個好長嘅ENV指令設定成一個環境變量,咁樣會令Dockerfile難讀兼難維護,不如直接將配置文件COPY入鏡像更合適。另外,如果喺運行時見到類似 Error 401, Unauthorized 呢類問題,好多時都係因為容器入面嘅應用讀取唔到正確嘅環境變量(例如API Token冇設定)所導致,而唔係Dockerfile本身嘅語法錯誤。
總括嚟講,精通 ENV指令 並唔係死記語法,而係要理解佢點樣影響鏡像構建嘅緩存機制、層次文件系統,以及點樣同 ARG 同其他指令協作,去打造出更高效、更安全、更易於管理嘅 容器化 應用。希望以上嘅詳解同例子,可以幫你喺2026年嘅開發工作中,更得心應手噉運用呢個基礎但強大嘅工具。
AboutDockerfileProfessional illustrations
環境變量設定最佳實踐
好啦,講到喺 Dockerfile 入面設定 環境變量,唔少朋友可能覺得好簡單,咪就係用 ENV指令 囉!但係點樣設定先至係最穩陣、最有效率,又唔會整大個 鏡像 或者洩漏敏感資料呢?呢度就有好多學問喇。首先,最基本嘅原則就係要分清楚 構建時 同 運行時 需要嘅變數。如果你嘅變數只係喺 鏡像構建 過程度需要,例如要裝某個特定版本嘅套件,咁就應該用 ARG 而唔係 ENV。因為 ARG 係 構建參數,佢嘅值只會喺 docker build 嗰陣存在,唔會留喺最終嘅 容器 入面,咁樣可以減少 鏡像 入面不必要嘅資訊,亦都安全啲。你可以用 --build-arg 嚟傳值入去。相反,ENV 設定嘅變數就會成為 容器 運行環境嘅一部分,應用程式(例如 Node.js)喺運行時可以直接讀取到。
跟住落嚟,我哋要講下點樣善用 緩存 機制。Docker 引擎 嘅構建過程係分 層 嘅,每一行指令都會產生一個新 層。如果你成日改動 ENV 指令,尤其係擺喺 Dockerfile 好前嘅位置,就好容易令到後面嘅 構建 步驟 緩存 失效,每次都要重新行過,拖慢構建速度。所以,一個好嘅實踐係將成日會變嘅 環境變量(例如版本號)擺去檔案嘅後半部分,而將唔會點變嘅設定(例如 PATH設置)擺喺前面。例如,你裝完 alpine 之後,就好快設定好個 PATH 或者語言環境,咁之後即使你更新應用程式版本,前面嘅 層 都仲可以用返 緩存,慳返唔少時間。
另外,敏感資料嘅處理絕對係重中之重!千祈唔好將密碼、API金鑰呢類敏感資料直接用 ENV指令 寫死喺 Dockerfile 入面,因為咁樣會永久留喺 鏡像 嘅某一 層,好容易被挖返出嚟。就算你之後刪除嗰行指令都冇用,因為舊 層 依然存在。比較好嘅做法係喺運行時先至注入,例如用 docker run -e 或者用 容器 編排工具嘅 secrets 管理功能。咁樣,環境變量 就只會存在於運行中嘅 容器實例 嘅記憶體度,安全好多。如果你喺 構建階段 真係需要用到敏感資料(例如要從私人倉庫拉取套件),可以用 BuildKit 嘅秘密掛載功能,或者用 ARG 傳入,但要確保唔會用 ENV 將佢轉存落去。
仲有,環境變量 嘅組織同埋引用都係一門藝術。如果你有成堆相關嘅變數,可以考慮用一個 ENV指令 嚟設定多個,減少 層 嘅數量。同時,要識得利用 變量引用 嚟簡化設定,例如設定一個基礎路徑,然後其他變數基於呢個路徑去組合。不過要留意,Dockerfile 入面嘅 變量引用 語法(用 $variable 或者 ${variable})同埋作用範圍,ARG 同 ENV 之間嘅引用規則係有分別嘅,唔好搞亂。
最後不得不提嘅就係 多階段構建 呢個神器。喺複雜嘅 鏡像構建 過程度,你可能喺第一個階段需要用 環境變量 去編譯程式碼,但係你唔想將編譯時用到嘅所有工具同埋變數都帶入最終嘅生產 鏡像。咁點算?用 多階段構建 就啱晒。你可以喺第一個階段用 ARG 同 ENV 點用都得,完成編譯後,只將編譯好嘅成品(例如一個二進制檔)複製到第二個乾淨嘅階段。咁樣,最終嘅 鏡像 就會又細又乾淨,入面只包含運行必要嘅 環境變量,完全唔會有多餘嘅構建資訊,對於安全同 容器化 部署嘅效率都有極大幫助。總括嚟講,設定 環境變量 唔係求其打句指令就算,要諗清楚佢嘅生命周期、對 緩存 嘅影響、安全性,同埋點樣配合 構建階段 嚟達到最佳嘅 配置管理 效果。
AboutENVProfessional illustrations
ARG與ENV指令分別點用
好,等我哋深入拆解下 Dockerfile 裡面 ARG 同 ENV 呢兩個指令究竟點用,同埋喺唔同情境下點樣揀。好多初學 Docker 嘅朋友成日搞亂佢哋,其實最核心嘅分別就係:ARG 係 build-time(構建階段)用嘅變數,而 ENV 就係 run-time(容器運行時)用嘅環境變量。呢個分別直接影響到你個鏡像點樣構建、點樣配置,同埋點樣傳遞參數。
首先講 ARG 指令。佢嘅全名係 build argument,顧名思義,佢只係喺你用 docker build 命令構建鏡像嗰陣先存在同有效。你可以當佢係一個臨時嘅、為咗構建過程而設嘅參數。點樣用呢?你可以在 Dockerfile 裡面用 ARG 變數名[=預設值] 來定義,然後喺執行 docker build 嗰陣,透過 --build-arg 變數名=值 嚟從外面傳入唔同嘅值。呢個功能對於要構建唔同版本、或者需要根據情況調整構建參數嘅時候好有用。例如,你想構建一個 Node.js 應用嘅鏡像,但係唔想將版本號寫死喺 Dockerfile,你就可以咁樣做:喺 Dockerfile 寫 ARG NODE_VERSION=18,然後喺安裝時引用 $NODE_VERSION。當你想試下用 Node.js 20 嚟構建,只需要喺 build 命令加 --build-arg NODE_VERSION=20 就得,唔使改 Dockerfile 本身。不過要記住,呢個 NODE_VERSION 變數只會喺構建過程(例如 RUN 指令執行 apt-get install 或者 npm install 時)先用到,一旦鏡像構建完成,佢就會消失,唔會留喺最終嘅容器實例裡面。另外,ARG 仲有一個常見用途,就係配合多階段構建(multi-stage build)嚟用,喺唔同嘅構建階段傳遞參數,令到構建過程更加靈活同高效,特別係用 BuildKit 做構建引擎時,緩存機制會更聰明。
跟住到我哋成日見嘅 ENV 指令。ENV 就係設定環境變量,佢唔單止喺構建階段(build-time)有效,更重要嘅係,佢會持久化到構建出嚟嘅鏡像裡面,並且喺你之後用 docker run 啟動容器時繼續存在。呢個就係同 ARG 最大嘅分別!ENV 設定嘅變數,會成為容器運行環境嘅一部分。點樣用呢?語法係 ENV 變數名=值 或者 ENV 變數名 值。例如,你好常見會設定 ENV NODE_ENV=production,咁樣當你個 Node.js 應用喺容器裡面運行時,就會讀取到呢個環境變量,知道而家係生產模式。另一個經典例子就係 PATH設置,例如 ENV PATH=/usr/local/app/bin:$PATH,將你應用嘅執行路徑加入系統 PATH,咁你就可以直接喺命令行打應用名嚟執行。因為 ENV 會留喺鏡像入面,所以佢係做容器配置管理嘅重要工具。你喺 Dockerfile 用 ENV 設定好嘅變數,之後喺運行容器時,可以用 docker run -e "變數名=新值" 嚟覆蓋佢,呢個就係好常見嘅動態配置方法。例如,你個應用要連數據庫,個連接地址唔應該寫死喺鏡像,就可以喺 Dockerfile 設一個預設值 ENV DB_HOST=localhost,然後實際運行時先透過 -e DB_HOST=mysql.prod.svc 嚟注入真正嘅地址。
咁 ARG 同 ENV 有冇交集呢?有嘅!佢哋可以一齊用,而且呢個技巧好實用。你可以用 ARG 嚟設定一個構建時嘅參數,然後將佢嘅值賦予一個 ENV 變數。咁樣做嘅好處係,你可以從構建命令控制最終鏡像裡面嘅環境變量預設值。舉個例,你想個鏡像預設用某個版本嘅 Alpine 做基礎,但係又想可以隨時改,你可以咁寫:ARG ALPINE_VERSION=3.18 ENV BASE_IMAGE_VERSION=$ALPINE_VERSION。咁樣,你構建時傳入唔同嘅 --build-arg,就會影響到最終鏡像入面 BASE_IMAGE_VERSION 呢個環境變量嘅預設值。不過要留意,如果你之後用 docker run -e 去改 BASE_IMAGE_VERSION,係會覆蓋到呢個由 ARG 傳入嘅預設值嘅。
最後,俾啲實用建議同分析。點樣揀用 ARG 定 ENV 呢?記住以下幾個原則:第一,如果個變數只係用嚟控制點樣安裝軟件、下載邊個版本嘅檔案、或者影響鏡像層(layer)嘅構建過程,例如係 apt-get update 嘅鏡像源地址、或者係下載某個軟件包嘅 URL,咁就用 ARG。因為佢唔應該洩漏到運行時環境。第二,如果個變數係你個應用程式運行時需要讀取嘅配置,例如係數據庫連接字串、API金鑰(當然敏感資料唔應該直接寫喺 Dockerfile,而係用 -e 注入)、運行模式(development/production)、或者係服務端口,咁就一定要用 ENV。第三,要善用 多階段構建 同 BuildKit 嘅緩存優勢。ARG 嘅值如果改變,會令到所有用到呢個 ARG 值嘅 Dockerfile 指令之後嘅緩存層失效。所以,要將 ARG 指令擺得越後越好,或者將佢哋集中喺 Dockerfile 嘅頂部,但係就喺需要用到佢哋嘅 RUN 指令之前先重新定義一次,以減少不必要嘅緩存失效。第四,對於敏感資料,千祈唔好直接用 ARG 或 ENV 寫死喺 Dockerfile 入面,因為 ARG 嘅值喺構建歷史度可能會睇到。應該用 --build-arg 傳入,並且喺運行時用 docker run -e 或者 Docker Secrets 呢類方法嚟處理。
總括嚟講,理解清楚 ARG(構建參數)同 ENV(環境變量)嘅生命週期同影響範圍,係寫出高效、安全、易於配置嘅 Dockerfile 嘅關鍵。搞清佢哋,你就能夠更好咁控制你嘅鏡像構建流程同容器化應用嘅配置管理,避免出現一啲令人頭痛嘅問題,例如係構建出嚟嘅鏡像冇咗預期嘅配置,或者係敏感資料意外洩漏。
About容器Professional illustrations
Build-time變數設定技巧
好啦,而家我哋就深入講下 Build-time 變數設定嘅技巧,即係點樣喺用 docker build 構建鏡像嗰陣,靈活咁傳入參數。呢個技巧對於管理唔同環境(例如開發、測試、生產)嘅配置,或者避免將敏感資料寫死喺 Dockerfile 入面,真係好重要。最核心嘅工具就係 ARG 指令同 --build-arg 參數,佢哋係專門用喺構建階段嘅變數,同用嚟畀運行時容器用嘅 ENV 指令有好大分別。簡單嚟講,ARG 係「起樓時嘅藍圖參數」,而 ENV 係「入伙後屋企嘅固定擺設」。
點解要分得咁清楚?第一,係為咗安全。如果你有啲好似 API Key、暫時性嘅存取令牌呢類敏感資料,只係構建過程需要(例如從私人倉庫 Clone 一啲 Code),你就可以用 ARG 傳入,完成構建後,佢唔會留低喺最終嘅鏡像層入面,減少洩漏風險。相反,如果你唔小心用 ENV 設定咗呢啲敏感資料,佢就會永遠寫入鏡像歷史,被人用 docker history 或者入到容器就好易睇到。第二,係為咗靈活性同緩存。你可以用 ARG 嚟動態決定構建邊個版本嘅軟件,例如 ARG NODE_VERSION=18,咁樣唔使改 Dockerfile 就可以構建唔同版本嘅 Node.js 鏡像。而且,ARG 值嘅改變會令 Docker 嘅緩存失效,呢個特性可以用嚟強制更新某個構建步驟,例如喺 RUN apt-get update 之前加個 ARG CACHE_BUST=1,咁每次構建傳唔同值就可以繞過緩存,確保套件列表係最新。
實際點用呢?好簡單,喺你嘅 Dockerfile 入面,你可以用 ARG 指令去宣告一個變數,甚至可以畀個預設值。例如 ARG USER_NAME="default_user"。到真正構建嗰陣,你就要喺命令度用 --build-arg 嚟覆寫佢,好似 docker build --build-arg USER_NAME=alice -t myapp . 咁樣。呢個 USER_NAME 變數就可以喺佢之後嘅指令度用 $USER_NAME 或者 ${USER_NAME} 嘅形式嚟引用。不過要記住,ARG 嘅作用範圍只限於「宣告之後」到「一個構建階段結束」為止。如果你個 Dockerfile 用緊多階段構建,咁每個階段都要重新宣告一次 ARG 先可以用到,呢個設計可以令每個階段更加獨立。
另外一個實用技巧,就係點樣將 ARG 嘅值傳遞去 ENV。有時你構建時需要某個變數(例如軟件版本號),但係運行時個容器實例都需要用到同一個值。最直接嘅方法就係喺 ENV 指令度引用個 ARG 變數。例如: ARG APP_VERSION ENV APP_VERSION=$APP_VERSION 咁樣做,個 APP_VERSION 就會由構建參數,變成容器入面一個持久嘅環境變量。不過要留意,呢個 ENV 值就會被固化落鏡像層度。如果你用緊 BuildKit 呢個更先進嘅構建引擎(2026年基本上係標準啦),你可以用佢嘅構建階段特性做更精細嘅控制,減少最終鏡像嘅大小同資訊暴露。
最後提幾個常見嘅「伏位」。首先,唔好混淆 ARG 同 ENV。如果你喺 RUN 指令入面想用 ARG,一定要確保 ARG 已經喺前面宣告咗。第二,傳入 --build-arg 時,如果個值有空格或者特殊字符,記得要用引號包住。第三,如果你傳入一個 Dockerfile 入面無宣告嘅 --build-arg,構建過程會出警告,但唔會失敗,不過就無意思啦。第四,關於 PATH設置 呢類常用環境變量,我哋通常直接用 ENV 設定,好少用 ARG 去動態改,因為 PATH 係運行時關鍵配置。掌握好呢啲 Build-time變數設定技巧,你嘅 Dockerfile 就會更加安全、有彈性,亦都更符合現代容器化應用嘅配置管理最佳實踐。
About環境變量Professional illustrations
Run-time環境變數配置
講到Run-time環境變數配置,呢個真係Docker實戰入面好關鍵嘅一環,同構建時用ARG或者ENV設定死嘅變數好唔同。簡單啲講,Run-time變數係指個容器實際運行嗰陣先注入嘅設定,就好似你喺唔同環境(開發、測試、生產)行同一個Docker鏡像,但係可以俾唔同嘅資料庫連接字串或者API金鑰佢,唔使為每個環境重新構建過個鏡像,超級方便。呢個做法係現代配置管理嘅核心思想,將配置同程式碼分離,令到你個容器化應用更加靈活同安全。
點樣喺Run-time設定呢啲環境變量呢?最直接嘅方法就係用 docker run 指令嘅 -e 旗標。例如你有一個Node.js應用,需要一個叫 API_KEY 嘅變數,你就可以噉樣運行個容器:docker run -e API_KEY=your_secret_key_here my-node-app。咁樣,個容器入面嘅Node.js程式就可以透過 process.env.API_KEY 攞到呢個值。如果你有成堆變數要設定,逐個 -e 會好麻煩,你可以將所有變數放喺一個 .env 檔案入面,然後用 --env-file 參數一次過載入,例如 docker run --env-file .env.production my-app。呢個方法喺部署上好常見,可以確保敏感資料唔會寫死喺 Dockerfile 或者 鏡像 入面,減低洩露風險。
不過,有冇諗過點解我哋要特登區分 build-time 同 run-time 呢?呢度就涉及 Docker 引擎 同 鏡像構建 嘅層次概念。喺 Dockerfile 入面用 ENV指令 設定嘅變數,會成為鏡像嘅一個永久層。佢有兩個作用:第一,喺構建階段,佢可以俾其他指令使用,例如設定 PATH設置 或者俾 RUN 指令用;第二,佢會成為該鏡像衍生出嚟所有容器實例嘅默認環境變數。但問題就喺度,如果個密碼用ENV寫死喺Dockerfile,咁任何拎到呢個鏡像嘅人都會見到,極度唔安全。所以,最佳實踐係:構建階段需要嘅變數(例如版本號、下載URL)可以用 ARG 配合 --build-arg 傳入,或者用ENV設定一啲非敏感嘅默認值;而運行階段需要嘅、尤其係敏感或者會因環境而異嘅配置,就一定要用 -e 或者 --env-file 喺Run-time先注入。
舉個實用例子,假設你用緊 多階段構建 來整一個好細嘅 alpine 基礎鏡像應用。喺構建階段,你可能需要用 ARG 來傳入一個NPM registry嘅鏡像地址,加快構建速度。但係,當個應用行起嚟,佢需要連接一個外部API,個API endpoint同認證token就應該喺Run-time先設定。如果你唔小心將API endpoint用ENV寫死喺Dockerfile,咁你想將個應用由測試環境搬去生產環境,就要重新構建鏡像,唔單止麻煩,仲會破壞咗「一次構建,隨處運行」嘅容器本意。另外,Run-time變數仲可以覆蓋喺Dockerfile入面用ENV設定嘅默認值,俾你一個退路。
仲有一點好重要,就係點樣喺你嘅應用程式碼入面變量引用呢啲Run-time環境變數。以Node.js為例,你應該養成習慣,用 process.env.VAR_NAME 嘅方式去讀取,而唔好喺程式碼中間寫死任何配置值。同時,要考慮埋變數唔存在嘅情況,提供合理嘅默認值或者立即報錯(例如 Error 401, Unauthorized 呢類錯誤,好多時就係因為冇設定好正確嘅認證環境變數而導致)。呢種做法可以令你嘅應用更容易適應唔同嘅容器實例環境。
最後提提你,隨著 BuildKit 成為默認嘅構建引擎,構建過程變得更智能,緩存 機制亦更完善。但係,Run-time配置同構建緩存冇直接關係,因為佢根本唔參與構建過程。不過,如果你錯誤地將應該喺Run-time設定嘅變數改用ARG或ENV喺構建時寫死,就可能會導致構建層嘅內容因配置唔同而改變,從而破壞緩存,令每次構建都要重新執行某啲步驟,拖慢開發同部署流程。所以,清晰區分構建時同運行時嘅變數,唔單止關乎安全同靈活性,仲會影響到你嘅開發效率同鏡像構建速度。記住,將變化嘅部分留到最後一刻(即係容器運行嗰刻)先決定,呢個就係容器化配置管理嘅精髓所在。
About鏡像Professional illustrations
多階段構建ENV設定
講到多階段構建ENV設定,呢個技巧對於優化Docker鏡像嚟講真係好緊要。好多香港嘅開發者初初用Dockerfile,可能就係喺最頂部用一條ENV指令,設定晒所有環境變量,然後就一路用到底。但係當你開始玩多階段構建(Multi-stage Build)嘅時候,就會發現ENV嘅設定要跟住唔同嘅構建階段(Build Stage)去管理,唔可以一本通書睇到老。點解呢?因為多階段構建嘅本意就係要整出一個又細又安全嘅最終鏡像,如果你將所有開發階段用嘅環境變量(例如Node.js嘅NODE_ENV=development)唔小心留低喺最終生產鏡像度,唔單止會令到個鏡像無謂咁大咗,仲可能會洩露一啲構建參數或者內部路徑,搞出類似Error 401 Unauthorized呢類安全隱患都唔出奇。
所以,喺每個構建階段裏面點樣設定同管理ENV,就成為咗一門學問。首先你要明白,ENV指令設定嘅環境變量,佢嘅生命周期係跟住個構建階段嘅。即係話,你喺第一個FROM alpine(或者其它基礎鏡像)之後設定嘅ENV,只會存在於嗰個階段裏面。當你用第二個FROM指令去開始一個新階段嘅時候,之前嗰個階段嘅環境係會被清空嘅,唔會自動帶過去。呢個設計其實好合理,因為每個階段嘅任務都唔同,例如第一階段可能係用嚟安裝依賴同構建應用(build-time),需要一大堆開發工具同變量;而第二階段就只係拎走第一階段構建好嘅成品,然後用一個好乾淨嘅環境去運行佢。如果你有啲環境變量(例如係應用運行時需要嘅配置,好似資料庫連接字串)係想帶入最終容器實例嘅,你就必須喺最終運行嘅階段裏面,再用ENV指令設定一次。
咁樣做有咩好處呢?第一,當然係安全。你可以好清晰咁控制邊啲變量只係構建過程需要,邊啲係運行時必須。例如,你喺構建階段可能會用ARG同--build-arg去傳入一啲敏感嘅令牌(Token)去Clone私人GitBook倉庫,呢啲ARG喺構建完成後就唔應該存在於最終鏡像度。第二,就係可以善用Docker嘅構建緩存(Cache)。Docker引擎嘅構建緩存係基於指令同層(Layer)嘅,如果你喺早期階段就設定咗一啲成日會變嘅環境變量(例如係版本號),咁就可能會令到後面嘅緩存層失效,拖慢構建速度。透過多階段構建,你可以將穩定嘅設定放喺前面,將經常變動嘅ENV設定放喺後面合適嘅階段,從而提升緩存嘅利用率。
舉個具體例子,假設你係用Node.js寫應用。你嘅Dockerfile可能會有兩個階段:第一階段用node:alpine呢類大鏡像去安裝npm套件同執行build;第二階段就用番個淨alpine,然後只係從第一階段抄走dist目錄同安裝運行時必要嘅項目。喺第一階段裏面,你應該設定ENV NODE_ENV=production(注意:即使係構建階段,設定NODE_ENV=production都可以令npm只安裝生產依賴,唔裝devDependencies,令個中間鏡像細啲)。同時,你可能會用ARG去傳入一啲構建時嘅版本號。而喺第二階段,即係最終運行嘅alpine鏡像裏面,你需要重新設定應用運行所需嘅環境變量,例如係PORT、DATABASE_URL呢啲。呢度要特別小心PATH設置,如果你從第一階段COPY咗一啲自定義嘅二進制文件過嚟,你可能需要喺第二階段用ENV指令去更新PATH變量,等系統可以搵到呢啲可執行文件。
另外,用開BuildKit嘅朋友更要留意,因為BuildKit提供咗更先進嘅緩存同並行構建能力。喺多階段構建入面,你可以利用佢嘅特性,將一啲純粹用於構建、但唔需要留喺最終鏡像嘅工具同變量,完全隔離喺一個獨立階段,然後用--mount=type=cache呢類方法去管理緩存,咁樣ENV嘅管理就可以更加精細。總而言之,多階段構建入面嘅ENV設定,核心思想就係「按需分配,階段隔離」。將配置管理(Configuration Management)嘅思維帶入Dockerfile寫作,唔好將所有變量堆埋一齊,而係根據每個構建階段嘅具體任務,去決定要設定咩環境變量,同埋佢哋嘅值應該係咩。咁樣先至可以砌出一個又細、又快、又安全嘅Docker鏡像,避免出現Page Not Found或者因為環境配置唔啱而引發嘅各種Legacy錯誤。
AboutGitBookProfessional illustrations
.env檔案點樣配合使用
好啦,講到 .env檔案點樣配合使用,呢個真係好多初學 Docker 嘅朋友會混淆嘅地方。首先要搞清楚,Dockerfile 入面嘅 ENV指令,同我哋平時喺項目根目錄放嗰個 .env 檔案,係兩樣嘢嚟,雖然佢哋都係處理 環境變量,但作用嘅階段同對象完全唔同。簡單啲講,Dockerfile ENV 係用嚟設定將來喺 容器 入面運行時嘅環境變量,而喺 docker build 過程中使用嘅 .env 檔案,主要係同 --build-arg 參數一齊用,或者俾 docker-compose 用嘅。呢個概念好重要,唔好搞亂。
咁我哋點樣喺構建 鏡像 嘅時候,用到 .env 檔案呢?最常見嘅做法係用嚟傳遞 構建參數。你知道啦,寫 Dockerfile 嘅時候,我哋可以用 ARG 指令嚟定義一啲只喺 構建階段 有效嘅變量。例如,我哋想指定某個軟件版本,又唔想將版本號寫死喺 Dockerfile 入面,就可以用 ARG。當我哋執行 docker build 命令時,就可以透過 --build-arg 將個值傳入去。但係,如果參數好多,逐個喺命令行寫就好麻煩,亦容易出錯。呢個時候,一個 .env 檔案就幫到手。你可以將所有需要嘅 構建參數 寫喺一個叫 .env 嘅檔案入面,格式就係 KEY=VALUE,一行一個。然後喺 build 嘅時候,加個參數 --env-file .env,Docker 引擎(特別係用緊 BuildKit 嘅話)就會自動讀取呢個檔案,並將入面嘅變量作為 構建參數 嚟用。不過要留意,呢個用法需要配合 BuildKit,而且 .env 檔案入面嘅變量名,要同你 Dockerfile 裏面用 ARG 定義嘅變量名對應返。呢種做法對於 配置管理 好有幫助,尤其係喺 CI/CD 管道入面,可以好方便咁切換唔同環境嘅構建配置。
另外一個大頭,就係 .env 檔案同 docker-compose.yml 嘅配合,呢個可能仲加常見。當你編寫一個 docker-compose.yml 檔案去定義同運行多個 容器實例 時,好多時服務嘅配置(例如數據庫密碼、API金鑰)都會用環境變量嚟設定。為咗唔好將敏感資料寫死喺 YAML 文件入面,你可以將呢啲變量全部放喺 .env 檔案。Docker Compose 會自動喺你運行 docker-compose up 嘅目錄入面,尋找一個叫 .env 嘅檔案,並將裏面嘅變量加載到 Compose 文件嘅環境中。咁樣,你喺 docker-compose.yml 裏面就可以用 ${VARIABLE_NAME} 嘅語法去引用呢啲值。呢個方法唔單止安全,而且好靈活。例如,你開發環境同生產環境用唔同嘅數據庫,你只需要準備兩個唔同嘅 .env 檔案(例如 .env.dev 同 .env.prod),然後喺啟動嘅時候指定用邊個檔案就得啦,完全唔使改動 docker-compose.yml 本身。呢種將配置同代碼分離嘅做法,係現代 容器化 應用嘅最佳實踐。
不過,有幾點陷阱一定要小心。第一,千萬唔好將 .env 檔案 commit 去 Git!呢個檔案好大機會包含密碼、私鑰呢啲敏感資訊,一定要將佢加入 .gitignore。你可以提交一個 .env.example 檔案,裏面只係列出需要嘅變量名,但係值就留空或者用假值,等團隊其他成員知道需要配置啲咩。第二,喺 Dockerfile 入面,如果你用 ENV指令 設定咗一個變量,佢會成為 鏡像 嘅一層,並且會一直存在於最終嘅 容器 入面。所以,如果係敏感資料,絕對唔應該用 Dockerfile 嘅 ENV 去設定,而應該喺運行時(透過 docker run -e 或者 Compose 嘅 .env)先注入。第三,關於 PATH設置 或者其他系統級別嘅環境變量,通常都係喺基礎 鏡像(例如 alpine 或者官方 Node.js 鏡像)裏面已經設定好,除非你好清楚自己做緊咩,否則唔好隨便覆寫佢,以免導致容器內嘅命令搵唔到。
最後,講一個進階啲嘅技巧,就係喺 多階段構建 裏面點樣善用環境變量。喺一個多階段嘅 Dockerfile 裏面,每個 構建階段 都可以有自己嘅 ARG 同 ENV。你可以喺第一個階段用 ARG 讀取構建時嘅參數,然後將佢轉化成 ENV 或者直接使用。但係,呢啲變量唔會自動帶去下一個構建階段。如果你想將某個值(例如一個由 構建參數 計算出嚟嘅版本號)傳遞俾後續階段使用,你可能需要將佢定義為 ENV,或者用 --build-arg 喺每個階段重新傳遞。呢個過程需要好好規劃,否則好容易出現啲變量值唔見咗,或者用咗 Legacy 方式導致 緩存 失效嘅問題。理解清楚每條指令生效嘅時間點(build-time 定係 run-time),同埋佢影響嘅範圍(係影響一層定係整個最終鏡像),對於寫出一個高效、安全嘅 Dockerfile 至關重要。
AboutARGProfessional illustrations
環境變量安全注意事項
講到喺 Dockerfile 入面用 ENV 指令設定環境變數,好多開發者第一反應就係方便,可以將啲配置傳入去個容器度。但係,如果你唔小心處理,呢個方便就會變成一個好大嘅安全漏洞,分分鐘俾人拎到你啲敏感資料,例如數據庫密碼、API Keys、或者係第三方服務嘅認證令牌。所以,我哋必須要認真睇吓點樣喺 鏡像構建 同埋 容器運行 嘅時候,保護好呢啲 環境變量。
首先,最常見亦都係最危險嘅錯誤,就係直接將敏感嘅環境變數寫死喺 Dockerfile 裡面。我知,貪快嘅時候真係會咁做,但係咁樣做,個敏感值就會永遠留喺 鏡像 嘅某一層度。就算你之後嘅 commit 刪咗佢,只要有人 pull 到你個舊版 鏡像,又或者用 docker history 去睇,都好容易搵得返出嚟。因為 Docker 嘅 層次文件系統 係唔會真正刪除舊層嘅。所以,千祈唔好咁樣寫:ENV DB_PASSWORD="MySuperSecretPassword123"。咁樣等同將你屋企鎖匙掛喺門口。
咁正確做法應該係點?對於構建時需要嘅敏感資料,你應該用 ARG 指令配合 --build-arg 參數。ARG 設定嘅係 構建參數,佢嘅值喺 鏡像構建 完成之後,唔會保留喺最終嘅 鏡像 層度(除非你用咗佢去設定一個 ENV)。例如,你喺 Dockerfile 度寫:ARG SECRET_KEY;然後喺 build 嘅時候傳入去:docker build --build-arg SECRET_KEY=12345 . 。咁樣,個 12345 就只會喺 構建階段 存在,唔會留喺最終 容器 嘅環境變數入面。不過都要小心,如果你喺 Dockerfile 入面做咗啲好似 RUN echo $SECRET_KEY 嘅操作,咁個值就有可能被寫入 鏡像 層,所以連 RUN 指令都要小心處理呢啲參數。
對於運行時需要嘅敏感環境變數,例如係個 容器實例 啟動時要連去數據庫,正確嘅方法係喺運行時先至傳入去。用 docker run 嘅 -e 或者 --env-file 參數來設定。例如:docker run -e DB_PASSWORD=secret my-image。咁樣,個密碼就只會存在於運行中嘅 容器 記憶體入面,而唔會固化喺 鏡像 度。呢個係 配置管理 嘅最佳實踐,將配置同程式碼分離。
另外,利用 多階段構建 都可以幫到手加強安全。你可以喺第一個構建階段用 ARG 同埋敏感資料去下載啲必要嘅套件或者做編譯(例如係 Node.js 項目用 private npm registry),然後喺第二個階段,用一個乾淨嘅基礎 鏡像(例如 alpine),只係將編譯好嘅產物 copy 過去。咁樣,最終嘅生產 鏡像 就完全唔會含有任何構建階段嘅敏感資料。BuildKit 作為新一代嘅構建引擎,喺處理呢類 多階段構建 同埋 緩存 方面更加強大同安全,建議大家啟用嚟用。
仲有一點好容易忽略,就係 PATH設置 或者其他看似無害嘅環境變數,都有可能洩漏資訊。例如,你設定咗一個 ENV 指向咗某個內部路徑,可能就會透露咗你公司內部嘅目錄結構。又或者,你喺 鏡像 入面設定咗 NODE_ENV=production,但係如果你唔小心將啲開發用嘅工具同埋 source map 都打包入去,咁樣設定咗都冇用,反而可能令人誤會個 容器 好安全。所以,設定環境變數時要諗清楚,係咪每一條都係必要,會唔會透露咗不必要嘅系統資訊。
最後,一定要養成好習慣,定期用工具掃描你嘅 鏡像,睇吓有冇唔小心留低咗敏感嘅環境變數或者密鑰。同埋,千萬唔好將含有真實敏感資料嘅 鏡像 push 上公開嘅倉庫,例如係 Docker Hub。就算你之後刪咗,都好難保證冇人已經 pull 低咗。總而言之,將環境變數當成係鎖匙同密碼咁看待,唔好寫死,要用動態傳入嘅方式,並且嚴格區分 構建時 同 運行時 嘅需要,咁先可以確保你 容器化 嘅應用程式係安全可靠,唔會出現 Error 401, Unauthorized 呢啲因為憑證洩漏而引致嘅問題,亦都避免咗將你內部嘅配置暴露於人前。
AboutBuildKitProfessional illustrations
Docker Compose整合ENV
講到 Docker Compose 整合 ENV,其實就係將你喺 Dockerfile 入面學識嗰套環境變量管理,提升到成個應用堆疊(Stack)嘅層面。好多香港嘅開發者,尤其係做緊 Node.js 或者係用緊 alpine 呢類輕量基礎鏡像嘅朋友,一開始可能淨係識喺 Dockerfile 用 ENV 指令去設定一啲固定值,例如係 PATH設置 或者係應用程式嘅預設端口。但當你要管理幾個唔同嘅服務,每個服務又有自己嘅資料庫連接字串、API金鑰(要小心 Error 401: Unauthorized 呢類問題)、或者唔同嘅構建參數時,逐個逐個容器去設定就非常麻煩同易出錯。呢個時候,Docker Compose 就係你嘅救星,佢可以幫你集中化咁管理所有環境變量,無論係開發、測試定係生產環境,配置管理都會變得清晰同安全好多。
咁點樣具體去做呢?首先你要明白,Docker Compose 處理環境變量主要有兩個大方向:第一,係喺 docker-compose.yml 檔案入面直接定義;第二,係透過外部嘅 .env 檔案去引入。我哋先講第一種。你可以直接喺 Compose 檔案嘅服務定義底下,用 environment: 呢個關鍵字去列出你嘅環境變量。例如,你有一個 Node.js 嘅服務,需要設定資料庫主機同埋一個 API 密鑰,你可以咁寫:
` environment: - DB_HOST=database_server - API_SECRET_KEY=my_secret_key_here
咁樣做嘅好處係一目了然,所有配置都喺同一個 YAML 檔案入面。但壞處都好明顯,就係將敏感資料(例如密鑰)直接寫死喺版本控制(例如 GitBook 或者 Git)入面,係非常之唔安全嘅做法。所以,呢種方法通常只係用喺一啲非敏感或者係開發環境專用嘅變量。
為咗解決安全問題,第二種方法——使用 .env 檔案——就係最佳實踐。你可以在你嘅項目根目錄建立一個名叫 .env 嘅檔案(記得要加到 .gitignore 入面,唔好提交上去!),然後喺入面好似寫設定檔咁定義變量:
DB_HOST=production_database.prod.svc API_SECRET_KEY=very_long_and_secure_random_string_2026 APP_VERSION=2.6.0
跟住,喺你嘅 docker-compose.yml 入面,你可以用 ${} 嘅語法去引用呢啲變量。更強大嘅係,你甚至可以直接喺 environment: 部分只寫變量名,等 Compose 自動去 .env 檔案度搵:
environment: - DB_HOST=${DB_HOST} - API_SECRET_KEY=${API_SECRET_KEY}
或者,你可以用更簡潔嘅列表格式。咁樣一來,你嘅 Compose 檔案本身就變得乾淨同安全,敏感資訊完全隔離。當你要切換環境,例如由開發轉去生產,你只需要換咗個 .env 檔案就得,完全唔使改動 Compose 檔案本身,呢個對於 容器化 應用嘅部署流程嚟講,係一個極之重要嘅 配置管理 優勢。
另外,一個好實用嘅技巧係將 Docker Compose 嘅環境變量同 Dockerfile 入面嘅 ARG(構建參數)同 ENV 指令結合起嚟用。記住,ARG 係用喺 鏡像構建 階段(build-time),而 ENV 係用喺 容器實例 運行階段(run-time)。喺 Compose 入面,你可以用 args: 去傳遞構建參數畀 Dockerfile,特別係當你使用緊 BuildKit 或者係 多階段構建 來優化鏡像大小嘅時候。例如,你喺 Dockerfile 入面定義咗一個 ARG,用嚟決定安裝邊個版本嘅套件:
ARG NODE_VERSION=18 FROM node:${NODE_VERSION}-alpine ...
然後,你可以在 docker-compose.yml 嘅服務底下,咁樣傳遞個值過去,甚至可以引用返 .env 檔案入面嘅變量,做到完全統一嘅參數管理:
build: context: . args: - NODE_VERSION=${NODE_VERSION_IN_ENV_FILE}
最後,不得不提嘅係 緩存 同 層 嘅問題。當你經常改變環境變量嘅值,特別係透過 ARG 去影響構建過程時,可能會意外咁令到 Docker 嘅構建緩存失效,導致重新下載依賴同構建,浪費時間同頻寬。所以,最佳做法係將經常變動嘅環境變量設定(特別係 build-time 嘅)放喺 Dockerfile 指令嘅較後位置,而將一啲穩定不變嘅設定(例如 PATH設置)放喺前面,咁樣就可以更好地利用 層次文件系統 嘅緩存優勢,加快你嘅 鏡像構建 速度。
總括嚟講,將 Docker Compose 同 ENV 整合,唔單止係為咗方便,更加係為咗實現一套可維護、安全同適應多環境嘅 容器化 策略。無論你係想避免嗰啲煩人嘅 Legacy 設定錯誤,定係想優化團隊嘅開發流程,精通環境變量喺 Compose 入面嘅各種玩法,絕對係 2026 年每個 DevOps 同開發者都要掌握嘅基本功。記住,分清楚邊啲係構建時需要,邊啲係運行時需要,善用 .env 檔案保護機密,咁你先可以真正發揮 Docker 引擎同 Docker Compose 嘅威力,令到你嘅應用由開發到上線都順暢無比。
AboutalpineProfessional illustrations
實戰例子:應用配置設定
好,等我哋用一個實戰例子,深入講下點樣喺 Dockerfile 入面用 ENV 指令去設定應用配置。呢個係 Docker 容器化最核心嘅技巧之一,因為你唔會想將數據庫密碼、API 金鑰呢啲敏感或者環境相關嘅配置,直接寫死喺個鏡像入面。咁樣個鏡像就冇咗可移植性,由開發機搬去生產環境就會出大事,例如成日撞到 Error 401 Unauthorized 呢類問題。
我哋嚟模擬一個 Node.js 應用嘅情境。假設你個應用需要連去一個外部 API,而個 API 金鑰同埋服務嘅網址(Endpoint)會因為環境(開發、測試、生產)而唔同。最差嘅做法就係將 const apiKey = 'my_secret_key_123' 直接寫死喺 app.js 檔案入面。咁做,你一將個鏡像推上 Docker Hub 或者任何容器註冊表,就已經洩漏咗機密。正確做法係利用 Dockerfile 嘅 ENV 指令,或者結合構建參數(ARG)同運行時環境變量。
首先,你喺 Dockerfile 裡面可以咁樣定義一啲基礎嘅環境變量。例如,我哋用一個輕量嘅 alpine 基礎鏡像,然後設定一啲應用運行時需要嘅配置路徑同默認值。你可以寫 ENV APP_PORT=3000 同 ENV APP_ENV=development。呢啲設定會成為鏡像嘅一部分,喺任何由呢個鏡像啟動嘅容器實例入面都會存在。呢個步驟好重要,因為佢為你嘅應用提供咗一個默認嘅運行配置。不過要留意,ENV 指令每用一次,就會為鏡像增加一個新嘅層(Layer),所以如果有多個變量,最好用一個 ENV 指令並以空格分隔嚟設定,例如 ENV APP_PORT=3000 APP_ENV=development NODE_ENV=production,咁樣可以減少鏡像層數,對構建緩存同最終鏡像大小都有好處。
但係,如果啲配置係敏感嘅,或者你希望喺唔同構建階段注入唔同嘅值,咁就要用到 ARG 同 ENV 嘅配合。ARG 係構建時(build-time)嘅變量,而 ENV 係運行時(run-time)嘅變量。實戰上,我哋經常會用 ARG 嚟傳入一啲構建時需要嘅參數(例如版本號),然後喺 Dockerfile 內部將佢賦值俾一個 ENV 變量。點解要咁做?因為 ARG 變量喺容器運行時係唔存在嘅,但 ENV 變量就會一直存在。例如,你喺構建時想安裝某個特定版本嘅軟件包,你可以用 --build-arg 參數傳入:docker build --build-arg NODE_VERSION=18 .。然後喺 Dockerfile 裡面寫 ARG NODE_VERSION,跟住用 ENV NODE_VERSION=$NODE_VERSION。咁樣,唔單止構建階段用到呢個版本號,連運行時嘅容器內部都可以透過環境變量知道呢個資訊。
講到最實用嘅應用配置設定例子,一定係處理資料庫連接。假設你個 Node.js 應用用 MongoDB,你絕對唔應該將連接字串寫死。你可以喺 Dockerfile 設定一個默認嘅,但係冇密碼嘅 ENV 變量,例如 ENV DB_HOST=localhost DB_NAME=myapp。然後,喺生產環境運行容器嘅時候,你先至用 docker run -e DB_HOST=prod-db.example.com -e DB_PASSWORD=super_secret ... 呢種方式去覆蓋佢。呢個 -e 參數就係 Docker 引擎提供嘅強大功能,可以動態設定環境變量。咁樣,同一個鏡像,就可以喺開發、測試、生產環境之間無縫切換,只需要喺 docker run 或者 Docker Compose 檔案入面改動環境變量就得,完全唔使重新構建鏡像。
另外一個進階技巧係利用多階段構建(Multi-stage build)嚟管理唔同階段嘅配置。例如,喺第一個構建階段,你可能需要用 ARG 傳入一個 Git 存取令牌(Token)去克隆私有倉庫,呢個令牌係高度敏感嘅。你可以用 ARG GIT_TOKEN,然後用呢個令牌去 clone 代碼。但係緊記,為咗安全,你一定要喺同一個構建階段裡面清除嗰個含有令牌嘅層,或者確保呢個 ARG 唔會殘留喺最終嘅鏡像層入面。呢個時候,用 BuildKit 作為構建後端可以幫到手,佢有更先進嘅緩存同安全性管理。最終,你只會將編譯好嘅應用同運行時需要嘅 ENV 變量(例如 ENV NODE_ENV=production)打包到最後一個階段嘅鏡像,敏感嘅構建參數就唔會泄漏。
最後提一提 PATH設置 呢個經典例子。好多時你安裝咗軟件,都要將佢嘅路徑加到系統 PATH 入面。喺 Dockerfile 裡面,你可以直接用 ENV PATH=/usr/local/myapp/bin:$PATH。咁樣,你之後用 RUN 指令執行命令,或者容器啟動後執行應用,系統都會自動喺你設定嘅路徑入面搵到可執行文件。呢個係配置容器內部運行環境嘅基本功。
總括嚟講,實戰應用配置設定就係要分清邊啲配置可以用 ENV 寫死喺鏡像做默認值(例如非敏感嘅路徑、默認端口),邊啲一定要透過運行時環境變量注入(例如密碼、金鑰、服務地址)。善用 ARG 同 ENV 嘅分工,可以令你嘅鏡像構建過程更加靈活同安全,避免出現 Page Not Found 或者 Legacy 配置錯誤。記住,一個設計得好的 Dockerfile,其環境變量管理策略,就係成功容器化嘅關鍵。
AboutMediumProfessional illustrations
常見ENV設定錯誤解決
好啦,講完點樣正確設定ENV,咁我哋實戰時最常撞到嘅「地雷」又有邊啲呢?好多開發者,尤其係初接觸Dockerfile ENV指令嘅朋友,好容易喺一啲細節位踩坑,搞到個鏡像構建出問題,或者係容器運行時行為古古怪怪。以下就同大家拆解幾個常見嘅設定錯誤同埋點樣解決佢。
第一個大頭佛就係將構建時同運行時嘅環境變量撈亂。呢個係最經典嘅錯誤。好多時我哋需要喺docker build過程中用一啲變量,例如去指定某個Library嘅版本,呢啲係構建參數,應該用ARG指令而唔係ENV指令。如果你誤用ENV去定義構建階段先用嘅變量,咁呢個變量就會殘留喺最終嘅鏡像層度,不單止無謂地增大鏡像體積,更可能會洩露一啲敏感資訊,例如內部嘅Repo URL或者API Key。正確做法係用ARG,佢只喺構建階段有效,完成構建後就會消失。例如,你想喺構建時下載一個特定版本嘅Node.js,應該係「ARG NODE_VERSION=18」,然後用「${NODE_VERSION}」去引用;而唔係用「ENV NODE_VERSION=18」。記住口訣:構建階段用ARG,運行配置用ENV,咁就唔會搞錯。
第二個常見錯誤係環境變量嘅值入面有空格或者特殊字符,但係又冇用引號包住。Dockerfile嘅語法其實都幾敏感,如果你設定「ENV MY_NAME=John Doe」,Docker會以為你係設定一個叫「MY_NAME=John」嘅環境變量,而個值係「Doe」,完全唔係你預期咁。所以穩陣起見,無論個值係咩,都應該用雙引號包住,變成「ENV MY_NAME="John Doe"」。特別係當你個值係一個Path,或者包含「&」、「$」呢類字符時,引號就更加必不可少,可以避免Docker 引擎解析時出錯。
第三,就係過度依賴ENV去設定PATH呢類關鍵系統變量。好多鏡像,例如官方嘅Node.js或者alpine基礎鏡像,本身已經設好咗PATH。如果你喺Dockerfile中間加多句「ENV PATH=/my/app/node_modules/.bin:$PATH」,呢個做法本身冇問題,可以讓你嘅應用程式指令行得到優先執行。但係錯誤在於,有啲人會喺唔同嘅構建階段重複設定PATH,或者將佢設定到一個完全錯誤嘅路徑,導致容器一運行就「command not found」。建議嘅做法係,喺設定PATH時,一定要用「$PATH」去保留原有嘅路徑,同埋最好喺Dockerfile比較靠前、一次過搞掂嘅位置去設定,避免後續指令因為PATH問題而失敗。另外,利用多階段構建時,要記住每個構建階段嘅環境都是獨立嘅,上一個階段設定嘅ENV(包括PATH)唔會自動帶去下一個階段,你需要按需要重新設定。
第四個陷阱係關於環境變量嘅擴展同埋緩存問題。假設你有一句「ENV VERSION=1.0」,跟住後面有一句「RUN curl -O http://example.com/app-${VERSION}.tar.gz」。睇落冇問題,但係如果你之後改咗VERSION嘅值為「2.0」,然後重新構建,Docker可能會因為緩存機制,直接使用舊緩存嘅層,而唔會重新執行呢條RUN指令,結果你下載嘅依然係舊版本「1.0」嘅檔案。要打破呢個緩存,你可以用「--build-arg」傳入一個構建時間戳記作為ARG,然後喺RUN指令度引用佢,迫使Docker認為係一個新指令而跳過緩存。呢個技巧對於確保依賴更新好有用。
最後,仲有一個情況係同安全相關嘅:將秘密資料直接寫死喺ENV指令度。無論你係將API Token、數據庫密碼直接寫喺Dockerfile入面,定係用ENV指令去設定,只要呢啲資訊存在於鏡像嘅某一層,任何拿到呢個鏡像嘅人都可以用「docker history」或者直接運行容器並檢查環境變量嘅方式睇到。呢個係極之危險嘅做法。正確嘅配置管理方式係,喺運行時先通過「docker run -e」或者Docker Compose檔案嘅「environment」部分注入,又或者使用Docker Secrets或BuildKit嘅秘密掛載功能(適用於構建階段需要秘密嘅情況)。總之,要記住Dockerfile同最終生成嘅鏡像係不應該包含任何敏感資訊嘅。
總括來講,避開呢啲常見嘅ENV設定錯誤,關鍵在於清晰理解每條指令嘅作用範圍(構建時vs運行時)、注意語法細節(善用引號)、尊重Docker嘅層次文件系統同緩存機制,以及時刻將安全意識擺喺第一位。搞掂呢幾點,你寫出嚟嘅Dockerfile就會穩定同安全好多,唔會再出現啲似「Page Not Found」或者「Error 401 Unauthorized」呢類因為環境變量設定不當而引致嘅古怪問題啦。
AboutFoundProfessional illustrations
動態環境變數進階用法
講到動態環境變數嘅進階用法,我哋就唔可以再停留喺 Dockerfile 入面用 ENV 指令設定死一個值咁簡單。對於香港嘅開發者同 DevOps 團隊嚟講,要應付複雜嘅 CI/CD 流程、多環境部署(例如 Testing、Staging、Production),就一定要識得靈活運用 ARG 同 ENV 嘅配合,甚至係利用 BuildKit 嘅強大功能,嚟實現真正嘅動態配置。呢啲技巧可以令你構建出更安全、更靈活,而且更容易維護嘅容器鏡像。
首先,你一定要搞清楚 構建時 同 運行時 嘅分別,呢個係理解進階用法嘅核心。喺 Dockerfile 裡面,ARG 係 構建參數,佢只喺鏡像構建階段有效,完成 docker build 之後,佢嘅使命就完結,唔會存在於最終嘅容器實例入面。相反,ENV 設定嘅 環境變量 就會被寫入鏡像嘅某一層,喺容器啟動時依然存在。所以,一個好常見嘅進階模式就係:用 ARG 喺構建時傳入一啲敏感或者可變嘅資料(例如某個依賴庫嘅版本號),然後用佢嚟設定一個 ENV 變量。咁樣做既可以保持構建過程嘅動態性,又可以確保運行時有需要嘅配置。例如,你想個 Node.js 應用喺構建時安裝指定版本嘅 npm package,就可以用 ARG NPM_TOKEN 傳入 token,但呢個 token 唔應該留喺最終鏡像,所以唔會用 ENV 保存佢。
點樣先可以將動態性玩到出神入化?關鍵在於 多階段構建。假設你個應用需要編譯,編譯階段可能需要一啲秘鑰(例如從私人 GitBook 倉庫拉取內容),但運行階段完全唔需要。你就可以喺第一個構建階段用 ARG 傳入秘鑰,完成編譯後,將編譯好嘅產物複製到第二個階段(例如一個乾淨嘅 alpine 鏡像),而秘鑰就完全唔會進入最終嘅運行鏡像,大大提升安全性。呢個過程充分體現咗點樣透過 構建階段 去管理唔同嘅 環境變量 生命周期。
另外,善用 Docker 引擎嘅 緩存 機制都係進階技巧。如果你成日改動 ENV 指令嘅值,可能會導致緩存失效,令成個 鏡像構建 過程要重新行過,好嘥時間。點樣避免?你可以將最常變動嘅 ENV 指令擺喺 Dockerfile 較後嘅位置,甚至結合 ARG。例如,將版本號呢類經常變嘅嘢設為 ARG,然後喺接近檔案末尾先用佢嚟設定 ENV。又或者,將一啲真正動態、每次啟動都可能唔同嘅變數(例如 Error 401 時嘅重試次數),完全唔寫死喺鏡像,改為喺運行時通過 docker run -e 或者 Kubernetes 嘅 ConfigMap 嚟注入,咁樣個鏡像本身就更具通用性。
講到注入,就要提下 PATH設置 呢類基礎環境變量嘅進階管理。唔好以為 PATH 好簡單,當你喺多階段構建入面,從一個鏡像複製可執行文件去另一個鏡像時,好容易因為 PATH 唔同而出現 "command not found" 呢類 Legacy 問題。正確做法係,喺每個階段都明確地用 ENV 指令去設定或修改 PATH,確保無論喺邊個 構建階段,指令都可以正確執行。例如,你從一個裝咗一大堆工具嘅構建鏡像,複製一個二進制文件去一個 alpine 鏡像,記得喺 alpine 階段設定好 PATH 指向你複製文件嘅目錄。
最後,不得不提 BuildKit 帶嚟嘅革命性改進。由 2026 年嘅角度睇,BuildKit 已經係現代 Docker 環境嘅標準配置。佢提供咗更精細嘅 緩存 控制同安全功能。例如,你可以用 --secret 參數喺構建時傳入真正敏感嘅資料(比如係避免 Unauthorized 錯誤嘅 API key),而呢個資料完全唔會留喺 Dockerfile 歷史或者最終鏡像嘅任何 層 入面,比用 ARG 更安全。雖然我哋唔寫出嚟,但你要知道有呢個強大工具可以去研究。總而言之,掌握動態環境變數嘅進階用法,就等於掌握咗 容器化 應用 配置管理 嘅精髓,由單純砌出一個可以行到嘅 容器,升級到可以砌出一個適應任何環境、安全又高效嘅工業級鏡像,對於處理複雜部署嘅團隊嚟講,絕對係必學技能。
AboutHYProfessional illustrations
跨平台ENV設定兼容性
講到跨平台ENV設定兼容性,呢個真係唔少Docker用家嘅痛點。你喺Mac機寫好嘅Dockerfile,入面用ENV指令設定咗一啲環境變量,點知擺上Linux伺服器或者Windows CI/CD pipeline構建時,就出晒古靈精怪嘅問題,例如Page Not Found、Error 401 Unauthorized,甚至係路徑問題搞到成個鏡像行唔到。原因好簡單,唔同操作系統嘅底層處理環境變量、文件路徑同埋指令解析,都可能有微妙差異。所以,要確保你嘅Docker鏡像可以喺任何平台順利構建同運行,ENV設定嘅兼容性策略就變得超關鍵。
首先,最常見嘅地雷位就係PATH設置同文件路徑。例如,你喺ENV指令入面直接寫死一條絕對路徑,好似係「ENV APP_PATH=/usr/local/myapp」。喺Linux同alpine呢類基礎鏡像度行就冇問題,但如果你個鏡像要支援Windows容器,或者構建階段涉及唔同嘅基礎層,條路徑就可能完全唔對。比較穩陣嘅做法係,盡量使用相對路徑,或者利用Docker提供嘅標準目錄(例如「/app」),同埋要清楚知道每個基礎鏡像(例如node.js官方鏡像同alpine版本)預設嘅環境配置有咩唔同。另外,用「ENV」設定PATH去添加自定義執行檔位置時,要留意拼接嘅格式(Linux用冒號「:」分隔,Windows用分號「;」),呢度好易中伏。
另一個重點係點樣處理構建時同運行時嘅環境變量。呢度就要分清「ENV」同「ARG」指令嘅用途。「ENV」設定嘅變量會持久化到容器運行環境,而「ARG」就只係喺鏡像構建階段(build-time)先有效,係構建參數。點解呢個同跨平台兼容性有關?因為如果你將一啲平台相關嘅設定(例如某個依賴庫嘅下載URL)錯誤地用「ENV」寫死喺Dockerfile,咁個鏡像去咗第二個平台運行時,個值可能係錯嘅。正確做法係,將平台相關或者敏感嘅配置,透過「ARG」喺構建時傳入(用「--build-arg」參數),然後再喺需要時賦值俾「ENV」,或者更好嘅係,等到運行容器時先透過「-e」參數注入。咁樣,你個Dockerfile本身就更具可移植性。
而家Docker 引擎同BuildKit已經成為主流,佢哋對多階段構建嘅支援亦幫到手提升兼容性。你可以喺唔同嘅構建階段,為唔同嘅平台設定專屬嘅「ENV」。例如,第一個階段用嚟編譯程式,你可以針對編譯環境設定ENV;第二個階段係運行階段,就用一個乾淨嘅基礎鏡像,只設定運行所需嘅最少ENV變量。呢種做法唔單止可以減細最終鏡像體積,更重要係將平台相關嘅構建工具污染隔離咗,令到最終運行時嘅環境更統一、更少兼容性問題。記得,每個「FROM」指令都會開始一個新階段,入面嘅ENV設定唔會自動帶去下個階段,呢個特性要善用。
仲有,環境變量嘅引用同默認值設定都要小心。喺Dockerfile入面,你會用「$VARIABLE」或者「${VARIABLE}」嚟引用變量。為咗避免變量未定義時出錯,可以設定默認值,語法係「${VARIABLE:-default}」。呢個技巧對於跨平台兼容好有用,因為你可以設定一個通用默認值,然後容許喺構建或運行時,按平台需要去覆寫佢。例如,設定「ENV LOG_LEVEL=${LOG_LEVEL:-info}」,咁無論喺邊個平台,如果無特別指定,都會用「info」等級,但平台管理員可以輕易改咗佢。
最後,實戰上仲要留意一啲細微位。比如話,唔好依賴宿主機嘅環境變量自動傳入構建過程,除非你明確用「--build-arg」傳遞。又例如,清理唔必要嘅ENV變量,因為每一條「ENV」指令都會成為鏡像嘅一個層,多餘嘅變量可能會意外影響後面嘅指令,或者造成緩存失效。定期審視你嘅Dockerfile,睇下有冇ENV設定係已經變成Legacy(遺留)或者係某個舊平台先需要,及時清理咗佢。總括嚟講,寫Dockerfile ENV設定時,心態要好似寫跨平台應用咁,假設個環境會喺唔同地方構建同運行,咁自然就會寫出更穩陣、兼容性更高嘅配置,確保你嘅容器化應用可以順暢喺任何Docker引擎上跑起嚟,唔會出啲令人頭痛嘅Error。
AboutENV指令Professional illustrations
生產環境最佳配置指南
好,咁我哋就講下點樣喺生產環境度,將你個 Dockerfile 同 ENV 指令配置到最好。呢度唔係講啲基本嘢,而係真係要上 Production 嘅實戰心法,尤其係點樣管理環境變量同優化鏡像,避開晒啲常見嘅 Legacy Error 401 Unauthorized 或者 Page Not Found 呢類鑊氣。
首先,最緊要係分清「構建時」同「運行時」。呢個係好多新手甚至中手都會撈亂嘅位,一撈亂就會將敏感資料(例如 API Key)打包入鏡像層,搞到安全大鑊。喺 Dockerfile 裏面,ENV 指令設定嘅環境變量,係會同時喺構建階段同最後嘅容器實例入面生效。如果你要傳入啲密碼或者 Token 去 build,例如用嚟安裝私人 npm package,咁你一定要用 ARG 配合 --build-arg 參數,而且記住 ARG 只係喺構建階段存在。最佳做法係,用 ARG 嚟接收構建參數,然後喺 RUN 指令度用,完成後就清理,千祈唔好將佢留喺最終嘅鏡像層度。例如,你可以用多階段構建,喺第一階段用 ARG 裝完嘢,到第二階段只係抄走需要嘅檔案,咁樣敏感資料就唔會留低,大大減少風險。
跟住落嚟,講下點樣有策略地用 ENV 指令。好多人都係求其喺 Dockerfile 開頭打一大抽 ENV,但咁樣會破壞緩存機制。Docker 引擎嘅層次文件系統好睇重指令順序,如果你成日改動最頂嗰幾個 ENV,後面所有指令嘅緩存層都會失效,要重新構建,好嘥時間。所以,生產環境最佳配置係:將最穩定、最少改動嘅環境變量放喺前面(例如 LANG=C.UTF-8),而將成日會變、或者係應用特定嘅變量(例如 NODE_ENV=production)放喺 Dockerfile 嘅較後位置,最好就係放喺 COPY 咗應用程式碼之後。另外,PATH 設置都係一個重點,你應該喺 ENV 指令度擴展 PATH,而唔係直接覆蓋,等你可以用番系統原有嘅路徑,避免行唔到一啲基本指令。
另外,選擇基礎鏡像都好關鍵。Alpine 係好細,但唔係萬能。喺生產環境,你要考慮唔係淨係 size,仲有安全性、穩定性同維護性。Alpine 用 musl libc,有時會同某啲編譯好嘅二進制檔案(例如 Node.js 嘅某啲 native module)唔兼容,可能引致啲古靈精怪嘅 runtime error。所以,好多企業生產環境反而會用官方嘅 slim 版本(例如 node:20-slim),佢哋基於 Debian,有更好嘅兼容性,同時都 keep 住個鏡像唔會太大。記住,構建階段你可以用多個不同基礎鏡像,最後先將成品放去一個最精簡嘅基礎鏡像度,呢個就係多階段構建嘅精髓,可以平衡開發靈活性同生產環境嘅安全輕量。
最後,一定要提配置管理嘅文化。千祈唔好將 .env 檔案直接 COPY 入鏡像,亦都唔好喺 Dockerfile 入面寫死啲會因環境而異嘅值(例如資料庫連接字串)。正確做法係,喺 Dockerfile 入面用 ENV 設定預設值,然後喺運行容器嘅時候,透過 docker run -e 或者 Docker Compose 檔案,再唔係就係 Kubernetes 嘅 ConfigMap/Secret,從外部注入環境變量。咁樣,同一個鏡像就可以喺唔同環境(開發、測試、生產)度無縫使用,實現真正嘅「一次構建,到處運行」。同時,善用 BuildKit 呢個現代構建引擎,佢可以提供更好嘅緩存管理同安全性,例如可以用 secret mount 嘅方式安全傳遞構建參數,連 ARG 都唔使出現喺最終嘅鏡像歷史度。總之,生產環境嘅配置,核心思想就係「分離關注點」:構建邏輯歸 Dockerfile,運行配置歸外部環境,咁先至係穩陣、安全同易於維護嘅王道。
AboutDocker 引擎Professional illustrations
2026最新Docker ENV趨勢
講到2026年最新嘅Docker ENV趨勢,我哋首先要睇吓Docker生態有咩大變化。而家Docker 引擎同BuildKit嘅整合已經去到一個新層次,ENV指令唔再係單純喺Dockerfile裡面設定啲固定值咁簡單。好多團隊開始玩更精細嘅環境變量管理策略,特別係喺多階段構建入面,點樣善用ENV同ARG(構建參數)去優化鏡像構建流程,成為咗關鍵。例如,你喺第一個構建階段用ARG嚟傳入一啲敏感嘅API Key(當然要用--build-arg小心傳),然後喺最後嘅生產鏡像階段,只係透過ENV設定一啲運行時必要、但非敏感嘅配置,咁樣就可以大幅減少安全風險同鏡像層數,對緩存機制亦都更加友好。
另一個好明顯嘅趨勢係,環境變量嘅動態注入同配置管理變得更加「無縫」。以前可能要靠一啲外部工具或者複雜嘅腳本,但係而家結合咗GitBook或者類似嘅內部文檔平台,團隊可以好容易將最新嘅環境配置同步到容器啟動參數度。不過要提提你,如果你仲用緊一啲Legacy方法,例如將成抽配置硬編碼喺Dockerfile裡面,好容易就會遇到類似Error 401, Unauthorized呢類問題,因為啲密碼或者Token可能已經過期,但鏡像又無更新到。所以2026年嘅最佳實踐,係強烈建議將所有運行時配置,透過環境變量喺容器實例啟動嗰陣先注入,而唔係固化喺鏡像入面。
至於PATH設置呢類基礎但又好重要嘅ENV,趨勢係走向更精簡同明確。好似用alpine呢類超細基礎鏡像嘅時候,好多開發者會特登喺Dockerfile裡頭用ENV指令去重新定義PATH,確保自己安裝嘅軟件(例如特定版本嘅Node.js)路徑優先被使用,避免因為鏡像本身預設PATH而導致「command not found」呢類古靈精怪錯誤。呢個做法雖然細微,但對於確保容器化應用行為一致性好有幫助。
另外,點樣聰明地使用ENV嚟控制構建過程本身,都係一個熱門話題。例如,你可以設定一個環境變量叫 NODE_ENV=production`,然後喺Dockerfile入面嘅RUN指令(例如npm install)就會根據呢個變量去決定安裝啲咩包(唔裝devDependencies)。但要注意啦,如果呢個ENV係喺Dockerfile較早位置定義,佢可能會影響後續所有構建階段嘅緩存。所以2026年嘅常見手法,係將呢類影響構建行為嘅ENV,集中放喺一個專門嘅構建階段,或者用ARG傳入,等層次文件系統嘅緩存失效可以控制得更精準。
最後都要提吓錯誤處理嘅趨勢。而家好少會見到啲容器因為缺少環境變量而直接出Page Not Found或者爆Error 401就算數。更多係會喺Dockerfile或者應用啟動腳本入面,加入一啲檢查邏輯,如果必要嘅ENV唔存在,就會喺容器啟動時即刻輸出明確錯誤日誌然後停止,而唔係行到一半先嚟跪低。呢種做法對於喺Medium到大規模K8s集群呢啲不同環境下嘅除錯,效率高好多。總括嚟講,2026年Docker ENV嘅核心思路,就係「動態、安全、明確同可維護」,將配置同鏡像本身盡量分離,同時善用構建階段同變量引用機制去打造更輕量、更安全嘅容器。