docker: Compose exec assumes interactive TTY
docker compose exec ... is different to docker exec ..., and this can cause surprising issues when running these commands in a pipeline. By default compose:
- allocates a pseudo TTY if stdout is a terminal (ignores stdin)
- enters interactive mode by default
So in a script it can be useful to sniff stdin and disable TTY if it's not interactive:
local execFlags=()
# Do not allocated a pseudo-TTY if *stdin* (file 0) is not a terminal i.e. if piping stdin.
# See: `help test`
if [ ! -t 0 ]; then
execFlags+=(--no-tty)
fi
exec docker compose exec "${execFlags[@]}" $@"
See:
- https://docs.docker.com/reference/cli/docker/compose/exec/
- https://github.com/docker/compose/blob/main/cmd/compose/exec.go#L85
Published on: 27 Oct 2025