Docker
Base Images
Dockerfile
CMD Instruction
Container Customization

Changing the default command of base docker images

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Changing a base image's default command is easy once you separate Docker's startup rules into the right pieces. Most confusion comes from mixing up CMD and ENTRYPOINT, or from changing one when the other is actually controlling the container's process.

Know What the Base Image Defines

Docker images can define startup behavior with two instructions:

  • 'CMD, which supplies a default command or default arguments'
  • 'ENTRYPOINT, which defines the executable that should run'

If a parent image only defines CMD, a child image can replace it with a new CMD. If the parent image defines ENTRYPOINT, changing CMD may only change the arguments passed to that entrypoint.

The quickest way to stop guessing is to inspect the parent image before writing your Dockerfile.

bash
docker image inspect python:3.12-slim \
  --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'

That output tells you whether the image starts with an executable, default arguments, or both.

Override CMD in a Child Image

If the parent image uses CMD for its default behavior, the child image only needs to define a new CMD. The last CMD in the Dockerfile wins.

dockerfile
1FROM python:3.12-slim
2
3WORKDIR /app
4COPY app.py .
5
6CMD ["python", "app.py"]

This permanently changes the default process for containers built from the child image. When someone runs the image without extra arguments, Docker executes python app.py.

Use exec-form JSON syntax rather than shell form. It avoids an extra shell process and makes signal handling more predictable, which matters if the container is managed by Compose, Kubernetes, or a process supervisor.

Understand How ENTRYPOINT Changes the Meaning

If the base image defines an ENTRYPOINT, then CMD acts more like default arguments. For example, a base image may define an executable and expect child images to provide the flags.

dockerfile
1FROM some-image
2
3ENTRYPOINT ["my-server"]
4CMD ["--port", "8080"]

This container starts as my-server --port 8080. If the base image already had an entrypoint that you do not want, you must override ENTRYPOINT, not only CMD.

dockerfile
1FROM some-image
2
3ENTRYPOINT ["python", "worker.py"]
4CMD ["--queue", "default"]

Now the original entrypoint is gone, and your image starts python worker.py --queue default.

Override at Runtime When the Change Is Temporary

Sometimes you do not need a new image at all. If the change is only for debugging or a one-off command, override it when the container starts.

bash
docker run --rm python:3.12-slim python -c "print('hello from container')"

That replaces the image's CMD for this run only. If you also need to replace the image's entrypoint, use the --entrypoint flag:

bash
docker run --rm --entrypoint /bin/sh nginx:alpine -c "echo debug shell"

Runtime overrides are useful when:

  • you want a quick test without rebuilding
  • you need an interactive shell in a container
  • the image is fine, but one deployment needs a different startup command

Build-time overrides are better when the new command should be the long-term default.

Design Clear Image Behavior

A good image should make its startup contract obvious. If the image is tightly focused on one service, define ENTRYPOINT explicitly and use CMD for a few default arguments. If the image is meant to be reused in many ways, keep it flexible and avoid a complicated entrypoint wrapper unless you really need one.

Here is a common Node example:

dockerfile
1FROM node:20-alpine
2
3WORKDIR /app
4COPY package*.json ./
5RUN npm ci --omit=dev
6COPY . .
7
8ENTRYPOINT ["node", "server.js"]
9CMD ["--port", "3000"]

The executable is fixed, but the default port can still be overridden at runtime by supplying alternate arguments.

Test the Effective Command

After building the child image, inspect or run it instead of assuming the override worked.

bash
1docker build -t my-app .
2docker image inspect my-app \
3  --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'
4docker run --rm my-app

This is the fastest way to catch mistakes such as changing CMD when the base image still forces an unexpected ENTRYPOINT.

Common Pitfalls

  • Overriding CMD when the parent image's ENTRYPOINT still controls execution.
  • Using shell form commands and then debugging quoting or signal-handling issues.
  • Rebuilding a child image for a temporary change that could have been a runtime override.
  • Forgetting that only the last CMD or ENTRYPOINT in a Dockerfile is effective.
  • Skipping docker image inspect and guessing how the base image starts.

Summary

  • 'CMD supplies defaults, while ENTRYPOINT defines the executable.'
  • Changing a base image's default command may require overriding one or both instructions.
  • Use exec-form syntax for clearer process behavior.
  • Prefer runtime overrides for temporary changes and child images for permanent ones.
  • Inspect the parent and child image metadata instead of guessing how startup works.

Course illustration
Course illustration

All Rights Reserved.