X
Popular Searches

The Difference Between CMD and ENTRYPOINT in Docker Images

Illustration showing the Docker logo

The CMD and ENTRYPOINT instructions are two commonly confused Dockerfile directives. Both have a role in determining the command which will run when the container starts.

The CMD and ENTRYPOINT can be overridden individually within each image. Effective use of these directives makes your container easier to use by shortening the length of commands you supply.

What Is The Entrypoint?

We’ll look at ENTRYPOINT first as it’s processed before CMD when starting a new container. The image’s entrypoint defines the process which will be run when the container starts.

Docker defaults the entrypoint to /bin/sh -c. This means you’ll end up in a shell session when you start the container. For many containers, it’s more desirable to have a different process launch by default. You want headless services to start their workload straightaway.

Setting the ENTRYPOINT directive in a Dockerfile instructs Docker to run a specific command when the container starts. It will become the foreground process, instead of the default shell session.

ENTRYPOINT ["date"]
Advertisement

A container created with this Dockerfile will run the date command. As date is not a long-living foreground process, the container will exit immediately afterwards.

Entrypoints must be executable binaries or scripts. Your container won’t start if you specify an invalid entrypoint. If you’re using a custom script, make sure it’s got the executable bit set. You can add execute permissions using chmod +x my-script.sh.

Adding The Command (CMD)

The CMD instruction is something of a misnomer. It provides default arguments for the command defined by ENTRYPOINT.

ENTRYPOINT ["date"]
CMD ["+%A"]

This example results in the container running date +%A. The +%A argument to date displays the current day of the week (e.g. Monday).

CMD is designed to be overridden. docker run lets you specify a different command for an individual container instance:

docker run my-image +%B

The default CMD will be overridden with +%B, causing the container to display the name of the current month. This works because the image’s entrypoint remains intact. The CMD is always appended to the ENTRYPOINT, so the final command becomes date +%B.

Advertisement

You should use ENTRYPOINT to define your container’s primary executable. Use CMD to define default arguments for that executable. It will be overridden when the container is run with different arguments.

Entrypoint Overrides

You can force Docker to start an image using a custom entrypoint. Pass the --entrypoint flag to docker run:

docker run --entrypoint /bin/sh my-image

The entrypoint defined in the container’s image will be ignored in favour of the command you’ve specified. In our example, a shell session will be started, instead of the date command.

Overriding entrypoints should be a rare occurrence. It can go against the image author’s intentions. Setting a custom entrypoint can be useful though, particularly when debugging. If a container’s misbehaving, overriding its entrypoint can grant you shell access you couldn’t otherwise obtain.

Which One To Use?

If you’re an image author, you should use ENTRYPOINT when defining what your container will run. If you want to provide default arguments, but expect the user to override them, include CMD too.

As an image user, you can normally stick to overriding CMD. docker run has transparent support for command overrides. Any arguments provided after the image name will be interpreted as the CMD string for the container.

Entrypoint Modes: Shell or Exec

Docker actually supports two different forms of ENTRYPOINT: exec mode and shell mode. Exec mode is characterised by the use of an array construct to specify parameters. In shell mode, the command is specified as one string.

# exec mode
ENTRYPOINT ["binary", "--param", "--another-param"]

# shell mode
ENTRYPOINT binary --param --another-param
Advertisement

Using shell mode causes your binary to be executed as a subprocess of /bin/sh -c. This gives your entrypoint access to environment variables defined by the shell.

Shell mode has tradeoffs though. You can’t use CMD so users won’t be able to issue overrides. Arguments given to docker run will be ignored; your container will always use the entrypoint as-is.

Because your binary runs within a shell, Docker lifecycle commands like docker stop may work erratically or not at all. Docker will signal the shell to stop, instead of the process within. You can launch your process with exec to avoid this.

ENTRYPOINT exec binary --param --another-param

Benefits of Docker’s Entrypoint Approach

Separating the entrypoint from its arguments helps you hide complexity in your containers. This is most beneficial when you’re creating utility containers to encapsulate CLI programs.

Set your CLI’s binary as the image’s entrypoint. This lets users interact without repeating the binary name in each command.

Consider if we packaged the above Dockerfile as date:latest:

# default entrypoint (/bin/sh -c)
docker run date:latest date +%A

# with `date` as the entrypoint
docker run date:latest +%A`
Advertisement

Setting a custom entrypoint shortens commands and reduces repetition. The container becomes more specialised by invoking date automatically. This creates a friendlier interface for your users.

Summary

Docker’s ENTRYPOINT and CMD instructions are a frequent source of confusion. Their naming masks their intended purposes.

Use ENTRYPOINT to set the “command” that will execute when new containers start. You can define default arguments using CMD. ENTRYPOINT and CMD are combined together to produce the container’s final command string.

When you use docker run, Docker replaces the image’s default CMD with the arguments you specify. If you need to override an image’s entrypoint, use the --entrypoint flag.

James Walker James Walker
James Walker is a contributor to CloudSavvy IT. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes. Read Full Bio »

The above article may contain affiliate links, which help support CloudSavvy IT.