ฉันจะใช้ตัวแปรภายใน Dockerfile CMD ได้อย่างไร


112

ภายใน Dockerfile ของฉัน:

ENV PROJECTNAME mytestwebsite
CMD ["django-admin", "startproject", "$PROJECTNAME"]

ข้อผิดพลาด:

CommandError: '$PROJECTNAME' is not a valid project name

วิธีแก้ปัญหาที่เร็วที่สุดที่นี่คืออะไร? Docker มีแผนที่จะ "แก้ไข" หรือแนะนำฟังก์ชันนี้ใน Docker เวอร์ชันที่ใหม่กว่าหรือไม่

หมายเหตุ: ถ้าฉันลบบรรทัด CMD ออกจากไฟล์ Docker แล้วเรียกใช้คอนเทนเนอร์ Docker ฉันสามารถเรียกใช้ Django-admin startproject $ PROJECTNAME ด้วยตนเองจากภายในคอนเทนเนอร์และมันจะสร้างโครงการ ...


1
คุณกำหนด$PROJECTNAMEอย่างไรและเมื่อไหร่?
Piotr Wittchen

ที่จุดเริ่มต้นของ Dockerfile ของฉันโดยใช้ ENV นอกจากนี้ฉันลืมที่จะพูดถึงว่าถ้าฉันลบบรรทัด CMD ออกจาก Dockerfile แล้วเรียกใช้คอนเทนเนอร์จากภายในคอนเทนเนอร์ฉันสามารถเรียกใช้คำสั่งนี้และจะสร้างโปรเจ็กต์ (หมายความว่าตัวแปร ENV นั้นถูกต้อง)
david

คุณหมายถึงตัวแปรประเภทใด: ตัวแปร dockerfile หรือตัวแปรสภาพแวดล้อม (เช่นเดียวกับรันไทม์ระบบของคุณ)
emix

คำตอบ:


171

เมื่อคุณใช้รายการการดำเนินการดังใน ...

CMD ["django-admin", "startproject", "$PROJECTNAME"]

... จากนั้น Docker จะดำเนินการคำสั่งที่กำหนดโดยตรงโดยไม่ต้องเกี่ยวข้องกับเชลล์ เนื่องจากไม่มีเปลือกที่เกี่ยวข้องนั่นหมายความว่า:

  • ไม่มีการขยายตัวแปร
  • ไม่มีการขยายสัญลักษณ์แทน
  • ไม่มี I / O เปลี่ยนเส้นทางด้วย>, <, |ฯลฯ
  • ไม่มีคำสั่งหลายคำสั่งผ่าน command1; command2
  • และอื่น ๆ

หากคุณต้องการCMDขยายตัวแปรคุณต้องจัดเรียงเชลล์ คุณสามารถทำได้ดังนี้:

CMD ["sh", "-c", "django-admin startproject $PROJECTNAME"]

หรือคุณสามารถใช้สตริงธรรมดาแทนรายการการดำเนินการซึ่งจะทำให้คุณได้ผลลัพธ์ที่เหมือนกับตัวอย่างก่อนหน้านี้:

CMD django-admin startproject $PROJECTNAME

2
อ่านเพิ่มเติมในเครื่องมือติดตามปัญหาของ Docker: github.com/docker/docker/issues/5509
59

21

หากคุณต้องการใช้ค่าในรันไทม์ให้ตั้งENVค่าในไฟล์Dockerfile. ARGหากคุณต้องการที่จะใช้ที่สร้างเวลาแล้วที่คุณควรใช้

ตัวอย่าง:

ARG value
ENV envValue=$value
CMD ["sh", "-c", "java -jar ${envValue}.jar"]

ส่งผ่านค่าในคำสั่ง build:

docker build -t tagName --build-arg value="jarName"

12

สมมติว่าคุณต้องการเริ่มกระบวนการ java ภายในคอนเทนเนอร์:

ตัวอย่างที่ตัดตอนมาของ Dockerfile:

ENV JAVA_OPTS -XX +UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm 
... 
ENTRYPOINT ["/sbin/tini", "--", "entrypoint.sh"] 
CMD ["java", "${JAVA_OPTS}", "-myargument=true"]

ตัวอย่างข้อความที่ตัดตอนมาจาก entrypoint.sh:

#!/bin/sh 
... 
echo "*** Startup $0 suceeded now starting service using eval to expand CMD variables ***"
exec su-exec mytechuser $(eval echo "$@")

0

แรงบันดาลใจจากด้านบนฉันทำสิ่งนี้:

#snapshot by default. 1 is release.
ENV isTagAndRelease=0

CMD     echo is_tag: ${isTagAndRelease} && \
        if [ ${isTagAndRelease} -eq 1 ]; then echo "release build"; mvn -B release:clean release:prepare release:perform; fi && \
        if [ ${isTagAndRelease} -ne 1 ]; then echo "snapshot build"; mvn clean install; fi && \ 
       .....
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.