2016-11-04 43 views
2

我在AWS上有兩個彈性beanstalk環境:開發和生產。我在每個實例上運行一個glassfish服務器,並且要求相同的應用程序包可以在生產環境和開發環境中部署,而不需要兩個不同的文件。這兩個實例大小不同:dev有一個微型實例,而生產有一箇中等的實例,因此我需要爲glassfish部署兩個不同的配置文件,每個環境一個。EC2上的Docker,dockerfile中的RUN命令沒有讀取環境變量

主要的問題是該文件必須在服務器啓動之前在glassfish config目錄中,因此我認爲在容器創建時移動它可能會更好。

當然,每個環境都使用docker容器來託管glassfish實例,所以我的第一個想法是爲elastic-beanstalk配置一個環境變量。在這種情況下

ypenvironment = dev 

的開發環境和

ypenvironment = pro 

用於生產環境。然後在我的DOCKERFILE我把這種說法在運行命令:

RUN if [ "$ypenvironment"="pro" ] ; then \ 
     mv --force /var/app/GF_domain.xml /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \ 
    elif [ "$ypenvironment"="dev" ] ; then \ 
     mv --force /var/app/GF_domain.xml.dev /usr/local/glassfish/glassfish/domains/domain1/config/domain.xml ; \ 
    fi 

不幸的是,當啓動完成後,雙方GF_domain文件仍在var/app

然後我發現RUN命令在容器完全加載之前運行了一些東西,可能缺少彈性beanstalk注入的變量。所以我試着將代碼移動到ENTRYPOINT指令。再次運氣不佳,容器啓動失敗。也試過

ENTRYPOINT ["command", "param"] 

語法,但它沒有工作給予

System error: exec: "if": executable file not found in $PATH 

因此我堅持。

回答

2

你需要:

1/使用入口點(或至少使用sh -c 'if...'語法):作爲用於運行時執行,而不是在編譯時生成的圖像。

2 /使用build-time variables (--build-arg)

可以使用在Dockerfile ENV指令來定義變量值。這些值堅持在建成的形象。
但是,往往持久性不是你想要的。用戶想要根據他們在哪個主機上構建圖像來指定不同的變量。

一個很好的例子是http_proxy或拉動中間文件的源版本。該ARG指令讓Dockerfile作者定義用戶可在編譯時使用--build-arg標誌設置值:

$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 . 

在你的情況,你的Dockefile應包括:

ENV ypenvironment 

然後docker build --build-arg ypenvironment=dev ... myDevImage

您將構建2個不同的圖像(基於相同的Dockerfile)


我需要能夠使用相同的EAR包用於開發和親環境,

然後,你希望你的入口點,運行的時候,要根據環境的價值移動文件變量。

你Dockerfile仍然需要包括:

ENV ypenvironment

但你需要與

docker run -x ypenvironment=dev ... 

運行一個像確保您的腳本(通過您的入口點引用)包括if [ "$ypenvironment"="pro" ] ; then...你在你的問題中提到,加上你的應用的實際啓動(在前臺)。
您的腳本需要而不是立即退出,或者您的容器在啓動後立即切換到退出狀態。

+0

對不起,它不清楚,但兩個不同的構建是我想要避免的。我需要能夠爲dev和pro環境使用相同的EAR包,但在elastic-beanstalk中,您只能部署EAR文件,而EAR文件又必須包含DOCKERFILE。也許有一種方法可以在運行docker build命令的上下文中獲取環境變量值,但我不知道。我會盡快編輯我的問題,謝謝! – Gabber

+0

@Gabber所以你說的是運行時,而不是構建時間(Dockerfile)? – VonC

+0

@Gabber我編輯了我的答案,包括運行時語法 – VonC

2

使用Docker時,您必須區分構建時操作和運行時操作。 Dockerfiles用於構建Docker鏡像,不用於部署容器。這意味着Dockerfile中的所有命令都會在您構建Docker鏡像時執行,當您從中部署容器時,它將執行而不是

CMDENTRYPOINT命令是特殊的構建時命令,它告訴Docker在從映像部署容器時要執行的命令。

現在,在你的情況下,更好的方法是檢查Glassfish是否支持domain.xml(或其他地方)中的環境變量。如果是這樣,您可以在兩種環境中使用相同的domain.xml文件,併爲它們使用相同的Docker映像。然後,通過在本地運行時使用docker run -e "VAR=value"以及在Elastic Beanstalk上部署時使用環境屬性配置部分,將運行時環境變量注入容器,然後區分這些環境。

編輯:如果你不能使用內部domain.xml環境變量,您可以通過啓動一個腳本讀取運行環境變量,並把它們的值在正確的地方使用seddomain.xml容器解決問題,然後照常開始你的申請。你可以在this post找到一個例子。

+0

這不是我所要求的,而是我所需要的。感謝:) – Gabber

+0

對不起,我試過這個解決方案,但沒有工作,恐怕不可能讓Glassfish的domain.xml文件從aws環境讀取變量,因此不能接受這個正確的答案 – Gabber

+0

然後,還有另一種解決方案恰好適用於這些情況。我已經更新了我的答案。祝你好運:-) –

相關問題