Docker
Docker-Compose
Entrypoint
Command
Containers

Docker-Compose Entrypoint/Command

Master System Design with Codemia

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

Introduction

In Docker Compose, entrypoint and command both affect what runs when a container starts, but they do not mean the same thing. The reliable mental model is that entrypoint defines the executable or wrapper script, while command provides the default arguments or alternate command payload sent to that executable.

Start with the Image Contract

Before looking at Compose, remember that the image may already define ENTRYPOINT and CMD in its Dockerfile. Compose does not invent startup behavior from scratch; it layers overrides on top of that image contract.

A typical Dockerfile looks like this:

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

When a container starts from this image, Docker effectively runs python app.py. If Compose overrides only command, the entrypoint stays python. If Compose overrides entrypoint, the original executable is replaced entirely.

Use command to Change the Payload

command is the safer override when you want a different default action but still want the image's startup wrapper or executable.

yaml
1services:
2  worker:
3    image: myapp:latest
4    command: ["jobs.py", "--queue", "critical"]

If the image entrypoint is python, the container will run python jobs.py --queue critical. This is common with official images that use an entrypoint script to prepare permissions, environment variables, or generated configuration before launching the real process.

Use entrypoint to Replace the Executable

Override entrypoint only when you intentionally want a different launcher.

yaml
1services:
2  web:
3    image: nginx:latest
4    entrypoint: ["/bin/sh", "-c"]
5    command: ["echo starting && nginx -g 'daemon off;'"]

Now the image's original entrypoint is ignored. The shell becomes the executable, and the command string becomes the shell payload. That is powerful for debugging and one-off overrides, but it can also bypass important image logic.

Exec Form and Shell Form Are Different

Compose supports list form and string form, just like Docker. Prefer list form when you want predictable argument passing.

yaml
command: ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]

List form avoids shell parsing, which means fewer surprises with quoting, environment expansion, and signal handling. Use string form only when you explicitly want shell behavior.

yaml
command: sh -c "echo booting && python app.py"

That second form is useful, but it changes how arguments are parsed. It also makes signal forwarding less direct because a shell process sits between Docker and your main program.

Why Official Images Often Care About Entrypoint

Many production images use an entrypoint script for setup work such as waiting for dependencies, adjusting file ownership, substituting configuration templates, or running database migrations. For example, a shell script may end with exec "$@" so the final application replaces the shell process.

bash
1#!/bin/sh
2set -e
3
4python manage.py migrate
5exec gunicorn app.wsgi:application --bind 0.0.0.0:8000

If Compose replaces entrypoint, that setup logic disappears unless you reproduce it yourself. That is why command is usually the better first choice.

Good Debugging Pattern

If you only need temporary shell access, do not permanently edit the Compose file. Override the entrypoint at runtime instead.

bash
docker compose run --entrypoint /bin/sh web

This keeps the declared service clean and prevents accidental commits of debugging-only startup behavior.

Compose Should Not Become Your Scripting Language

Large startup scripts written inline inside command are hard to test and painful to maintain. If startup requires real branching logic, put that logic in a checked-in script inside the image and let Compose reference it plainly.

yaml
1services:
2  api:
3    build: .
4    command: ["/app/start-api.sh"]

That keeps orchestration concerns in Compose and application boot logic in versioned source files.

Common Pitfalls

  • Overriding entrypoint when only command needed to change.
  • Forgetting that the base image may depend on its entrypoint script for setup work.
  • Using string form unintentionally and getting unexpected shell parsing or quoting.
  • Hiding complex boot logic in a long Compose command instead of a real script.
  • Debugging a startup issue without first inspecting the image's original ENTRYPOINT and CMD.

Summary

  • 'entrypoint defines the executable or wrapper that starts first.'
  • 'command supplies default arguments or a replacement payload for that executable.'
  • Compose overrides sit on top of the Dockerfile, so the image contract still matters.
  • Prefer list form for predictable argument handling and cleaner signal behavior.
  • Use command for most behavior changes and reserve entrypoint for deliberate executable replacement.

Course illustration
Course illustration

All Rights Reserved.