Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Python Scripts as Container Entrypoint

Run Python scripts as container entrypoint in this Docker tutorial. Hands-on steps to set scripts as CMD/ENTRYPOINT, troubleshoot edge cases, and connect to next lessons.

Focus: run python scripts as container entrypoint

Sponsored

You've built a Python script that works perfectly on your machine, but when you Dockerize it, the container starts and immediately exits — or worse, it runs but behaves differently than expected. This disconnect between local development and container execution is a common frustration, and the root cause is almost always how you define the container's entrypoint. In this lesson, you'll learn exactly how to make a Python script the definitive, single-purpose command of your Docker container — so it starts, runs, and finishes exactly how you intend.

The problem this lesson solves

Containers are ephemeral by design: they run a single process and exit when that process finishes. If you've ever built a Docker image for a Python script only to see docker run print nothing and return to your shell, you've hit this exact problem. The default behavior — or a poorly configured CMD or ENTRYPOINT — can cause your script to be ignored, misinterpreted, or executed with the wrong interpreter. This lesson eliminates that guesswork.

Pro tip: A container's entire lifecycle is its main process. If that process exits, the container stops. Your Python script is that main process — so getting the entrypoint right is non-negotiable.

Core concept / mental model

Think of a Docker container like a dedicated, single-purpose computer. The entrypoint is the program that runs when you turn it on. If you set a Python script as the entrypoint, the container becomes that script — no default shell, no extra services, just your Python code executed from start to finish.

Key definitions

  • ENTRYPOINT: The executable that runs when the container starts. Once set, it cannot be overridden by docker run arguments unless you use --entrypoint flag.
  • CMD: Default arguments passed to ENTRYPOINT. Can be overridden by appending arguments to docker run.
  • python script.py combination: Most common pattern — ENTRYPOINT is ["python"], CMD is ["script.py"] (or vice versa).

Mental model diagram

Container start
       │
       ▼
[ENTRYPOINT]  ──►  python
       │
       ▼
[CMD]          ──►  /app/myscript.py
       │
       ▼
Your Python script executes
       │
       ▼
Script finishes → container exits

How it works step by step

Follow this logical sequence to make any Python script your container's entrypoint:

  1. Write your script — create app.py with if __name__ == "__main__": block (standard Python entryguard).
  2. Copy it into the image — use COPY app.py /app/ in your Dockerfile.
  3. Set permissions — ensure the script is executable (RUN chmod +x /app/app.py) if you plan to run it directly (shebang line).
  4. Define the entrypoint — choose one of these patterns: - ENTRYPOINT ["python", "/app/app.py"] — no shell, direct execution. - ENTRYPOINT ["python"] and CMD ["/app/app.py"] — arguments separable.
  5. Build and rundocker build -t myapp . then docker run myapp.

Important: Always use the exec form (["python", "script.py"]) not the shell form (python script.py). The exec form avoids PID 1 issues and signal handling problems.

Hands-on walkthrough

Let's build a complete example. We'll create a simple data-processing script and configure it as the container's entrypoint.

Step 1: Create your Python script

#!/usr/bin/env python3
"""data_processor.py: Simulate data processing as container entrypoint."""
import sys
import time

def process_data(filename: str = "data.csv") -> None:
    print(f"Processing {filename}...")
    time.sleep(1)  # Simulate work
    print("Done! Results written to output.json")

if __name__ == "__main__":
    # Accept optional filename from command line
    args = sys.argv[1:]
    if args:
        process_data(args[0])
    else:
        process_data()

Step 2: Write the Dockerfile

# Use official Python slim image
FROM python:3.11-slim

# Set working directory
WORKDIR /app

# Copy the script
COPY data_processor.py .

# Make executable (optional, good for shebang)
RUN chmod +x data_processor.py

# Set entrypoint — exec form, no shell
ENTRYPOINT ["python", "/app/data_processor.py"]

Step 3: Build and run

# Build the image
docker build -t data-processor .

# Run without arguments
$ docker run data-processor
Processing data.csv...
Done! Results written to output.json

# Override the default file via CMD or run arguments
# If you used CMD ["data.csv"] after ENTRYPOINT:
$ docker run data-processor mydata.csv
Processing mydata.csv...
Done! Results written to output.json

Step 4: Verify the process

# Check what's running inside
docker run -d --name processor data-processor
docker exec processor ps aux
# You'll see: python /app/data_processor.py

# Stop and clean up
docker stop processor
docker rm processor

Compare options / when to choose what

Pattern Dockerfile example Use case Overridable?
Direct exec ENTRYPOINT ["python", "/app/app.py"] Script that never needs arguments No clean override (use --entrypoint flag)
ENTRYPOINT + CMD ENTRYPOINT ["python"] + CMD ["/app/app.py"] Script with default arguments Yes — append args to docker run
Shebang + exec ENTRYPOINT ["/app/app.py"] Script with #!/usr/bin/env python3 Same as above
Shell form ENTRYPOINT python /app/app.py Quick prototyping (avoid in production) Partial — but creates extra shell process

General rule: For production, use ENTRYPOINT ["python", "app.py"] and let CMD carry default arguments. This gives you maximum flexibility without losing the ability to override parameters at runtime.

Troubleshooting & edge cases

Container exits immediately

Symptom: docker run myapp prints nothing or returns instantly. - Fix: Ensure your script has a blocking call or actual work. Add print() statements and check logs with docker logs <container-id>. - Check: Did you set ENTRYPOINT to a shell command that finishes instantly? Use exec form.

"Python: can't open file '/app/script.py': [Errno 2] No such file or directory"

Cause: The script path inside the container doesn't match WORKDIR or COPY location. - Fix: Use WORKDIR /app and COPY script.py ., then reference /app/script.py or just script.py (relative to WORKDIR).

Permission denied

Symptom: exec ./script.py: permission denied - Fix: Add RUN chmod +x script.py in Dockerfile, or use ENTRYPOINT ["python", "script.py"] which doesn't need execute permission.

Shell vs exec form surprise

# DON'T do this (shell form):
ENTRYPOINT python /app/script.py  # Runs via /bin/sh -c

# DO this (exec form):
ENTRYPOINT ["python", "/app/script.py"]  # Runs directly, no shell

The shell form wraps your command in /bin/sh -c, which means PID 1 is the shell, not your Python process. This breaks signal handling (e.g., docker stop won't gracefully shut down your script).

What you learned & what's next

You now understand how to make a Python script the definitive entrypoint of a Docker container — from choosing between exec/shell form, setting up ENTRYPOINT with CMD, to debugging common failures. You've seen how the container lifespan mirrors your script's execution and how to pass arguments at runtime.

Next step: In the next lesson, you'll explore how to combine multiple scripts and services inside a single container using supervisord or init systems, or dive into multi-container setups with Docker Compose to orchestrate Python microservices.

Practice recap

Create a new Dockerfile for a Python script that reads a filename from environment variable (e.g., INPUT_FILE) using os.environ.get() inside the script. Build and run the container, then override the filename by passing -e INPUT_FILE=custom.csv at runtime. Verify that the script uses the environment variable instead of the default.

Common mistakes

  • Using shell form ENTRYPOINT python /app/script.py instead of exec form ["python", "/app/script.py"] — breaks signal handling and containers may not stop gracefully.
  • Forgetting to COPY the script into the image or mis-matching the WORKDIR path — leads to 'No such file or directory' error at runtime.
  • Setting only CMD without ENTRYPOINT and expecting the script to run — CMD is ignored if no ENTRYPOINT is defined and docker run passes arguments.
  • Assuming ENTRYPOINT with shebang needs execute permission for python interpreter — the interpreter itself doesn't need the script to be executable.

Variations

  1. Use ENTRYPOINT ["python3"] (explicit Python 3) instead of python on systems where python maps to Python 2.
  2. Combine with CMD ["--help"] to show usage instructions by default when no overrides are provided.
  3. For debugging, temporarily override entrypoint with docker run --entrypoint bash myapp to inspect the container interactively.

Real-world use cases

  • CI/CD pipeline running a Python test suite: set entrypoint to pytest and CMD to a test directory.
  • Data pipeline container that runs an ETL script daily via Kubernetes Job: entrypoint is the Python ETL script.
  • Microservice that starts a Flask or FastAPI app: entrypoint is python app.py with default port arguments in CMD.

Key takeaways

  • The container's main process is defined by ENTRYPOINT; the script becomes that process.
  • Always use exec form (["exec", "args"]) for ENTRYPOINT and CMD to avoid shell overhead and ensure clean signal handling.
  • Use ENTRYPOINT for the fixed executable (Python interpreter) and CMD for default script arguments.
  • The container exits when your Python script finishes — design scripts to be idempotent or long-running accordingly.
  • Use docker logs to debug script output, and docker run --entrypoint bash to inspect file paths inside the container.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.