`docker compose exec` Is the Right Command When the Service Is Already Running and You Need to Step Inside
A practical docker compose exec guide for developers who need to run commands in an existing service container and want to understand when exec is the right move versus run.
Why this command matters: Compose users often mix up
runandexec, then get confused when they create a new one-off container instead of entering the running service they actually meant to inspect.
What docker compose exec does
Docker documents docker compose exec as executing a command in a running service container. That “running” part is the key distinction.
A common example:
docker compose exec web shThis enters the already-running web service container and opens a shell there.
That makes it ideal for live inspection and one-off commands against the actual container instance currently serving your application.
Why this is different from docker compose run
The Docker docs for compose run explain that it starts a new container for a one-off command. That is useful, but it is not the same operation.
If your question is:
- what does the currently running app container see
- can this live service reach the database
- what files exist in the running container right now
then exec is usually the right choice, not run.
This distinction matters a lot because new containers can have different lifecycle context from the one already in service.
A practical debugging example
Suppose the application is serving traffic but failing to load a config file. The right first move might be:
docker compose exec web ls -la /app/configThat inspects the actual running service container, not a separate one-off container with similar config.
The difference can completely change the debugging result.
Why the TTY behavior matters
Docker documents that docker compose exec allocates a TTY by default, unlike raw docker exec where you often explicitly pass -it. This is a nice ergonomics improvement for interactive debugging sessions.
When scripting, the docs note that you can disable TTY allocation with -T. That is useful in CI or other non-interactive contexts.
This is a good example of why reading the command reference matters. Small behavior differences shape how cleanly the tool fits automation.
Good uses of compose exec
It is especially useful for:
- opening a shell in a running service
- running migrations inside an already-up container
- checking filesystem or config state
- verifying network access from the live service context
The theme is simple: inspect or act inside the container that actually exists right now.
That may sound obvious, but it prevents a very common debugging mistake: validating the wrong container context and then building confidence on top of the wrong result.
Wrong context is one of the most expensive small mistakes in container debugging.
exec helps when you really mean the live service.
That is why this command pays off so quickly in practice. It removes one whole class of confusion before you even start reasoning about the bug itself.
Final recommendation
If the service is already running and your question is about that live container, prefer docker compose exec. Save compose run for true one-off containers. The difference sounds small, but operationally it changes which environment you are actually looking at.