Docker的ARG、ENV和.env配置完整指南
本文將幫助您自信地使用 Docker ARG、ENV、env_file 和 .env 檔案。您將瞭解如何使用 Docker 構建時變數、環境變數和 docker-compose 模板輕鬆配置 Docker 映像和 dockerized 應用程式。
常見的誤解
- .env 檔案僅在使用docker-compose.yml 檔案時的預處理步驟中使用。美元符號變數(如 $HI)被替換為同一目錄中名為“.env”的檔案中包含的值。
- ARG僅在構建 Docker 映像(RUN 等)期間可用,而不是在建立映像並從其啟動容器之後(ENTRYPOINT、CMD)。您可以使用 ARG 值來設定 ENV 值來解決這個問題。
- ENV值可用於容器,但在 Docker 構建期間也可使用 RUN 樣式的命令,從引入它們的行開始。
- 如果您使用 bash (RUN export VARI=5 && …) 在中間容器中設定環境變數,它將不會在下一個命令中持續存在。有辦法解決這個問題。
- env_file是一種將許多環境變數一次性傳遞給單個命令的便捷方式。這不應與.env檔案混淆。
- 設定 ARG 和 ENV 值會在 Docker 映像中留下痕跡。不要將它們用於不打算保留的秘密(好吧,您可以使用多階段構建)。
該指南分為以下主題:
The Dot-Env File (.env)
如果您的專案中有一個名為.env的檔案,它僅用於將值放入同一資料夾中的 docker-compose.yml 檔案中。這些與 Docker Compose 和 Docker Stack 一起使用。它與 ENV、ARG 或上面解釋的任何 Docker 特定無關。這完全是 docker-compose.yml 的事情。
檔案中的值.env用以下表示法編寫:
VARIABLE_NAME=some value OTHER_VARIABLE_NAME=some other value, like 5 |
這些鍵值對用於替換 docker-compose.yml 檔案中的美元符號變數。這是一種預處理步驟,並使用生成的臨時檔案。這是避免硬編碼值的好方法。
這是一個示例 docker-compose.yml 檔案,依賴於 .env 檔案提供的值:
version: '3' services: plex: image: linuxserver/plex environment: - env_var_name=${VARIABLE_NAME} # here it is |
提示:使用 .env 檔案時,您可以很容易地除錯 docker-compose.yml 檔案。只需輸入docker-compose config。透過這種方式,您將看到 docker-compose.yml 檔案內容在執行替換步驟後的樣子,而無需執行任何其他內容。
ARG 和 ENV 可用性
在使用Docker時,我們區分了兩種不同型別的變數--ARG和ENV。
ARG也被稱為構建時變數。它們只在Docker檔案中用ARG指令 "宣佈 "的那一刻起可用,直到映象被構建。執行中的容器不能訪問ARG變數的值。這也適用於CMD和ENTRYPOINT指令,它們只是告訴容器在預設情況下應該執行什麼。如果你告訴Dockerfile期待各種ARG變數(沒有預設值),但在執行構建指令時卻沒有提供任何ARG變數,就會出現錯誤資訊。
然而,ARG值可以在映象建立後,透過檢視映象的docker歷史,很容易被檢查出來。因此,他們是敏感資料的一個糟糕選擇。
ENV變數在構建過程中也是可用的,只要你用ENV指令引入它們。然而,與ARG不同的是,它們也可以被從最終映象中啟動的容器所訪問。在啟動一個容器時,ENV值可以被覆蓋,下面會有更多的介紹。
下面是圍繞從Docker檔案構建Docker映象和執行容器的過程中,對ARG和ENV可用性的簡化概述。它們是重疊的,但ARG不能從容器內部使用。
設定ARG值
所以,你有你的Docker檔案,其中定義了ARG和ENV值。如何設定它們,以及在哪裡設定?你可以在Docker檔案中留空,或者設定預設值。如果你沒有為預期的ARG變數提供一個值,而這些變數沒有預設值,你會得到一個錯誤資訊。
這裡有一個Dockerfile的例子,既有預設值,也有沒有預設值的。
ARG some_variable_name # or with a hard-coded default: ARG some_variable_name=default_value RUN echo "Oh dang look at that $some_variable_name" # you could also use braces - ${some_variable_name} |
當從命令列構建Docker映象時,你可以使用-build-arg設定ARG值。
$ docker build --build-arg some_variable_name=a_value
使用上述Dockerfile執行該命令,將導致以下一行被列印出來(除其他外)。
Oh dang look at that a_value |
那麼,這如何轉化為使用docker-compose.yml檔案?當使用docker-compose時,你可以在args塊中指定傳遞給ARG的值。
version: '3' services: somename: build: context: ./app dockerfile: Dockerfile args: some_variable_name: a_value |
當你試圖設定一個在Docker檔案中沒有提到的ARG變數時,Docker會抱怨。
設定ENV值
那麼,如何設定ENV值呢?你可以在啟動容器時設定(我們將在下面討論這個問題),但你也可以透過硬編碼在Docker檔案中直接提供預設ENV值。此外,你還可以為環境變數設定動態的預設值!
在構建映象時,你能提供的唯一東西是ARG值,如上所述。你不能直接提供ENV變數的值。然而,ARG和ENV都可以一起工作。你可以使用ARG來設定ENV變數的預設值。下面是一個基本的Docker檔案,使用硬編碼的預設值。
# no default value ENV hey # a default value ENV foo /bar # or ENV foo=/bar # ENV values can be used during the build ADD . $foo # or ADD . ${foo} # translates to: ADD . /bar |
這裡是一個Docker檔案的片段,使用動態構建時的環境值。
# expect a build-time variable ARG A_VARIABLE # use the value to set the ENV var default ENV an_env_var=$A_VARIABLE # if not overridden, that value of an_env_var will be available to your containers! |
一旦映象構建完成,你可以透過三種不同的方式啟動容器,併為ENV變數提供數值,可以從命令列或使用docker-compose.yml檔案。所有這些都將覆蓋Docker檔案中的任何預設ENV值。與ARG不同,你可以向容器傳遞所有種類的環境變數。即使是那些在Dockerfile中沒有明確定義的變數。然而,這取決於你的應用程式是否會做任何事情。
- 1. 逐一提供數值
在命令列中,使用-e標誌。
$ docker run -e "env_var_name=another_value" alpine env |
來自docker-compose.yml :
version: '3' services: plex: image: linuxserver/plex environment: - env_var_name=another_value |
[b]2. 從你的主機傳遞環境變數值[/b]
這和上面的方法是一樣的。唯一的區別是,你不提供一個值,而只是命名這個變數。這將使Docker訪問主機環境中的當前值,並將其傳遞給容器。 |
$ docker run -e env_var_name alpine env
對於docker-compose.yml檔案,省去等號和後面的所有內容,以達到同樣的效果。
version: '3' services: plex: image: linuxserver/plex environment: - env_var_name |
- 3. 從一個檔案中取值(env_file)
我們可以指定一個檔案來讀取這些變數的值,而不是把這些變數寫出來或硬編碼(根據12因素的人的意見,這不是好的做法)。這樣一個檔案的內容看起來像這樣。
env_var_name=another_value
上面的檔案叫做env_file_name(名稱任意),它位於當前目錄下。你可以引用這個檔名,透過解析,提取要設定的環境變數。
$ docker run --env-file=env_file_name alpine env
在docker-compose.yml檔案中,我們只需引用一個env_file,然後Docker就會解析它,找出要設定的變數。
version: '3' services: plex: image: linuxserver/plex env_file: env_file_name |
這裡有一張小抄,結合了ARG和ENV可用性的概述以及從命令列設定它們的常用方法。
在我們繼續之前:如果你是Docker的新手,並且不習慣考慮映象和容器,就會經常遇到一個問題:如果你試圖在RUN語句中設定一個環境變數的值,比如RUN export VARI=5 && ...,你將無法在接下來的RUN語句中訪問它。其原因是,對於每個RUN語句,一個新的容器會從一箇中間映像中啟動。命令結束後會儲存一個映象,但環境變數不會以這種方式持續存在。
如果你對一個映像感到好奇,想知道它是否在容器啟動前提供了預設的ENV變數值,你可以檢查Image映像,看看哪些ENV條目是預設設定的。
# first, get the images on your system and their ids $ docker images # use one of those ids to take a closer look $ docker inspect image-id # look out for the "Env" entries |
覆蓋ENV值
假設你有一個由Dockerfile構建的映象,它提供了預設的ENV值。從它啟動的容器可以訪問Dockerfile中定義的ENV變數。然而,這些值可以透過提供單一的環境變數或env_files來覆蓋,環境變數被解析並傳入容器。
一旦一個程式在容器內執行,或者當一個命令被評估時,他們可以為自己改變環境值。像這樣的東西。
$docker run myimage SOME_VAR=hi python app.py
將完全覆蓋你可能為app.py指令碼設定的任何SOME_VAR,即使在最後命令之前有一些帶有-e標誌的值。
優先順序是,從強到弱:容器化應用程式集的東西,來自單一環境條目的值,來自env_file(s)的值,最後是Dockerfile預設值。
相關文章
- Dockerfile小記之ARG和ENVDocker
- Dockerfile 第4關:ENV、EXPOSE、WORKDIR、ARG指令Docker
- Laravel 原始碼閱讀指南 -- 載入和讀取 ENV 配置Laravel原始碼
- laravel5.8 如何修改.env路徑?如修改./.env為./env/product.envLaravel
- NODE_ENV和webpackWeb
- [Bash] env
- Laravel 配置多環境env檔案Laravel
- 理解webpack之process.env.NODE_ENV詳解(十八)Web
- PHP開發laravel框架的.env檔案配置PHPLaravel框架
- Laravel 支援動態多 env 配置讀取Laravel
- process.env.NODE_ENV環境變數vue2.x變數Vue
- 設定環境變數配置的簡單方法.env變數
- env 環境變數變數
- #!/usr/bin/env pythonPython
- Laravel5.5 和 5.2 env 取值問題Laravel
- vue cli中的env詳解Vue
- Laravel 和 Lumen 中通過環境變數配置對應的 env 檔案Laravel變數
- cross-env 是什麼ROS
- 解決:NPM ERR! @ dev: `node node_modules/cross-env/bin/cross-env.js 的辦法NPMdevROSJS
- goland終端中go env與系統中go env不一致的問題GoLand
- cross-env 是什麼鬼ROS
- laravel 踩坑 env,configLaravel
- 如何修改process.env.PROXY_SERVERServer
- @babel/preset-env使用polyfill遇到的坑Babel
- @babel/preset-env的一個引數Babel
- 在非 laravel 專案中使用 laravel 的特性 5: 配置 config && envLaravel
- NODE_ENV跨平臺設定
- Laravel Class env does not exist 問題排查Laravel
- conda support env+python versionPython
- 【jenkins】/usr/bin/env: php: No such file or directoryJenkinsPHP
- env :讓系統決定你命令的位置
- k8s env、configmap、secret外部資料載入配置K8S
- Homestead 上 cross-env 裝不上ROS
- Laravel env 設定多環境切換Laravel
- Network config of Openwrt based ESXI Env
- 深入理解 Laravel 中.env 檔案讀取Laravel
- 我又掉 Laravel env 函式坑裡了Laravel函式
- PHP/MySQL Dev. Primer (1) Establish Env.PHPMySqldev