Docker ENTRYPOINT, CMD, and docker-compose entrypoint command

In Docker, both ENTRYPOINT and CMD define what process or command the container will execute when it starts, but they serve slightly different purposes and interact in specific ways:

  1. ENTRYPOINT: Defines the primary executable that will run within the container. This is usually the command or script that you always want to execute when the container starts, regardless of any additional parameters. It’s commonly used for setting up the "base command" or script that should run in all cases (e.g., an initialization script, a specific executable, etc.).

  2. CMD: Specifies the default arguments to pass to the ENTRYPOINT or, if no ENTRYPOINT is specified, it acts as the command to run. CMD is often used to define the "default behavior" but can be overridden by providing a command in the Docker run command or Docker Compose.

How ENTRYPOINT and CMD Work Together

When both ENTRYPOINT and CMD are specified in a Dockerfile:

  • ENTRYPOINT specifies the primary command or executable.
  • CMD provides the arguments or options for the ENTRYPOINT.

For example, given this Dockerfile:

ENTRYPOINT ["./scripts/wait-for-it.sh", "db:5432", "--"]
CMD ["python", "scripts/init_db.py"]

When the container starts, it will effectively run:

./scripts/wait-for-it.sh db:5432 -- python scripts/init_db.py

In this case:

  • ./scripts/wait-for-it.sh db:5432 -- is the ENTRYPOINT.
  • python scripts/init_db.py is the CMD argument passed to the ENTRYPOINT.

Benefits of Using Both

  1. Modularity: You can set up ENTRYPOINT as a stable entry script (e.g., a wait-for script or a wrapper) and use CMD to specify a default command that can be easily overridden.
  2. Flexibility: CMD can be overridden by specifying an alternative command when you run the container. For instance, if you run docker run myimage echo "Hello", it will replace python scripts/init_db.py with echo "Hello" while still running through the ENTRYPOINT.

If Only CMD or ENTRYPOINT is Present

  • Only CMD: Docker will execute the CMD as the container’s command.
  • Only ENTRYPOINT: You’d need to provide arguments explicitly when running the container if you want to specify them, as there’s no default argument.

Common Use Cases

  1. Using ENTRYPOINT for Initialization Logic: It’s common to set up ENTRYPOINT with initialization tasks, like waiting for a service to be ready (wait-for-it.sh), and use CMD for the main application command.
  2. Overriding Commands: With this setup, you can run the container with different commands without modifying the ENTRYPOINT logic. For example:
    docker run myimage python scripts/some_other_script.py
    

In Your Case

In your setup:

ENTRYPOINT ["./scripts/wait-for-it.sh", "db:5432", "--"]
CMD ["python", "scripts/init_db.py"]
  • ENTRYPOINT will run the wait-for-it.sh script, ensuring that the db service is available before starting.
  • CMD runs init_db.py, the database initialization script, by default.

If you wanted to run a different command (e.g., echo "Testing"), you could override CMD like this:

docker-compose run db-init echo "Testing"

In this case, wait-for-it.sh will still execute, but it will run echo "Testing" instead of python scripts/init_db.py.

Summary Table

Type Purpose Can be Overridden?
ENTRYPOINT Defines the base command/executable. Typically stable. No (unless you use --entrypoint)
CMD Defines default arguments or command if no ENTRYPOINT is set. Yes, by providing a new command

In short:

  • ENTRYPOINT is for the fixed part of the command, especially useful for setup tasks.
  • CMD is for the flexible, default part of the command that can be overridden when needed.