System DesignEasy
What is the difference between CMD and ENTRYPOINT in a Dockerfile?
Both define what runs when the container starts but they behave differently.
ENTRYPOINT — the binary that always runs. Hard to override at docker run.
CMD — the default arguments to that binary. Easy to override.
Typical pattern: ENTRYPOINT for the program, CMD for the default args:
FROM mcr.microsoft.com/dotnet/aspnet:9.0
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet"]
CMD ["MyApi.dll"]
docker run image→ runsdotnet MyApi.dlldocker run image --version→ runsdotnet --version(CMD replaced)docker run --entrypoint /bin/sh image→ opens a shell (ENTRYPOINT replaced)
Two forms — use the exec form (JSON array) always:
# ✓ Exec form — no shell, signals (SIGTERM) reach the process
ENTRYPOINT ["dotnet", "MyApi.dll"]
# ✗ Shell form — wraps in /bin/sh -c, signals NOT delivered properly
ENTRYPOINT dotnet MyApi.dll
Shell form breaks graceful shutdown in Kubernetes: SIGTERM goes to sh, not your app. Your app gets killed instead of completing in-flight requests.
Common mistakes:
- Forgetting to combine ENTRYPOINT + CMD when you want both program AND args
- Using the shell form and wondering why containers don't drain cleanly
- Overriding ENTRYPOINT in production by accident → wrong binary runs
Quick mnemonic: ENTRYPOINT = "what to run", CMD = "with these defaults". If you don't need argument flexibility, just use one well-formed ENTRYPOINT.