docker run
docker-compose.yml
After establishing the base image, installing dependencies, and copying your project files into the image using COPY
or ADD
, the next step is to define how your container will behave when it starts. Specifically, you need to tell Docker where commands should be executed inside the container and what command should run by default. This is accomplished using the WORKDIR
, ENTRYPOINT
, and CMD
instructions in your Dockerfile. These are significant for making your containerized ML applications runnable and easy to use.
The WORKDIR
instruction sets the working directory for any subsequent RUN
, CMD
, ENTRYPOINT
, COPY
, and ADD
instructions in the Dockerfile. Think of it as changing the current directory (cd
) within the context of building and running your image.
If WORKDIR
is not specified, Docker executes subsequent commands in the root directory (/
). Explicitly setting a WORKDIR
makes your Dockerfile instructions clearer and less reliant on absolute paths.
Benefits:
Example:
Consider an ML project structured like this on your host machine:
my_ml_project/
├── Dockerfile
├── requirements.txt
├── src/
│ ├── train.py
│ └── predict.py
└── data/
└── dataset.csv
Instead of writing COPY src /app/src
and then RUN python /app/src/train.py
, you can use WORKDIR
:
# Dockerfile snippet
# ... (FROM, install dependencies)
# Set the working directory
WORKDIR /app
# Copy application code relative to WORKDIR
COPY src/ ./src/
COPY requirements.txt .
# Install dependencies (pip install -r requirements.txt)
# Copy data (might be better handled with volumes, see Chapter 3)
COPY data/ ./data/
# Subsequent commands like CMD or ENTRYPOINT will run from /app
CMD ["python", "src/train.py"]
In this example, WORKDIR /app
creates the /app
directory if it doesn't exist and sets it as the current directory. The COPY
instructions now use relative destinations (./src/
, .
, ./data/
), copying files into /app
. The final CMD
executes python src/train.py
assuming /app
is the current directory.
The ENTRYPOINT
instruction configures a container to run as an executable. It specifies the command that will always be executed when the container starts. Any command-line arguments provided to docker run <image> [arguments]
are appended to the ENTRYPOINT
command.
ENTRYPOINT
is often used when you want the container's primary purpose to be running a specific application or script.
There are two forms:
ENTRYPOINT ["executable", "param1", "param2"]
docker run
are appended directly after the specified parameters.ENTRYPOINT command param1 param2
/bin/sh -c
). It can be useful for environment variable substitution but might have unexpected behavior with signal handling or if the command contains shell metacharacters.Example (Exec Form):
Suppose you want your container to always execute Python scripts.
# Dockerfile snippet
# ... (FROM, WORKDIR, COPY, etc.)
ENTRYPOINT ["python"]
# Default script to run if no arguments are provided to docker run
CMD ["src/train.py"]
When you run this container:
docker run my-ml-image
: Executes python src/train.py
(the CMD
provides the default argument to the ENTRYPOINT
).docker run my-ml-image src/predict.py --model /app/models/model.pkl
: Executes python src/predict.py --model /app/models/model.pkl
(the arguments provided override the CMD
and are appended to the ENTRYPOINT
).The ENTRYPOINT
ensures python
is always the main command, making the container act like a dedicated Python script runner.
The CMD
instruction provides defaults for an executing container. These defaults can include an executable, but they are often used to specify default parameters for an ENTRYPOINT
. If used without an ENTRYPOINT
, CMD
specifies the default command to run.
Crucially, the entire CMD
instruction is overridden if the user provides arguments to docker run <image> [arguments]
.
CMD
also has two forms:
CMD ["param1","param2"]
(Used as default parameters for ENTRYPOINT
)CMD ["executable","param1","param2"]
(Default command if no ENTRYPOINT
)CMD command param1 param2
(Default command run via /bin/sh -c
)Use Cases:
Default arguments for ENTRYPOINT
(Most Common Combined Use):
WORKDIR /app
COPY src/ ./src/
ENTRYPOINT ["python", "src/run_experiment.py"]
# Default parameters if none are provided via 'docker run'
CMD ["--data", "data/dataset.csv", "--epochs", "10"]
docker run my-ml-image
executes: python src/run_experiment.py --data data/dataset.csv --epochs 10
docker run my-ml-image --data data/other.csv --epochs 20
executes: python src/run_experiment.py --data data/other.csv --epochs 20
(The CMD
is completely replaced).Default command (No ENTRYPOINT
):
WORKDIR /app
COPY src/ ./src/
# No ENTRYPOINT defined
CMD ["python", "src/train.py"]
docker run my-ml-image
executes: python src/train.py
docker run my-ml-image python src/predict.py
executes: python src/predict.py
(The entire default CMD
is replaced by the command provided).The most powerful and common pattern is using ENTRYPOINT
to specify the fixed executable (like python
or a wrapper script) and CMD
to specify the default, overridable arguments (like the script name or default hyperparameters).
Best Practices:
WORKDIR
: Always set a WORKDIR
to establish a clear execution context within your container. /app
is a common convention.["executable", "param1"]
) for both ENTRYPOINT
and CMD
to avoid shell processing quirks and make argument handling explicit.ENTRYPOINT
for the Executable: If your container is designed to run a specific command or behave like an executable, use ENTRYPOINT
. Examples: ENTRYPOINT ["python"]
, ENTRYPOINT ["./my_inference_server"]
.CMD
for Defaults: Use CMD
to provide default arguments to the ENTRYPOINT
or to specify a default command that is easily overridden. Example: CMD ["my_script.py", "--default-flag"]
.By carefully defining WORKDIR
, ENTRYPOINT
, and CMD
, you create Docker images that are not only reproducible environments but also behave predictably and are user-friendly, whether running training jobs or serving models. They define the interface for interacting with your containerized ML application.
© 2025 ApX Machine Learning