Dockerfile - ตั้งค่า ENV เป็นผลลัพธ์ของคำสั่ง


93

เป็นไปได้หรือไม่ที่จะตั้งค่าตัวแปร docker ENV ให้เป็นผลลัพธ์ของคำสั่ง ชอบ:

ENV MY_VAR whoami

ฉันต้องการให้ MY_VAR ได้รับค่า "root" หรืออะไรก็ตามที่ส่งคืน whoami


คำตอบ:


21

นอกเหนือจากคำตอบ DarkSideF

คุณควรทราบว่าแต่ละบรรทัด / คำสั่งใน Dockerfile ถูกรันในคอนเทนเนอร์อื่น

คุณสามารถทำสิ่งนี้:

RUN export bleah=$(hostname -f);echo $bleah;

สิ่งนี้ทำงานในคอนเทนเนอร์เดียว


15
เพียงชี้แจง - $bleahคือไม่สามารถใช้ได้ทุกที่นอกคำสั่งทำงานนี้ไม่ได้ในบรรทัดถัดไปใน dockerfile เดียวกันให้อยู่คนเดียวในภาพอื่นมันตามออก คุณลักษณะที่ขาดหายไปอย่างชัดเจนจากนักเทียบท่าที่นี่ดูเหมือนว่าการเขียนและอ่านจากไฟล์เป็นวิธีเดียวในการจัดเก็บตัวแปร (ไดนามิก) ในรูปภาพและส่งต่อระหว่างรูปภาพซึ่งดูเหมือนจะแฮ็กสุด ๆ
davnicwil

17

ฉันมีปัญหาเดียวกันและพบวิธีตั้งค่าตัวแปรสภาพแวดล้อมอันเป็นผลมาจากฟังก์ชันโดยใช้คำสั่ง RUN ใน dockerfile

ตัวอย่างเช่นฉันต้องตั้งค่า SECRET_KEY_BASE สำหรับแอพ Rails เพียงครั้งเดียวโดยไม่ต้องเปลี่ยนแปลงเหมือนตอนที่ฉันเรียกใช้:

docker run  -e SECRET_KEY_BASE="$(openssl rand -hex 64)"

ฉันเขียนลงในสตริง Dockerfile แทนเช่น:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

และตัวแปร env ของฉันพร้อมใช้งานจากรูทแม้หลังจากเข้าสู่ระบบ bash หรืออาจจะ

RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'

จากนั้นตัวแปรที่มีอยู่ในคำสั่ง CMD และ ENTRYPOINT

นักเทียบท่าแคชเป็นเลเยอร์และเปลี่ยนเฉพาะเมื่อคุณเปลี่ยนสตริงก่อนหน้านั้น

คุณยังสามารถลองวิธีต่างๆในการตั้งค่าตัวแปรสภาพแวดล้อม


/etc/profile.d/docker_init.sh ยังคงเป็นสิ่งอยู่หรือไม่ คำตอบนี้เป็นการพูดถึงเพียงเรื่องเดียวที่ฉันสามารถหาได้จาก Google และมันไม่ได้ผลสำหรับฉัน อาจเป็นส่วนหนึ่งของเครื่องมือดำเนินการเทียบท่าในปี 2559 ที่ไม่เป็นปัจจุบันอีกต่อไปหรือไม่?
SigmaX

1
@SigmaX ไม่ใช่นักเทียบท่า แต่เป็นสิ่งที่Linuxมากกว่า *.shไฟล์ใด ๆ ที่อยู่ภายใน/etc/profile.d/จะถูกใช้เพื่อเติมข้อมูลในสภาพแวดล้อม
Madacol


7

คำตอบนี้ตอบสนองต่อการ@DarkSideF ,

วิธีการที่เขาเสนอมีดังต่อไปนี้ในDockerfile:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

( เพิ่มการส่งออกใน/etc/bash.bashrc )

เป็นสิ่งที่ดี แต่ตัวแปรสภาพแวดล้อมจะพร้อมใช้งานสำหรับกระบวนการ/bin/bashเท่านั้นและหากคุณพยายามเรียกใช้แอปพลิเคชันนักเทียบท่าของคุณตัวอย่างเช่นแอปพลิเคชัน Node.js /etc/bash.bashrcจะถูกละเว้นโดยสิ้นเชิงและแอปพลิเคชันของคุณจะไม่มีเงื่อนงำใด ๆSECRET_KEY_BASEเมื่อพยายาม process.env.SECRET_KEY_BASEในการเข้าถึง

นั่นคือเหตุผลว่าทำไมENVคีย์เวิร์ดจึงเป็นสิ่งที่ทุกคนพยายามใช้กับคำสั่งแบบไดนามิกเพราะทุกครั้งที่คุณเรียกใช้คอนเทนเนอร์หรือใช้execคำสั่ง Docker จะตรวจสอบENVและไพพ์ทุกค่าในกระบวนการที่รันอยู่ (คล้ายกับ-e)

วิธีแก้ปัญหาอย่างหนึ่งคือการใช้ Wrapper (ให้เครดิต@duglinในปัญหา github นี้ ) มีไฟล์ Wrapper (เช่นenvwrapper) ในรูทโปรเจ็กต์ของคุณซึ่งประกอบด้วย:

#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*

จากนั้นในDockerfile:

...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp

4

นอกเหนือจากคำตอบของ @ DarkSideF แล้วหากคุณต้องการใช้ผลลัพธ์ของคำสั่งก่อนหน้านี้ซ้ำในDockerfile ระหว่างกระบวนการสร้างคุณสามารถใช้วิธีแก้ปัญหาต่อไปนี้:

  1. เรียกใช้คำสั่งเก็บผลลัพธ์ในไฟล์
  2. ใช้การแทนที่คำสั่งเพื่อรับผลลัพธ์ก่อนหน้าจากไฟล์นั้นไปเป็นคำสั่งอื่น

ตัวอย่างเช่น :

RUN echo "bla" > ./result
RUN echo $(cat ./result)

สำหรับสิ่งที่สะอาดกว่าคุณสามารถใช้ส่วนสำคัญต่อไปนี้ซึ่งมี CLI ขนาดเล็กที่เรียกว่าenvstore.py:

RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)

หรือคุณสามารถใช้ไลบรารีpython-dotenvซึ่งมี CLI ที่คล้ายกัน


2

ไม่แน่ใจว่านี่คือสิ่งที่คุณกำลังมองหาหรือไม่ แต่เพื่อที่จะฉีด ENV vars หรือ ARGS ลงใน. Dockerfile ของคุณสร้างรูปแบบนี้ได้

ใน my_build.sh ของคุณ:

echo getting version of osbase image to build from
OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')

echo building docker
docker build -f \
--build-arg ARTIFACT_TAG=$OSBASE \
PATH_TO_MY.Dockerfile \
-t my_artifact_home_url/bucketname:$TAG .

สำหรับการรับ ARG ในไฟล์. Dockerfile ของคุณข้อมูลโค้ดอาจมีลักษณะดังนี้:

FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}

อีกทางเลือกหนึ่งสำหรับการรับ ENV ใน. Dockerfile ของคุณตัวอย่างข้อมูลอาจมีลักษณะดังนี้:

FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}

แนวคิดคือคุณเรียกใช้เชลล์สคริปต์และเรียกว่า.

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