Skip to content

1.06 Docker CMD vs ENTRYPOINT

Overview

CMD and ENTRYPOINT are Dockerfile instructions that define what runs when a container starts. Understanding the difference is essential for building flexible, reusable images.

Abstract

CMD sets a default command that is fully replaced if you pass arguments at runtime. ENTRYPOINT sets a fixed executable that always runs, with any runtime arguments appended to it. Combining both gives you a default with an override β€” the most flexible pattern.


Why It Matters in Production

Containers are not virtual machines. They exist to run one specific process β€” and when that process ends, the container exits. Getting CMD and ENTRYPOINT right means your images behave predictably whether run manually, in CI/CD pipelines, or orchestrated by Kubernetes.


Key Concepts

Instruction Behavior Runtime Override
CMD Sets the default command and/or parameters Completely replaced by anything passed after the image name
ENTRYPOINT Sets the fixed executable to run Appended to by runtime args; replaced only with --entrypoint flag
CMD + ENTRYPOINT CMD provides default args to ENTRYPOINT Runtime args replace CMD portion only; ENTRYPOINT stays fixed

Common Use Cases

  • CMD β€” Images where you want a sensible default but full flexibility to override (e.g. Ubuntu defaulting to bash)
  • ENTRYPOINT β€” Images designed as executables, where the program is fixed and only arguments vary (e.g. a custom sleep or backup tool)
  • ENTRYPOINT + CMD β€” Best of both: a fixed program with a configurable default argument that can still be overridden at runtime

How Containers Exit

A container only lives as long as its main process. When the process finishes or crashes, the container exits.

# Ubuntu exits immediately β€” bash finds no terminal and quits
docker run ubuntu

# Override the default command to keep the container alive for 5s
docker run ubuntu sleep 5

Example Configuration or Commands

Nginx and MySQL β€” CMD in real images

# Nginx Dockerfile (simplified)
CMD ["nginx"]

# MySQL Dockerfile (simplified)
ENTRYPOINT ["/entrypoint.sh"]
CMD ["mysqld"]

Ubuntu base image β€” CMD defaults to bash

FROM ubuntu:14.04
CMD ["bash"]

Custom sleeper image using CMD

FROM Ubuntu
CMD sleep 5
# Build the image
docker build -t ubuntu-sleeper .

# Run with default (sleeps 5s)
docker run ubuntu-sleeper

# Override CMD entirely β€” sleeps 10s instead
docker run ubuntu-sleeper sleep 10

CMD β€” shell form vs JSON array form

# Shell form (works, but avoid for ENTRYPOINT/CMD best practice)
CMD sleep 5

# JSON array form β€” CORRECT: executable and args are separate elements
CMD ["sleep", "5"]

# JSON array form β€” WRONG: do not combine executable and args as one string
# CMD ["sleep 5"]   ← this will fail

JSON Array Rule

Always use the JSON array format for CMD and ENTRYPOINT. The first element must be the executable. Never combine the command and its arguments into a single string element.

Custom sleeper image using ENTRYPOINT

FROM Ubuntu
ENTRYPOINT ["sleep"]
# The argument is appended to ENTRYPOINT β€” runs: sleep 10
docker run ubuntu-sleeper 10

# Running without an argument causes an error
docker run ubuntu-sleeper
# sleep: missing operand
# Try 'sleep --help' for more information.

Combining ENTRYPOINT with CMD for a default argument

FROM Ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]
# No argument passed β€” uses CMD default: sleep 5
docker run ubuntu-sleeper

# Argument passed β€” overrides CMD: sleep 10
docker run ubuntu-sleeper 10

Overriding ENTRYPOINT at runtime

# Replace the entrypoint with a different executable entirely
docker run --entrypoint sleep2.0 ubuntu-sleeper 10
# Command at startup: sleep2.0 10

CMD vs ENTRYPOINT β€” Behaviour Summary

Scenario Dockerfile docker run command Command at startup
CMD only, no runtime arg CMD sleep 5 docker run ubuntu-sleeper sleep 5
CMD only, runtime arg CMD sleep 5 docker run ubuntu-sleeper sleep 10 sleep 10
ENTRYPOINT only, with arg ENTRYPOINT ["sleep"] docker run ubuntu-sleeper 10 sleep 10
ENTRYPOINT only, no arg ENTRYPOINT ["sleep"] docker run ubuntu-sleeper sleep β†’ error
ENTRYPOINT + CMD, no arg ENTRYPOINT ["sleep"] CMD ["5"] docker run ubuntu-sleeper sleep 5
ENTRYPOINT + CMD, with arg ENTRYPOINT ["sleep"] CMD ["5"] docker run ubuntu-sleeper 10 sleep 10
Override entrypoint ENTRYPOINT ["sleep"] docker run --entrypoint sleep2.0 ubuntu-sleeper 10 sleep2.0 10

Best Practices

Best Practices

  • Always write CMD and ENTRYPOINT in JSON array format β€” shell form has subtle differences in signal handling and variable expansion
  • Use ENTRYPOINT + CMD when your image is a purpose-built tool: ENTRYPOINT is the command, CMD is the safe default argument
  • Use CMD only when the image is a general base and the user should fully control what runs
  • Keep the entrypoint executable simple β€” use a wrapper shell script (entrypoint.sh) for complex init logic
  • Document all supported runtime arguments in your image's README

Security Best Practices

Security

  • Avoid running containers as root β€” set a non-root USER in your Dockerfile above the ENTRYPOINT/CMD line
  • Do not embed secrets or credentials in CMD or ENTRYPOINT β€” they are visible in docker inspect and image layers
  • Prefer specific executable paths (e.g. /usr/bin/sleep) over relying on PATH resolution inside containers
  • If using a shell wrapper as your entrypoint, validate and sanitize any arguments it processes

Do and Don't

βœ… Do ❌ Don't
Use JSON array format: CMD ["sleep", "5"] Use shell string in arrays: CMD ["sleep 5"]
Use ENTRYPOINT + CMD for default-with-override pattern Use CMD alone when the executable should always be fixed
Override ENTRYPOINT with --entrypoint when needed Assume runtime args replace the entrypoint β€” they don't
Use a wrapper entrypoint.sh for complex init logic Put multi-step init logic directly in ENTRYPOINT
Test both docker run image and docker run image arg Ship an image without verifying the no-arg case

Common Mistakes

Common Mistakes

  • Writing CMD ["sleep 5"] β€” the command and argument must be separate array elements: CMD ["sleep", "5"]
  • Expecting ENTRYPOINT to be replaced by runtime args β€” only CMD is replaced; use --entrypoint to override ENTRYPOINT
  • Forgetting that CMD is completely discarded when any argument is passed at runtime β€” even if you only wanted to append
  • Using shell form (CMD sleep 5) with ENTRYPOINT β€” the JSON format is required for CMD to act as default args to ENTRYPOINT
  • Not handling the missing-argument case when using ENTRYPOINT alone β€” always pair it with a CMD default

Troubleshooting

Container exits immediately

# Check what command the container ran
docker ps -a
docker logs <container_id>

# Inspect the image's configured entrypoint and cmd
docker inspect <image_name> | grep -A5 '"Cmd"'
docker inspect <image_name> | grep -A5 '"Entrypoint"'

sleep: missing operand error

The container used ENTRYPOINT ["sleep"] with no CMD default and no argument was passed at runtime. Fix:

# Add a default argument
ENTRYPOINT ["sleep"]
CMD ["5"]

Overriding the entrypoint for debugging

# Drop into a shell instead of running the default entrypoint
docker run --entrypoint /bin/bash -it ubuntu-sleeper

Quick Recap

  • Containers run one process; when that process ends, the container exits
  • CMD β€” default command, fully replaced by runtime arguments
  • ENTRYPOINT β€” fixed executable, runtime arguments are appended
  • Use ENTRYPOINT ["exec"] + CMD ["default-arg"] for the most flexible pattern
  • Always use JSON array format for both instructions
  • Override ENTRYPOINT at runtime with docker run --entrypoint <new-cmd>

Interview / Revision Notes

  • Q: What is the difference between CMD and ENTRYPOINT? CMD sets a default command that is fully replaced by runtime args. ENTRYPOINT sets a fixed executable; runtime args are appended to it.

  • Q: How do you provide a default argument that can still be overridden? Combine both: ENTRYPOINT ["sleep"] and CMD ["5"]. Runtime arg overrides CMD; ENTRYPOINT stays fixed.

  • Q: How do you override ENTRYPOINT at runtime? docker run --entrypoint <new-executable> image [args]

  • Q: Why must CMD and ENTRYPOINT use JSON array format? Shell form doesn't support CMD acting as default args to ENTRYPOINT. JSON format also handles signals correctly.

  • Q: Why does docker run ubuntu exit immediately? Ubuntu's default CMD is bash. Docker doesn't attach a terminal by default, so bash exits, and with it, the container.