Inside my Dockerfile:
ENV PROJECTNAME mytestwebsite
CMD ["django-admin", "startproject", "$PROJECTNAME"]
Error:
CommandError: '$PROJECTNAME' is not a valid project name
What is the quickest workaround here? Does Docker have any plan to "fix" or introduce this functionality in later versions of Docker?
NOTE: If I remove the CMD line from the Docker file and then run the Docker container, I am able to manually run Django-admin startproject $PROJECTNAME from inside the container and it will create the project...
When you use an execution list, as in...
CMD ["django-admin", "startproject", "$PROJECTNAME"]
...then Docker will execute the given command directly, without involving a shell. Since there is no shell involved, that means:
- No variable expansion
- No wildcard expansion
- No i/o redirection with
>
, <
, |
, etc
- No multiple commands via
command1; command2
- And so forth.
If you want your CMD
to expand variables, you need to arrange for a shell. You can do that like this:
CMD ["sh", "-c", "django-admin startproject $PROJECTNAME"]
Or you can use a simple string instead of an execution list, which gets you a result largely identical to the previous example:
CMD django-admin startproject $PROJECTNAME
If you want to use the value at runtime, set the ENV
value in the Dockerfile
. If you want to use it at build-time, then you should use ARG
.
Example :
ARG value
ENV envValue=$value
CMD ["sh", "-c", "java -jar ${envValue}.jar"]
Pass the value in the build command:
docker build -t tagName --build-arg value="jarName"
Lets say you want to start a java process inside a container:
Example Dockerfile excerpt:
ENV JAVA_OPTS -XX +UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm
...
ENTRYPOINT ["/sbin/tini", "--", "entrypoint.sh"]
CMD ["java", "${JAVA_OPTS}", "-myargument=true"]
Example entrypoint.sh excerpt:
#!/bin/sh
...
echo "*** Startup $0 suceeded now starting service using eval to expand CMD variables ***"
exec su-exec mytechuser $(eval echo "$@")
Inspired on above, I did this:
#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 && \
.....