Open an interactive shell with Docker Compose

Choose exec for a running service or run for a disposable command, and understand when attach controls the main process.

Best practices
Illustration of container operations and troubleshooting

For a service that is already running, use docker compose exec SERVICE sh. For a new one-off container, use docker compose run --rm SERVICE sh. Unlike up, these commands are designed for directly interacting with one command.

Open a shell in a running service

docker compose exec web sh
docker compose exec web python manage.py shell

The image must contain the requested executable. A Django management shell also requires the application files and dependencies. Compose exec normally enables interactive input and allocates a TTY; there is usually no need to add -it as with plain docker exec.

Exiting this shell normally ends only the exec process, leaving the service's main process running. Commands executed there still share the container's filesystem and can affect the application. For a scaled service, select a replica with --index when necessary.

In CI or a pipeline, disable TTY allocation:

docker compose exec -T web python manage.py check

A stopped or repeatedly crashing service cannot provide a reliable exec session.

Start a disposable command container

Given a service definition with an appropriate image:

docker compose run --rm web sh

This creates a separate container with the service configuration and overrides its command. An existing image entrypoint still runs unless you deliberately override it. For example, docker compose run --rm --entrypoint sh web bypasses that entrypoint, potentially skipping required initialization.

run can start dependencies; add --no-deps only when you do not need them. It does not publish the service's configured ports by default. Use --service-ports or an explicit -p when that is actually required and no conflicting listener exists. The container is removed after exit with --rm; mounted data can outlive it.

Keep a dedicated shell service

A tool service can use a shell as its main process:

services:
  tools:
    image: python:3.12-slim
    stdin_open: true
    tty: true
    command: ["sh"]

Start it in the background and explicitly attach:

docker compose up -d tools
docker compose attach tools

stdin_open keeps input open, and tty allocates a terminal. docker compose up is primarily a service-management and log-aggregation command; these settings do not turn its combined foreground output into a dependable interactive shell session.

Here the shell is the main process: exit stops the container. The usual interactive detach keys are Ctrl+P, then Ctrl+Q. Ctrl+C can affect the attached process; it is not a universal safe detach operation. exec starts a separate process, while attach connects to the existing one.

Diagnose unavailable shells

An immediate shell exit can result from closed input or from an entrypoint and command combination that does not do what you intended. Inspect the actual process configuration rather than assuming every shell needs a TTY to remain running.

Minimal or distroless images may have no sh or Bash. Use supported debug tooling, an appropriate debug image, or inspect files and logs without inventing an executable that the image does not contain. A new debug container is not automatically the same filesystem or process namespace as the original service.

See Compose exec, Compose run, and Compose attach.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting