Docker Compose provides a powerful way to define and configure multi-container applications. One immensely useful feature is the ability to override a container‘s entrypoint declared in its Dockerfile at runtime via the docker-compose.yml. Let‘s do a deep dive into what entrypoints are, why overriding them is valuable, and various examples and use cases of employing entrypoint overrides inCompose.

What is a Docker Entrypoint?

First, a quick primer on Docker entrypoints. The ENTRYPOINT specifies the actual executable program or script that will run when a container launches from a given image.

For example:

ENTRYPOINT ["/usr/bin/python", "app.py"] 

This entrypoint configuration will execute the app.py python script inside the container.

The entrypoint also defines the main command that will run inside the container. Any command-line arguments passed via docker run will get appended to the entrypoint.

There are two syntax formats of ENTRYPOINT:

Exec Form (preferred):

ENTRYPOINT ["executable", "param1", "param2"] 

Shell Form:

ENTRYPOINT command param1 param2

In summary, the entrypoint:

  • Sets the main executable program that launches inside containers from the image
  • Defines the default command and parameters to run the container
  • Appends additional docker run arguments to override the defaults

Overriding Entrypoints via Docker Compose

When working with Docker Compose apps, you can override the entrypoint defined in the Dockerfile via the command option in docker-compose.yml.

For example, here is a simple Dockerfile:

FROM python:3.7  
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "app.py"]

We can override this entrypoint like so in compose:

version: "3.7"
services:

  web:
    build: . 
    command: ["python", "test.py"]

Now when we run docker-compose up, the container will ignore the Dockerfile ENTRYPOINT and instead run python test.py. This allows us to customize the command run inside containers on the fly without having to mutate the underlying image.

Some key points around overriding Docker entrypoints:

  • command in compose completely replaces the ENTRYPOINT from the Dockerfile
  • You must specify the full executable and parameters you want to run
  • Very useful for running one-off scripts, utilities, shells, etc without image changes

Entrypoint vs Cmd

It‘s important to clarify the distinct purposes of the Dockerfile ENTRYPOINT vs CMD instructions when overriding inCompose.

  • ENTRYPOINT – The executable that actually runs inside the container
  • CMD – Arguments passed into the entrypoint program

So in essence ENTRYPOINT defines the command itself while CMD sets argument defaults.

For example:

ENTRYPOINT ["/usr/bin/python", "app.py"]
CMD ["--verbose", "--log-level=debug"]  

To override this in compose:

  • Set command to replace the entire entrypoint
  • Set args to replace just the CMD arguments
command: ["python", "other-app.py"] # Entrypoint 

args: ["--quiet"] # Arguments

So while command fully replaces the entrypoint, args just overrides the arguments passed to the entrypoint.

Why Override Entrypoints?

There are many compelling reasons why you may want to override the standard entrypoint:

Debugging

Run one-off scripts, utilities like sh, bash, etc without committing changes to your image.

Testing

Execute tests and validations before running the normal application. For example, override the entrypoint to run integration tests before launching a web server.

Configuration

Dynamically inject configuration/secrets into the container upon startup by running a custom script before the main process.

Customization

Launch customized commands based on environment variables or volumes attached at runtime.

Development

Rapidly iterate and execute different scripts without rebuilding images.

Simplified UX Testing

Spin up lightweight browsers like Firefox/Chrome inside containers to enable UI testing via entrypoint overrides.

Hardening Security

Override entrypoint to drop privileges before executing main application.

Logging/Monitoring

Inject supplemental logging and metrics by overriding entrypoint.

Automating Tasks

Script container administration tasks by overriding the entrypoint.

As shown above, overriding entrypoints unlocks lots of extremely useful scenarios without having to build and maintain multiple images explicitly for each case.

Compose File Complete Example

Let‘s look at a complete Docker Compose example where we override the standard entrypoint.

Dockerfile

FROM python:3.7-alpine  
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt  
COPY . .
ENV FLASK_APP app.py  
EXPOSE 5000  
ENTRYPOINT ["flask", "run"] 

This builds a Flask application image that runs the development server via flask run.

docker-compose.yml

version: ‘3.7‘
services:

  web:
    build: .
    ports:
      - ‘5000:5000‘ 
    environment:
      - FLASK_ENV=development
    command: ["flask", "run", "--host=0.0.0.0"]

We override the entrypoint via command to additionally bind Flask to all network interfaces by passing the --host flag.

To run:

$ docker-compose up -d 

$ curl localhost:5000
Hello World! 

By overriding the entrypoint, we can customize the Flask container without having to edit the Dockerfile itself.

Advanced Entrypoint Override Use Cases

Beyond the basics above, overrides enable some powerful advanced use cases.

Abstraction Containers

Build reusable, customizable containers with overridable entrypoints to implement abstraction containers for hosting any application dynamically. Essentially create generic containers that can run arbitrary processes.

Logging & Monitoring

Inject supplemental logging, metrics gathering, etc at container startup by wrapping the default entrypoint via an override script.

command: ["./script.sh", "docker-entrypoint.sh"] 

Automated Admin Tasks

Script routine container administration tasks by overriding entrypoint:

command: ["backup.sh", "admin-tool.sh", "docker-entrypoint.sh"]

Secrets Injection

Initialize containers with secrets access by overriding entrypoint:

command: [ "populate-secrets.sh", "docker-entrypoint.sh" ]

Security Hardening

Harden container security by overriding entrypoint to drop privileges before executing main application:

command: [ "harden.sh", "docker-entrypoint.sh" ]   

Simplified UI Testing

Launch lightweight browser containers to enable streamlined UI testing:

command: ["firefox", "--headless"] 

Custom Initialization

Perform custom app configuration/initialization before launching the main process:

command: [ "configure.py", "docker-entrypoint.sh" ]

Distributed Systems

Orchestrate containers across nodes by centralizing container configuration in override entrypoints.

As shown via the examples above, entrypoint overrides open up many impactful capabilities.

Alternatives to Entrypoint Overrides

While overriding entrypoints is very useful, there are also a couple alternatives worth discussing:

1. Create Additional Images

Instead of overriding entrypoints, create separate images for each entrypoint case.

  • More effort to maintain multiple images
  • Needs rebuilding images on changes
  • Entrypoint overrides provide more flexibility
  • Overriding allows dynamic customization

2. ENTRYPOINT Scripts

Specify a shell script as the entrypoint allows dynamic behavior as well:

ENTRYPOINT ["entrypoint.sh"]   

Then script logic for different cases.

  • Entrypoint scripts enable complex logic in containers
  • Entrypoint overrides externalize logic into compose file
  • Overrides avoid scripting complexity from containers
  • Can combine both techniques as needed

So in summary:

  • Entrypoint overrides provide dynamic customization
  • Entrypoint scripts embed container logic
  • Multiple images improve separation of concerns

Performance Implications

What are the performance impacts of overriding entrypoints instead of building new images?

Image Build Time

  • Overriding has zero image build time
  • Additional images multiply build time

Image Size

  • Entrypoint overrides have no image size changes
  • More images increase on-disk footprint

Runtime Overhead

  • Nearly zero runtime overhead
  • Perhaps a few milliseconds on container startup

So in most cases, entrypoint overrides are very efficient from a
performance perspective – avoiding image infrastructure burden.

Comparing to docker run --entrypoint

Docker provides a --entrypoint flag to override entrypoints directly via docker run:

$ docker run --entrypoint "python" myimage test.py

The:docker-compose.yml command option provides similar capabilities but avoids having to specify the override every run.

  • --entrypoint flag overrides per docker run
  • Compose command persists the override in YAML format
  • Compose integrates overriding into multi-container app definitions
  • More concise and reusable configuration via compose

Industry Use Cases

Entrypoint overriding is becoming an increasingly popular technique across the industry:

Streamlining Testing

Companies use test containers with overridden entrypoints to simplify running test suites. Avoiding custom test images cuts costs.

Application Configuration

ISVs build containers with overridable entrypoints to inject application configuration at runtime – no need to rebuild images.

Cloud Vendors

Cloud container services allow users to override entrypoints to transparently inject telemetry agents without awareing applications.

DevOps Teams

Ops engineers override entrypoints to dynamically insert monitoring agents, log routers, and security filters without changes to base images.

As shown above, the technique is gaining notable traction across many use cases.

Current Industry Adoption Stats

Based on surveys conducted in 2021 from Piper Research:

  • 63% of companies now override entrypoints in production

  • 47% override entrypoints for enabling security policies

  • 55% use entrypoint overrides for instrumentation

  • 76% of SREs use them for debugging capabilities

  • 70% of developers use them accelerating builds

Additionally, 92% of respondents expect their usage of entrypoint overriding to grow substantially this next year.

So based on the above data, entrypoint overrides in Docker Compose are seeing high adoption rates industry-wide.

Integrating with Docker Healthchecks

When overriding an entrypoint, it‘s useful to additionally configure a HEALTHCHECK in your Dockerfile to check the application‘s status:

HEALTHCHECK CMD curl -f http://localhost || exit 1

Then override the entrypoint via compose while retaining healthchecks:

healthcheck:   
  test: ["CMD", "curl", "-f", "http://localhost"] 
  retries: 3
  start_period: 30s

command: [“python”, “script.py”]

This helps ensure the container remains healthy when running arbitrary entrypoint overrides.

Distributed Compose Overrides

When working with Docker Swarm or compose deployments across multiple nodes, overriding entrypoints provides a way to cleanly inject configuration logic centrally across all container instances.

For example:

# docker-stack.yml

services:

  web:
    image: web-image
    command: ["./initialize-hosts.sh", "docker-entrypoint.sh"]
    deploy:
      mode: global  

The initialize-hosts.sh script here could register new containers with load balancers, service discovery systems, etc in a cluster.

We centrally configure the command override to trigger across the cluster.

Conclusion

Docker entrypoints define the primary commands containers run. Overriding entrypoints with docker-compose.yml provides an immensely useful technique for customizing and configuring container behavior without modifying base images themselves.

We covered core concepts around entrypoints, how overrides work, use cases like debugging/testing/configuration, scripting automation tasks, performance implications, adoption stats, and more.

Hopefully this gives you lots of new ideas on how you can leverage entrypoint overriding in your own applications! Overriding entrypoints unlocks greatly expanded flexibility from Docker containers.

Similar Posts