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
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 runarguments unless you use--entrypointflag. - CMD: Default arguments passed to
ENTRYPOINT. Can be overridden by appending arguments todocker run. python script.pycombination: Most common pattern —ENTRYPOINTis["python"],CMDis["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:
- Write your script — create
app.pywithif __name__ == "__main__":block (standard Python entryguard). - Copy it into the image — use
COPY app.py /app/in your Dockerfile. - Set permissions — ensure the script is executable (
RUN chmod +x /app/app.py) if you plan to run it directly (shebang line). - Define the entrypoint — choose one of these patterns:
-
ENTRYPOINT ["python", "/app/app.py"]— no shell, direct execution. -ENTRYPOINT ["python"]andCMD ["/app/app.py"]— arguments separable. - Build and run —
docker build -t myapp .thendocker 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.pyinstead of exec form["python", "/app/script.py"]— breaks signal handling and containers may not stop gracefully. - Forgetting to
COPYthe script into the image or mis-matching theWORKDIRpath — leads to 'No such file or directory' error at runtime. - Setting only
CMDwithoutENTRYPOINTand expecting the script to run —CMDis ignored if noENTRYPOINTis defined anddocker runpasses arguments. - Assuming
ENTRYPOINTwith shebang needs execute permission forpythoninterpreter — the interpreter itself doesn't need the script to be executable.
Variations
- Use
ENTRYPOINT ["python3"](explicit Python 3) instead ofpythonon systems wherepythonmaps to Python 2. - Combine with
CMD ["--help"]to show usage instructions by default when no overrides are provided. - For debugging, temporarily override entrypoint with
docker run --entrypoint bash myappto inspect the container interactively.
Real-world use cases
- CI/CD pipeline running a Python test suite: set entrypoint to
pytestandCMDto 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.pywith default port arguments inCMD.
Key takeaways
- The container's main process is defined by
ENTRYPOINT; the script becomes that process. - Always use exec form (
["exec", "args"]) forENTRYPOINTandCMDto avoid shell overhead and ensure clean signal handling. - Use
ENTRYPOINTfor the fixed executable (Python interpreter) andCMDfor default script arguments. - The container exits when your Python script finishes — design scripts to be idempotent or long-running accordingly.
- Use
docker logsto debug script output, anddocker run --entrypoint bashto inspect file paths inside the container.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.