Bonus: Using CMD and ENTRYPOINT in Dockerfiles
Overview
Teaching: 0 min
Exercises: 0 minQuestions
How are default commands set in Dockerfiles?
Objectives
Learn how and when to use
CMDLearn how and when to use
ENTRYPOINT
So far everytime we’ve run the Docker containers we’ve typed
docker run --rm -it <IMAGE>:<TAG> <command>
like
docker run --rm -it python:3.7 /bin/bash
Running this dumps us into a Bash session
printenv | grep SHELL
SHELL=/bin/bash
However, if no /bin/bash is given then you are placed inside the Python 3.7 REPL.
docker run --rm -it python:3.7
Python 3.7.4 (default, Jul 13 2019, 14:04:11)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
These are very different behaviors, so let’s understand what is happening.
The Python 3.7 Docker image has a default command that runs when the container is executed,
which is specified in the Dockerfile with CMD.
Create a file named Dockerfile.defaults
touch Dockerfile.defaults
# Dockerfile.defaults
# Make the base image configurable
ARG BASE_IMAGE=python:3.7
FROM ${BASE_IMAGE}
USER root
RUN apt-get -qq -y update && \
apt-get -qq -y upgrade && \
apt-get -y autoclean && \
apt-get -y autoremove && \
rm -rf /var/lib/apt-get/lists/*
# Create user "docker"
RUN useradd -m docker && \
cp /root/.bashrc /home/docker/ && \
mkdir /home/docker/data && \
chown -R --from=root docker /home/docker
ENV HOME /home/docker
WORKDIR ${HOME}/data
USER docker
CMD ["/bin/bash"]
Now build the dockerfile, specifying its name with the -f argument since docker will otherwise look for a file named Dockerfile by default.
docker build -f Dockerfile.defaults -t defaults-example:latest .
Now running
docker run --rm -it defaults-example:latest
again drops you into a Bash shell as specified by CMD.
As has already been seen, CMD can be overridden by giving a command after the image
docker run --rm -it defaults-example:latest python3
The ENTRYPOINT builder command allows to define a command or
commands that are always run at the “entry” to the Docker container.
If an ENTRYPOINT has been defined then CMD provides optional inputs to the ENTRYPOINT.
# entrypoint.sh
#!/usr/bin/env bash
set -e
function main() {
if [[ $# -eq 0 ]]; then
printf "\nHello, World!\n"
else
printf "\nHello, %s!\n" "${1}"
fi
}
main "$@"
/bin/bash
# Dockerfile.defaults
# Make the base image configurable
ARG BASE_IMAGE=python:3.7
FROM ${BASE_IMAGE}
USER root
RUN apt-get -qq -y update && \
apt-get -qq -y upgrade && \
apt-get -y autoclean && \
apt-get -y autoremove && \
rm -rf /var/lib/apt-get/lists/*
# Create user "docker"
RUN useradd -m docker && \
cp /root/.bashrc /home/docker/ && \
mkdir /home/docker/data && \
chown -R --from=root docker /home/docker
ENV HOME /home/docker
WORKDIR ${HOME}/data
USER docker
COPY entrypoint.sh $HOME/entrypoint.sh
ENTRYPOINT ["/bin/bash", "/home/docker/entrypoint.sh"]
CMD ["Docker"]
docker build -f Dockerfile.defaults -t defaults-example:latest --compress .
So now
docker run --rm -it defaults-example:latest
Hello, Docker!
docker@2a99ffabb512:~/data$
Applied
ENTRYPOINTandCMDWhat will be the output of
docker run --rm -it defaults-example:latest $USERand why?
Solution
Hello, <your user name>! docker@2a99ffabb512:~/data$
$USERis evaluated and then overrides the defaultCMDto be passed toentrypoint.sh
Key Points
CMDprovide defaults for an executing container
CMDcan provide options forENTRYPOINT
ENTRYPOINTallows you to configure commands that will always run for an executing container