19.2.5.1 Exec Container Command
A focused guide to Exec Container Command, connecting core concepts with practical Docker and container operations.
When using docker exec, the command argument specifies what gets executed inside the running container. This can be any binary, script, or shell command that exists within the container's filesystem. The exec'd command runs as an independent process inside the container's namespace environment, and the choice of command directly determines the scope and purpose of the exec operation.
Specifying the Command
The command and its arguments follow the container identifier directly on the command line:
docker exec CONTAINER COMMAND [ARGS...]
Everything after the container name is treated as the command to run:
docker exec my-container echo "Hello from inside"
docker exec my-container ls /app
docker exec my-container cat /etc/hosts
docker exec my-container ./health-check.sh
Single Utility Commands
Running discrete, non-interactive commands is the most common pattern for operational tasks that do not require a shell session:
# Check what processes are running
docker exec my-container ps aux
# View environment variables
docker exec my-container env
# Check disk usage
docker exec my-container df -h
# Show network configuration
docker exec my-container ip addr
Each of these executes a single command, prints output to the terminal, and returns. The container continues running its primary process undisturbed.
Shell Commands with Arguments
Shell built-ins and pipeline operators are not available directly — the command is executed without a shell wrapper by default. To use shell features (pipelines, redirects, variable expansion), explicitly invoke a shell:
# This works — single command
docker exec my-container ls /app
# This fails — pipe is interpreted by the host shell, not inside the container
docker exec my-container ls /app | grep .log
# This works — explicit shell invocation handles the pipe inside the container
docker exec my-container sh -c "ls /app | grep .log"
Using sh -c passes the entire shell expression as a string to the shell inside the container, which then processes the pipe, redirect, or any other shell syntax:
docker exec my-container sh -c "cat /app/config.yaml | grep database"
docker exec my-container sh -c "echo $HOSTNAME"
docker exec my-container bash -c "for f in /app/*.log; do wc -l $f; done"
Interactive Commands
For commands that require user input or a terminal interface, combine with -it:
docker exec -it my-container bash
docker exec -it postgres-container psql -U postgres
docker exec -it redis-container redis-cli
docker exec -it my-container python3
The -i flag keeps stdin open, and -t allocates a pseudo-TTY. Without these flags, interactive programs cannot function correctly — they may fail to display prompts, behave unexpectedly with line editing, or refuse to start.
Database Administration Commands
A common operational pattern is running SQL or CLI tools against a database container without exposing its port:
# PostgreSQL
docker exec -it postgres-container psql -U postgres -d mydb -c "VACUUM ANALYZE;"
# MySQL
docker exec -it mysql-container mysql -u root -p -e "SHOW DATABASES;"
# MongoDB
docker exec -it mongo-container mongosh mydb --eval "db.users.countDocuments()"
These commands connect to the database using the container's local socket or localhost interface — no port publishing is needed.
File Operations
Copy, move, or inspect files inside the container without stopping it:
docker exec my-container cat /app/logs/app.log
docker exec my-container ls -la /tmp
docker exec my-container find /var/log -name "*.log" -mmin -60
Create a file inside the container:
docker exec my-container sh -c "echo 'debug=true' >> /app/config.override"
Running Scripts Inside the Container
If a script exists inside the container, it can be executed directly:
docker exec my-container ./scripts/backup.sh
docker exec my-container /usr/local/bin/init-db.sh
Pass arguments to the script:
docker exec my-container ./scripts/migrate.sh --direction=up --version=20240615
Command Resolution: PATH Inside the Container
The command is resolved using the container's PATH environment variable. A command available in the image (e.g., curl, jq, python3) can be used directly:
docker exec my-container curl -s http://localhost:8080/health
docker exec my-container python3 -c "import json; print(json.dumps({'status': 'ok'}))"
If a command is not on the PATH, its full path must be specified:
docker exec my-container /usr/local/bin/myapp-cli --version
Checking Available Shells
Not all container images include bash. Minimal images (alpine, distroless) may only have sh or no shell at all:
# Use bash if available
docker exec -it my-container bash
# Fall back to sh
docker exec -it my-container sh
# Verify what shells are present
docker exec my-container ls /bin/bash /bin/sh 2>&1
Exit Codes
The exit code of docker exec CONTAINER COMMAND reflects the exit code of the exec'd command itself:
docker exec my-container test -f /app/config.yaml
echo $? # 0 if file exists, 1 if not
This makes docker exec usable in conditional scripts:
if docker exec my-container test -f /app/config.yaml; then
echo "Config file exists"
else
echo "Config file missing"
fi