Làm cách nào để sử dụng một biến bên trong Dockerfile CMD?


104

Bên trong Dockerfile của tôi:

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

Lỗi:

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

Cách giải quyết nhanh nhất ở đây là gì? Docker có kế hoạch nào để "sửa chữa" hoặc giới thiệu chức năng này trong các phiên bản sau của Docker không?

LƯU Ý: Nếu tôi xóa dòng CMD khỏi tệp Docker rồi chạy vùng chứa Docker, thì tôi có thể chạy Django-admin startproject $ PROJECTNAME theo cách thủ công từ bên trong vùng chứa và nó sẽ tạo dự án ...


1
Bạn xác định như thế nào và khi $PROJECTNAMEnào?
Piotr Wittchen

Ở đầu Dockerfile của tôi bằng cách sử dụng ENV. Ngoài ra, tôi quên đề cập rằng nếu tôi xóa dòng CMD khỏi Dockerfile và sau đó chạy vùng chứa, thì từ bên trong vùng chứa, tôi có thể chạy lệnh này và nó sẽ tạo dự án (nghĩa là biến ENV hợp lệ).
david

Ý bạn là loại biến nào: biến dockerfile hay biến môi trường (như trong thời gian chạy hệ thống của bạn)?
emix

Câu trả lời:


164

Khi bạn sử dụng danh sách thực thi, như trong ...

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

... thì Docker sẽ thực hiện lệnh đã cho một cách trực tiếp mà không liên quan đến trình bao. Vì không có shell liên quan, điều đó có nghĩa là:

  • Không có mở rộng biến
  • Không có mở rộng ký tự đại diện
  • Không i / o chuyển hướng với >, <, |, vv
  • Không có nhiều lệnh qua command1; command2
  • Và kể từ đó trở đi.

Nếu bạn muốn các CMDbiến mở rộng của mình , bạn cần phải sắp xếp cho một trình bao. Bạn có thể làm như thế này:

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

Hoặc bạn có thể sử dụng một chuỗi đơn giản thay vì một danh sách thực thi, điều này sẽ mang lại cho bạn kết quả phần lớn giống với ví dụ trước:

CMD django-admin startproject $PROJECTNAME

2
Một số bài đọc khác trong trình theo dõi vấn đề của Docker: github.com/docker/docker/issues/5509
jannis

@larsks một chuỗi đơn giản là TUYỆT VỜI
abdoutelb

Bạn đã cứu ngày của tôi!
Supratim Roy

18

Nếu bạn muốn sử dụng giá trị trong thời gian chạy, hãy đặt ENVgiá trị trong Dockerfile. Nếu bạn muốn sử dụng nó tại thời điểm xây dựng, thì bạn nên sử dụng ARG.

Thí dụ :

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

Truyền giá trị vào lệnh xây dựng:

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

10

Giả sử bạn muốn bắt đầu quy trình java bên trong vùng chứa:

Đoạn trích Dockerfile mẫu:

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

Đoạn trích entrypoint.sh mẫu:

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

0

Lấy cảm hứng từ trên, tôi đã làm điều này:

#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 && \ 
       .....
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.