รับค่าตัวแปรสภาพแวดล้อมใน Dockerfile


254

ฉันกำลังสร้างตู้คอนเทนเนอร์สำหรับแอปทับทิม การกำหนดค่าแอพของฉันมีอยู่ในตัวแปรสภาพแวดล้อม (โหลดภายในแอพด้วยdotenv )

หนึ่งในตัวแปรการกำหนดค่าเหล่านั้นคือ public ip ของแอพซึ่งใช้ภายในเพื่อสร้างลิงก์ ฉันต้องเพิ่มรายการ dnsmasq ที่ชี้ ip นี้ไปที่ 127.0.0.1 ภายในคอนเทนเนอร์เพื่อให้สามารถดึงลิงก์ของแอปราวกับว่ามันไม่ได้ถูกจัดเก็บ

ฉันจึงพยายามตั้งค่าENVใน Dockerfile ของฉันซึ่งจะส่งผ่านตัวแปรสภาพแวดล้อมไปยังคอนเทนเนอร์

ฉันลองบางสิ่ง

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

ทุกอย่างผ่านสตริง "REQUEST_DOMAIN" แทนที่จะเป็นค่าของตัวแปรสภาพแวดล้อม มีวิธีส่งค่าตัวแปรสภาพแวดล้อมจากเครื่องโฮสต์ไปยังคอนเทนเนอร์หรือไม่?

คำตอบ:


392

คุณควรใช้ARGคำสั่งใน Dockerfile ของคุณซึ่งมีความหมายสำหรับวัตถุประสงค์นี้

ARGคำแนะนำและกำหนดตัวแปรที่ผู้ใช้งานสามารถส่งผ่านที่สร้างเวลาในการสร้างที่มีนักเทียบท่าสร้างคำสั่งใช้เป็น--build-arg <varname>=<value>ธง

ดังนั้นDockerfileของคุณจะมีบรรทัดนี้:

ARG request_domain

หรือหากคุณต้องการค่าเริ่มต้น:

ARG request_domain=127.0.0.1

ตอนนี้คุณสามารถอ้างอิงตัวแปรนี้ภายใน Dockerfile ของคุณ:

ENV request_domain=$request_domain

จากนั้นคุณจะสร้างภาชนะของคุณเช่น:

$ docker build --build-arg request_domain=mydomain Dockerfile


หมายเหตุ 1:ภาพของคุณจะไม่สร้างหากคุณมีการอ้างอิงARGใน Dockerfile ของคุณ --build-argแต่ยกเว้นใน

หมายเหตุ 2:หากผู้ใช้ระบุ build build ที่ไม่ได้กำหนดไว้ใน Dockerfile บิลด์จะสร้างคำเตือน:

[คำเตือน] ไม่ได้สิ้นเปลืองงานสร้างอย่างน้อยหนึ่งรายการ


12
ARG มีให้บริการจากนักเทียบท่า v1.9 เป็นต้นไป
Synesso

สิ่งนี้ได้รับการสนับสนุนให้สร้างจากระยะไกลบน repo docker หรือไม่
James Lin

4
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argคุณผิด. คุณสามารถสร้างภาพที่มีการอ้างอิงได้โดยไม่ต้อง - build-arg ยิ่งกว่านั้นคุณสามารถตั้งค่าเริ่มต้นสำหรับการสร้าง ARG
ALex_hha

1
จุดประสงค์ของสาย ENV คืออะไร? สำหรับฉัน - build-arg + ARG ก็เพียงพอแล้ว
Phil

3
ARG กำหนดตัวแปรที่จะใช้ภายใน dockerfile ในคำสั่งที่ตามมา ENV กำหนดตัวแปรสภาพแวดล้อมที่ส่งผ่านไปยังคอนเทนเนอร์
Herm

56

ดังนั้นคุณสามารถทำได้: cat Dockerfile | envsubst | docker build -t my-target -

จากนั้นให้ใช้ Dockerfile พร้อมสิ่งต่อไปนี้:

ENV MY_ENV_VAR $MY_ENV_VAR

ฉันเดาว่าอาจมีปัญหากับตัวละครพิเศษบางตัว แต่วิธีนี้ใช้ได้กับกรณีส่วนใหญ่เป็นอย่างน้อย


13
ดูเหมือนจะไม่ทำงานหากคุณต้องการเพิ่มไฟล์จากไดเรกทอรีที่มี Dockerfile
Tom Hennen

2
ทางออกที่ดีมาก! บน Mac คุณจะได้รับเป็นส่วนหนึ่งของenvsubst brew install gettextแต่เนื่องจากความขัดแย้งที่อาจเกิดขึ้นกับระบบการสร้าง BSD จึงเป็น "ถังเท่านั้น" และไม่มีการสร้าง symlnks อย่างไรก็ตามมีความปลอดภัยในการทำln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/เพื่อเพิ่มหนึ่งคำสั่งใน PATH ของคุณ (มันคือ libs ที่เป็นปัญหาจริงๆ) หรือคุณสามารถใช้มันใน/usr/local/Cellar/gettext/*/bin/envsubstที่ตั้งของมัน
Bruno Bronosky

1
เพื่อชี้แจงความคิดเห็นของ @ TomHennen ให้วางไฟล์ไปที่ Dockerfile docker build -โดยเฉพาะสิ่งที่ไม่ได้ผลเมื่อคุณอ้างอิงเส้นทางสัมพัทธ์จาก Dockerfile ของคุณโดยไม่คำนึงถึงการทดแทน env var
superEb

4
Re @ คิดเห็น TomHennen ของถ้าคุณไม่ต้องการที่จะใช้คำสั่งบริบทขึ้นเช่น COPY ใน Dockerfile ของคุณคุณก็สามารถเปลี่ยนเส้นทางการส่งออกของ envsubst ไปยังแฟ้มชั่วคราวและแล้วฟีดที่เป็นdocker buildแทน ตัวอย่าง: cat Dockerfile | envsubst > DockerfileWithEnvVarsจากนั้นdocker build -t my-target -f DockerfileWithEnvVars .จึงrm DockerfileWithEnvVars
snark

หรือคุณสามารถใช้ฟองน้ำจากแพ็คเกจเพิ่มเติมenvsubst < Dockerfile | sponge Dockerfile
ALex_hha

19

อีกทางเลือกหนึ่งที่ใช้envsubstโดยไม่สูญเสียความสามารถในการใช้คำสั่งเช่นCOPYหรือADDและโดยไม่ใช้ไฟล์ระดับกลางจะใช้การทดแทนกระบวนการของ Bash :

docker build -f <(envsubst < Dockerfile) -t my-target .

3
น่าเสียดายที่ดูเหมือนจะใช้งานไม่ได้ (Docker 17.09) ฉันได้รับข้อผิดพลาดunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Alexander Klimetschek

11

โหลดตัวแปรสภาพแวดล้อมจากไฟล์ที่คุณสร้างเมื่อรันไทม์

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF

... จากนั้นใน Dockerfile

ADD build /build
RUN /build/test.sh

ที่ test.sh โหลด MYVAR จาก env.sh

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile

4

หากคุณเพียงแค่ต้องการค้นหาและแทนที่ตัวแปรสภาพแวดล้อมทั้งหมด ($ ExampleEnvVar) ใน Dockerfile แล้วสร้างมันขึ้นมาสิ่งนี้จะทำงาน:

envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -


คำตอบที่ดีที่สุดที่นี่และจากนั้นก็สามารถทำได้: envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -ที่FROMบรรทัดใช้ตัวแปรสภาพแวดล้อม
mikequentel

-6

เพิ่ม-eคีย์สำหรับส่งตัวแปรสภาพแวดล้อมไปยังคอนเทนเนอร์ ตัวอย่าง:

$ MYSQLHOSTIP=$(sudo docker inspect -format="{{ .NetworkSettings.IPAddress }}" $MYSQL_CONRAINER_ID)
$ sudo docker run -e DBIP=$MYSQLHOSTIP -i -t myimage /bin/bash

root@87f235949a13:/# echo $DBIP
172.17.0.2

6
ดาเมียนกำลังมองหาการสร้างภาพ -e ทำงานร่วมกับคำสั่งเรียกใช้แทน
Andres Restrepo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.