Docker
script automation
container startup
programming
DevOps

How can I run script automatically after Docker container startup

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To run a script automatically when a Docker container starts, the standard solution is to use an entrypoint script. That script runs as the container process or as a wrapper around the main process, performs startup work, and then execs the real application. The key detail is that containers should still end up with one main foreground process, not a shell script that spawns background work and exits unpredictably.

The Basic Docker Startup Model

Docker starts a container by running the image’s ENTRYPOINT and CMD. The most reliable pattern is:

  1. copy a startup script into the image
  2. make it executable
  3. set it as ENTRYPOINT
  4. have the script finish by running the main service with exec

That gives you a place to run initialization logic before the application begins serving.

Example Dockerfile

dockerfile
1FROM python:3.12-slim
2
3WORKDIR /app
4COPY entrypoint.sh /app/entrypoint.sh
5COPY app.py /app/app.py
6
7RUN chmod +x /app/entrypoint.sh
8
9ENTRYPOINT ["/app/entrypoint.sh"]
10CMD ["python", "app.py"]

The entrypoint script will always run, while CMD supplies the default application command.

Example entrypoint.sh

bash
1#!/bin/sh
2set -eu
3
4echo "Running startup script"
5
6# Example initialization logic
7if [ -f /app/init.sql ]; then
8  echo "Found init.sql"
9fi
10
11exec "$@"

The final exec "$@" matters. It replaces the shell with the target process so signals such as SIGTERM are delivered correctly to the application.

Why exec Matters

Without exec, the shell remains PID 1 and the actual application runs as a child. That can break signal handling and shutdown behavior.

Bad pattern:

bash
python app.py

Better:

bash
exec python app.py

Or, when using CMD, just:

bash
exec "$@"

That keeps the container aligned with Docker’s process model.

Running One-Time Initialization

Entrypoint scripts are often used for:

  • generating config files
  • waiting for dependent services
  • running database migrations
  • creating directories or permissions

Example:

bash
1#!/bin/sh
2set -eu
3
4python manage.py migrate
5exec gunicorn myapp.wsgi:application --bind 0.0.0.0:8000

This is common, but it should still be designed carefully. If migrations fail, the container should fail fast rather than continuing in a bad state.

ENTRYPOINT Versus CMD

Use ENTRYPOINT for the fixed startup wrapper. Use CMD for the default command or arguments that the wrapper ultimately runs.

If you put everything in CMD, a caller can easily override it and skip your startup logic. If you put everything in ENTRYPOINT, overrides become more awkward. The combination shown above is usually the right balance.

Docker Compose Example

Compose can still use the same pattern:

yaml
1services:
2  web:
3    build: .
4    ports:
5      - "8000:8000"

If you override command: in Compose, the entrypoint script still runs and receives the new command through "$@".

Avoid Backgrounding the Main Process

One common mistake is starting the real service in the background and letting the shell script end.

Bad:

bash
python app.py &
echo "started"

If the script exits, the container may stop even though you expected it to keep running. The main application should stay in the foreground as the container’s primary process.

When a Wrapper Script Is Not Needed

If all you need is to run a single program directly, skip the wrapper and use ENTRYPOINT or CMD directly.

dockerfile
CMD ["python", "app.py"]

Use a startup script only when there is real initialization work to do. Otherwise it adds indirection without value.

Common Pitfalls

The biggest mistake is writing an entrypoint script that does setup work but never execs the real application. Another is running the main process in the background, which breaks the container lifecycle. Teams also often overload startup scripts with too much orchestration logic that would be better handled elsewhere, such as in deployment tooling. Finally, if the script depends on tools like bash but the base image only has sh, the container fails before startup logic even begins.

Summary

  • Use an entrypoint script when you need startup logic before the main application begins.
  • End the script with exec "$@" or exec your-command so signal handling works correctly.
  • Keep the main process in the foreground.
  • Use ENTRYPOINT for the wrapper and CMD for default application arguments.
  • Skip the wrapper entirely if there is no real initialization work to perform.

Course illustration
Course illustration

All Rights Reserved.