Docker
ENTRYPOINT
base image
containerization
software development

Docker - Override or remove ENTRYPOINT from a base image

Master System Design with Codemia

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

Introduction

A Docker base image may define an ENTRYPOINT that runs a specific executable when the container starts. To override or remove it, use --entrypoint at runtime with docker run, or reset it in a child Dockerfile with ENTRYPOINT []. Understanding the difference between ENTRYPOINT and CMD is key to controlling container behavior.

ENTRYPOINT vs CMD

dockerfile
1# ENTRYPOINT defines the executable that always runs
2ENTRYPOINT ["python", "app.py"]
3
4# CMD provides default arguments to ENTRYPOINT (or runs as the command if no ENTRYPOINT)
5CMD ["--port", "8080"]
6
7# When both are set, the container runs: python app.py --port 8080
8# docker run myimage             → python app.py --port 8080
9# docker run myimage --port 3000 → python app.py --port 3000 (CMD is replaced)

ENTRYPOINT cannot be overridden by appending arguments to docker run. CMD can be overridden by appending arguments.

Override ENTRYPOINT at Runtime

bash
1# Base image has ENTRYPOINT ["python", "app.py"]
2# Override it to run bash instead
3docker run --entrypoint /bin/bash myimage
4
5# Override to run a different command
6docker run --entrypoint python myimage -c "print('hello')"
7
8# Override with sh for debugging
9docker run -it --entrypoint /bin/sh myimage

The --entrypoint flag replaces the image's ENTRYPOINT entirely. Any arguments after the image name become the new CMD.

Remove ENTRYPOINT Completely

bash
1# Set ENTRYPOINT to empty string to remove it
2docker run --entrypoint "" myimage /bin/bash
3
4# Now /bin/bash runs as the main command (no ENTRYPOINT wrapping it)

Override in a Dockerfile

When building a child image from a base that has an ENTRYPOINT:

dockerfile
1# Base image defines: ENTRYPOINT ["nginx", "-g", "daemon off;"]
2FROM nginx:latest
3
4# Reset ENTRYPOINT
5ENTRYPOINT []
6
7# Set a new command
8CMD ["bash"]
dockerfile
1# Or replace with a different ENTRYPOINT
2FROM nginx:latest
3ENTRYPOINT ["python", "server.py"]
4CMD ["--port", "8080"]

Setting ENTRYPOINT [] in the child Dockerfile clears the parent's entrypoint. Then CMD runs directly.

Shell Form vs Exec Form

dockerfile
1# Exec form (recommended) — runs the command directly
2ENTRYPOINT ["python", "app.py"]
3
4# Shell form — wraps in /bin/sh -c
5ENTRYPOINT python app.py

The key differences:

bash
1# Exec form: PID 1 is python
2# Signals (SIGTERM) go directly to python
3# docker stop works correctly
4
5# Shell form: PID 1 is /bin/sh, python is a child process
6# SIGTERM goes to sh, not python
7# docker stop may timeout and force-kill the container

Always use exec form (["cmd", "arg"]) for ENTRYPOINT to ensure proper signal handling.

Combining ENTRYPOINT with docker-compose

yaml
1# docker-compose.yml
2services:
3  app:
4    image: myimage
5    entrypoint: /bin/bash          # Override ENTRYPOINT
6    command: -c "echo hello"       # Override CMD
7
8  debug:
9    image: myimage
10    entrypoint: ""                 # Remove ENTRYPOINT
11    command: /bin/sh               # Run shell instead

Common Patterns

Wrapper Script ENTRYPOINT

dockerfile
1FROM python:3.11
2
3COPY entrypoint.sh /entrypoint.sh
4RUN chmod +x /entrypoint.sh
5
6ENTRYPOINT ["/entrypoint.sh"]
7CMD ["python", "app.py"]
bash
1#!/bin/bash
2# entrypoint.sh — runs setup then exec's CMD
3echo "Running migrations..."
4python manage.py migrate --noop
5
6echo "Starting app..."
7exec "$@"  # Runs CMD: python app.py

The exec "$@" pattern passes CMD arguments through and replaces the shell process with the command, making the CMD process PID 1.

Inspecting a Base Image's ENTRYPOINT

bash
1# View the ENTRYPOINT and CMD of any image
2docker inspect --format='{{json .Config.Entrypoint}}' nginx:latest
3# ["nginx","-g","daemon off;"]
4
5docker inspect --format='{{json .Config.Cmd}}' nginx:latest
6# ["nginx","-g","daemon off;"]
7
8# Or view the full config
9docker inspect nginx:latest | jq '.[0].Config.Entrypoint'
10docker inspect nginx:latest | jq '.[0].Config.Cmd'

Common Pitfalls

  • Confusing ENTRYPOINT and CMD override behavior: Arguments after docker run myimage replace CMD but not ENTRYPOINT. To replace ENTRYPOINT, you must use --entrypoint. Appending bash to docker run myimage bash only changes CMD.
  • Shell form ENTRYPOINT ignoring signals: Shell form (ENTRYPOINT python app.py) wraps the command in /bin/sh -c, making sh PID 1. docker stop sends SIGTERM to sh, not your app, causing a 10-second timeout and force kill. Always use exec form.
  • Forgetting exec "$@" in entrypoint scripts: Without exec, the entrypoint shell script remains PID 1 and your app runs as a child process. This breaks signal handling and health checks. Always end entrypoint scripts with exec "$@".
  • ENTRYPOINT [] does not reset CMD: Clearing the entrypoint with ENTRYPOINT [] still preserves the base image's CMD. If the base's CMD was arguments to the now-removed entrypoint, the container may fail. Set both ENTRYPOINT [] and a new CMD.
  • Not using --entrypoint "" (with empty string): Running docker run --entrypoint myimage bash tries to use myimage as the entrypoint. The correct syntax is docker run --entrypoint "" myimage bash to clear the entrypoint and run bash.

Summary

  • Override at runtime: docker run --entrypoint /bin/bash myimage
  • Remove at runtime: docker run --entrypoint "" myimage /bin/bash
  • Override in Dockerfile: ENTRYPOINT [] clears the parent's entrypoint
  • Always use exec form (["cmd", "arg"]) for proper signal handling
  • Use exec "$@" at the end of entrypoint scripts to pass CMD as the main process
  • Inspect base images with docker inspect --format='{{json .Config.Entrypoint}}' image

Course illustration
Course illustration

All Rights Reserved.