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
CMD
Learn 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
ENTRYPOINT
andCMD
What will be the output of
docker run --rm -it defaults-example:latest $USER
and why?
Solution
Hello, <your user name>! docker@2a99ffabb512:~/data$
$USER
is evaluated and then overrides the defaultCMD
to be passed toentrypoint.sh
Key Points
CMD
provide defaults for an executing container
CMD
can provide options forENTRYPOINT
ENTRYPOINT
allows you to configure commands that will always run for an executing container