Jak mogę użyć zmiennej wewnątrz Dockerfile CMD?

111

W moim pliku Dockerfile:

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

Błąd:

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

Jakie jest najszybsze obejście tego problemu? Czy Docker planuje „naprawić” lub wprowadzić tę funkcjonalność w nowszych wersjach Dockera?

UWAGA: Jeśli usunę linię CMD z pliku Docker, a następnie uruchomię kontener Docker, będę mógł ręcznie uruchomić Django-admin startproject $ PROJECTNAME z wnętrza kontenera i utworzy projekt ...

david
źródło
1
Jak i kiedy definiujesz $PROJECTNAME?
Piotr Wittchen
Na początku mojego Dockerfile przy użyciu ENV. Zapomniałem również wspomnieć, że jeśli usunę linię CMD z pliku Dockerfile, a następnie uruchomię kontener, z wnętrza kontenera mogę uruchomić to polecenie i utworzy projekt (co oznacza, że ​​zmienna ENV jest ważna).
david
Jaki typ zmiennej masz na myśli: zmienną dockerfile lub zmienną środowiskową (jak w środowisku wykonawczym systemu)?
emix

Odpowiedzi:

170

Kiedy używasz listy wykonania, jak w ...

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

... wtedy Docker wykona dane polecenie bezpośrednio , bez angażowania powłoki. Ponieważ nie ma tu powłoki, oznacza to:

  • Brak rozszerzania zmiennych
  • Brak rozszerzenia z użyciem symboli wieloznacznych
  • No I / O przekierowania z >, <, |, etc
  • Brak wielu poleceń za pośrednictwem command1; command2
  • I tak dalej.

Jeśli chcesz CMDrozwijać zmienne, musisz zorganizować powłokę. Możesz to zrobić w ten sposób:

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

Lub możesz użyć prostego ciągu zamiast listy wykonań, co daje wynik w dużej mierze identyczny z poprzednim przykładem:

CMD django-admin startproject $PROJECTNAME
larsks
źródło
2
Więcej do czytania w narzędziu do śledzenia problemów Dockera
jannis
20

Jeśli chcesz użyć wartości w czasie wykonywania, ustaw ENVwartość w Dockerfile. Jeśli chcesz go używać podczas kompilacji, powinieneś użyć ARG.

Przykład:

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

Przekaż wartość w poleceniu kompilacji:

docker build -t tagName --build-arg value="jarName"
rex roy
źródło
11

Powiedzmy, że chcesz rozpocząć proces Java w kontenerze:

Przykładowy fragment pliku Dockerfile:

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

Przykładowy fragment entrypoint.sh:

#!/bin/sh 
... 
echo "*** Startup $0 suceeded now starting service using eval to expand CMD variables ***"
exec su-exec mytechuser $(eval echo "$@")
Flavio Aiello
źródło
0

Zainspirowany powyżej, zrobiłem to:

#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 && \ 
       .....
csomakk
źródło