Understand CMD vs ENTRYPOINT and always use exec form so containers handle signals correctly.
CMD vs ENTRYPOINT
# CMD — overridable default command
FROM ubuntu
CMD ["echo", "hello"]
# docker run myimage -> echo hello
# docker run myimage ls -> ls (CMD replaced)
# ENTRYPOINT — always executes, CMD = default args
FROM python:3.12
ENTRYPOINT ["python3", "app.py"]
CMD ["--port", "3000"]
# docker run myimage -> python3 app.py --port 3000
# docker run myimage --port 8080 -> python3 app.py --port 8080
# Always use exec form (array) — handles signals correctly
CMD ["node", "server.js"] # exec form - GOOD
CMD node server.js # shell form - PID 1 = sh