Quick take: Docker command-line interface provides powerful tools for managing containerized applications.
Docker ps, images, exec, and logs: Complete Command Reference Guide
Docker command-line interface provides powerful tools for managing containerized applications. Among the most frequently used commands are docker ps, docker images, docker exec, and docker logs. These commands form the backbone of container lifecycle management and troubleshooting in production environments. This article provides an exhaustive exploration of each command, their options, practical applications, and real-world scenarios you will encounter as a DevOps engineer.
Understanding Docker Container Management Fundamentals
Before diving into specific commands, it is essential to understand the Docker architecture and container lifecycle. Docker containers are lightweight, standalone, executable packages containing everything needed to run an application. Unlike virtual machines, containers share the host OS kernel while maintaining isolation through namespaces and control groups. When you deploy containers, you need visibility into their status, resource usage, and behavior. This is where the core Docker commands become indispensable for daily operations.
The container lifecycle follows a predictable path: creation, running, paused, stopped, and removed states. Each state transition requires specific commands and produces specific outcomes. Understanding this lifecycle is crucial before mastering the individual commands covered in this article. DevOps teams must be able to query container status at any point, inspect running processes, retrieve logs for debugging, and execute maintenance tasks within containers without stopping them.
Docker ps: Listing and Managing Containers
Basic Docker ps Syntax and Output
The docker ps command is your primary tool for querying container status. In its simplest form, it lists all currently running containers with essential information about each. The command displays container ID, image name, command being executed, when it was created, its current status, exposed ports, and assigned name.
docker ps
This basic invocation shows only running containers. The output typically looks like this:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 nginx:latest "nginx -g 'daemon of" 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp web-server
f6e5d4c3b2a1 postgres:13 "docker-entrypoint.s" 5 hours ago Up 5 hours 5432/tcp db-primary
Essential Docker ps Flags and Options
Docker ps supports numerous flags that modify its behavior and output format. The most critical flag is --all or -a, which displays both running and stopped containers. This is essential for understanding the full history of containers on your system, especially when troubleshooting failed deployments or investigating why containers are not starting.
docker ps -a
When you run this command, you see containers in various states including stopped, exited, and created states. This reveals containers that may have crashed or been intentionally stopped. The status column shows exactly what happened, with exit codes for stopped containers indicating the reason for termination.
The --quiet or -q flag returns only container IDs without any additional information. This is particularly useful when scripting, as container IDs can be piped to other commands for bulk operations.
docker ps -q
You can use this to stop all running containers at once:
docker stop $(docker ps -q)
The --format flag allows custom output formatting using Go template syntax. This enables you to extract exactly the information you need for monitoring, logging, or integration with other tools. For example, to display only container names and their IP addresses:
docker ps --format "table {{.Names}}\t{{.ID}}\t{{.Status}}"
Advanced filtering with --filter enables you to query containers based on specific criteria like label, status, image name, or exit code. This is invaluable in complex environments with numerous containers.
docker ps -a --filter "status=exited"
This command shows only containers that have exited, helping you identify problematic deployments quickly.
The --size flag displays the size of each container on disk, which helps identify containers consuming excessive storage. This is important for capacity planning and troubleshooting disk space issues.
docker ps --size
Advanced Filtering Scenarios
In production environments with hundreds of containers, basic listing is insufficient. Docker supports filtering by multiple criteria simultaneously. To find all containers running a specific image that exited within the last day:
docker ps -a --filter "ancestor=myapp:latest" --filter "status=exited"
Label-based filtering is particularly powerful for container orchestration. If you have labeled containers with environment tags, you can list all production containers:
docker ps --filter "label=environment=production"
You can combine formatting with filtering to create monitoring dashboards or generate reports. For example, listing all containers with their resource limits:
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" --filter "status=running"
Docker images: Managing Container Images
Understanding Docker Image Structure
Before using docker images effectively, understand that Docker images are layered filesystems. Each instruction in a Dockerfile creates a new layer, and images are composed of multiple read-only layers stacked together. The docker images command displays information about these image layers and their metadata.
Basic Docker images Command
The docker images command lists all images stored on your system, showing repository, tag, image ID, creation time, and size. This is essential for understanding what images are available for deployment.
docker images
Output appears as follows:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a8efb6b4f8b5 2 weeks ago 142MB
postgres 13 e4f2e3c1d4a5 3 weeks ago 314MB
python 3.9 f6c5b4a3d2e1 1 month ago 886MB
myapp v1.0 a1b2c3d4e5f6 5 days ago 256MB
Filtering and Formatting Docker Images
The --filter flag for docker images works similarly to docker ps. You can filter images by dangling status, which identifies images not tagged and not used by any container. These are ideal candidates for cleanup to free disk space.
docker images --filter "dangling=true"
Dangling images accumulate quickly during development and CI/CD pipelines. To remove all dangling images safely:
docker image prune
You can filter images by reference, showing only images matching a specific pattern:
docker images --filter "reference=nginx*"
Custom formatting allows you to extract specific information needed for your workflow:
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
Managing Multiple Image Versions
In production environments, you often have multiple versions of the same application image. Understanding image relationships is crucial. The --digests flag shows the SHA256 digest of each image, which uniquely identifies image content independent of tags.
docker images --digests
This is important because two images with the same name and tag might have different digests if rebuilds occurred. Digests ensure you are deploying exactly the version you intended, regardless of tag changes.
To see only images with specific tag patterns, combine grep with docker images output:
docker images | grep -E "(latest|prod|staging)"
Understanding Image Size and Disk Usage
Image size directly impacts deployment speed, storage costs, and container startup time. Large images are particularly problematic in microservices architectures where you might have dozens of containers. The docker images output shows the virtual size, which is the amount of disk space used by the image.
To understand actual disk usage including shared layers:
docker system df
This command provides a summary of Docker's disk usage including images, containers, and volumes. It shows how much space could be freed by removing unused resources.
For development teams, optimizing image size is critical. Large base images impact both build time and deployment speed. Consider using minimal base images like alpine for non-critical components.
Docker exec: Executing Commands in Running Containers
Fundamentals of Docker exec
The docker exec command allows you to run commands inside a running container without stopping it or establishing a new session from scratch. This is invaluable for debugging, maintenance, and administration tasks. Unlike docker run which creates a new container, exec operates within an existing container's namespace and filesystem.
Basic syntax requires the container identifier (name or ID) and the command to execute:
docker exec container_name command
Interactive Execution and Shell Access
To debug container issues, you typically need an interactive shell session. Use the -i flag for interactive mode and -t for a pseudo-terminal. Combined as -it, this gives you a functioning shell prompt inside the container.
docker exec -it web-server /bin/bash
This command drops you into a bash shell inside the web-server container with full interactive capabilities. You can execute commands just as if you were inside the container directly. This is your primary troubleshooting mechanism for understanding container state, checking logs within the container, inspecting mounted volumes, or verifying configuration files.
For containers with only sh available (common in alpine-based images), use sh instead of bash:
docker exec -it app-container /bin/sh
Common Troubleshooting Tasks with Docker exec
When a containerized application is misbehaving, docker exec allows you to investigate directly. For example, to check if a network service is responding correctly:
docker exec web-server curl http://localhost:8080/health
To verify environment variables inside a container match your expectations:
docker exec app-container env | grep IMPORTANT_VAR
To check if required files exist at expected paths:
docker exec database-container ls -la /var/lib/postgresql/data
For database containers, you can execute database-specific commands directly:
docker exec db-primary psql -U postgres -c "SELECT version();"
This query verifies PostgreSQL is running and returns the version without entering an interactive session.
Running Scripts and Complex Commands
Docker exec can execute complex commands by using sh -c to invoke a shell interpreter:
docker exec web-server sh -c "ps aux | grep nginx"
This approach allows piping, redirection, and conditional execution within the container. You can chain multiple commands together:
docker exec app-container sh -c "cd /app && npm test && npm build"
For copying files from container to host or host to container during runtime, docker exec with redirection works effectively:
docker exec app-container cat /app/config.json > local-config.json
User Specification and Permissions
By default, docker exec runs commands as root inside the container. For security-sensitive operations, specify a different user with the --user flag:
docker exec --user appuser web-server whoami
This is particularly important when containers run with specific unprivileged users for security purposes. Running as the correct user ensures proper permissions and reproduces production conditions.
To determine what user the container normally runs as, check the Dockerfile or inspect the container configuration.
Working Directory Specification
The --workdir flag sets the working directory for the command execution:
docker exec --workdir /app container-name ls -la
This is useful when you need to execute commands relative to a specific directory without explicitly changing directories first.
Advanced Execution Scenarios
For containers running as root but needing to preserve the original user, use the --user flag to maintain consistency with production deployments:
docker exec --user 1000:1000 container-name id
Running privileged commands within containers requires understanding the container's capabilities. By default, docker exec inherits the container's privilege level. If you need specific privileges, check the container configuration before attempting operations.
For long-running background operations, you can detach from output:
docker exec -d container-name long-running-process &
The -d flag runs the command detached from your terminal, useful for asynchronous operations.
Docker logs: Analyzing Container Output
Understanding Container Logging Architecture
Docker captures container output (stdout and stderr) and stores it in logs accessible through the docker logs command. This is the primary mechanism for understanding container behavior, diagnosing problems, and monitoring application health. Different logging drivers can be configured to send logs to various backends, but the docker logs command accesses the locally stored logs.
Basic Docker logs Usage
The simplest docker logs invocation displays all captured output from container startup:
docker logs container_name
Output shows all stdout and stderr from the container, displayed in chronological order. For containers that have been running for extended periods, this can be substantial output.
Following Live Log Output
During troubleshooting and development, you need to watch logs as they occur. The --follow or -f flag mirrors tail -f functionality, displaying new log entries as they are generated:
docker logs -f web-server
Press Ctrl+C to exit the follow mode. This is essential when you are debugging live issues, testing code changes, or monitoring deployment progress in real-time.
Limiting Log Output
For containers running for days or weeks, logs become very large. The --tail flag limits output to the most recent N lines:
docker logs --tail 100 web-server
This shows only the last 100 lines, which is usually sufficient for diagnosing recent issues without overwhelming output.
Combining tail with follow shows recent logs plus new entries as they arrive:
docker logs --tail 50 -f app-container
Timestamp-Based Log Filtering
The --timestamps or -t flag adds timestamps to each log line, essential for understanding when events occurred:
docker logs -t web-server
Timestamps help correlate container events with external system events and identify timing-related issues.
Filter logs to specific time windows using --since and --until flags with duration or timestamp format:
docker logs --since 2024-01-15T10:00:00 --until 2024-01-15T11:00:00 app-server
You can also use relative durations:
docker logs --since 30m web-server
This shows only logs from the last 30 minutes, useful for examining recent activity without scrolling through days of logs.
Combining Docker logs with System Monitoring
In production environments, individual container logs must be collected and aggregated. Most teams use centralized logging solutions like ELK stack, Splunk, or cloud-native solutions. However, understanding local logs remains essential for troubleshooting.
To search logs for specific error patterns:
docker logs web-server | grep -i error
To count error occurrences:
docker logs app-container 2>&1 | grep -c "ERROR"
Extracting specific log entries for incident investigation:
docker logs db-server | grep "connection refused"
Analyzing Exit Status and Error Logs
When containers exit, their logs remain accessible until the container is removed. This is crucial for post-mortem debugging of failed containers:
docker logs failed-container
Combined with docker ps -a to find stopped containers, you can reconstruct what happened before failure.
To check the exit code of a stopped container:
docker inspect --format='{{.State.ExitCode}}' container_name
Exit code 0 indicates successful completion, while non-zero codes indicate errors. Common codes include 1 (general error), 126 (permission denied), 127 (command not found), and 130 (terminated by signal).
Advanced Log Analysis Patterns
For containers generating extensive logs, filter for specific patterns. To find database connection issues:
docker logs db-container | grep -i "connection\|timeout\|refused"
To identify performance issues, search for timeout or latency messages:
docker logs app-server | grep -i "slow\|timeout\|exceeded"
Combine multiple containers into one view for correlation analysis:
docker logs web-server | head -200 && echo "---" && docker logs db-server | head -200
Exporting Logs for Analysis
Save container logs to a file for offline analysis or sharing with other team members:
docker logs container-name > container-logs.txt 2>&1
For compressed storage of large logs:
docker logs container-name 2>&1 | gzip > container-logs.txt.gz
This approach preserves logs even after container removal, essential for incident investigations and compliance requirements.
Combining Commands for Real-World Workflows
Comprehensive Container Status Checks
In production environments, understanding overall system health requires combining multiple commands. A comprehensive health check script might look like:
#!/bin/bash
echo "=== Running Containers ==="
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
echo -e "\n=== Stopped Containers ==="
docker ps -a --filter "status=exited" --format "table {{.Names}}\t{{.ExitCode}}\t{{.Image}}"
echo -e "\n=== Image Summary ==="
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
echo -e "\n=== System Resource Usage ==="
docker system df
echo -e "\n=== Recent Container Activity ==="
for container in $(docker ps -q); do
echo "Container: $(docker ps --filter id=$container --format '{{.Names}}')"
docker logs --tail 5 $container | sed 's/^/ /'
done
Automated Troubleshooting Workflow
When containers fail unexpectedly, an automated workflow helps diagnose issues consistently:
#!/bin/bash
CONTAINER=$1
echo "Troubleshooting container: $CONTAINER"
echo ""
echo "1. Container Status:"
docker ps -a --filter name=$CONTAINER
echo -e "\n2. Container Logs (last 50 lines):"
docker logs --tail 50 $CONTAINER
echo -e "\n3. Container Configuration:"
docker inspect $CONTAINER | grep -A 5 "Env"
echo -e "\n4. Container Network:"
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}' $CONTAINER
echo -e "\n5. Recent Process Activity:"
docker exec -it $CONTAINER ps aux 2>/dev/null || echo "Container not running"
Monitoring Container Lifecycle Events
Understanding when containers start, stop, and fail is essential for operations. Combining docker ps with timestamps helps track lifecycle events:
#!/bin/bash
echo "Container Lifecycle Events:"
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.CreatedAt}}"
Practical DevOps Scenario: Production Issue Investigation
Consider a scenario where a production web service is not responding correctly. The investigation workflow combines multiple commands:
First, verify the container is running:
docker ps | grep web-service
If found, check recent logs for error patterns:
docker logs --tail 200 web-service | grep -i error
If errors reference database connections, verify the database container:
docker ps | grep database
Check database logs for connection errors:
docker logs database | grep -i "connection\|accept" | tail -20
Execute a connectivity test from the web service to the database:
docker exec web-service nc -zv database 5432
Verify environment variables are correctly set in the web service:
docker exec web-service env | grep DATABASE
This systematic approach, combining ps, logs, and exec, provides comprehensive visibility into the issue.
Best Practices and Performance Considerations
Log Management and Rotation
Docker's default logging driver stores logs locally, which can consume significant disk space for long-running containers. Configure log rotation to prevent disk exhaustion:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Add this configuration to /etc/docker/daemon.json and restart the Docker daemon. This limits individual log files to 10MB with a maximum of 3 rotated files, preventing runaway disk usage.
Efficient Container Listing with Filters
In large deployments with hundreds of containers, unfiltered docker ps commands become slow and produce overwhelming output. Always use filters to narrow results to relevant containers:
docker ps --filter "status=running" --filter "label=app=myapp"
This approach scales much better than processing all containers.
Strategic Use of Image Tags
Properly tagging images improves trackability and simplifies management. Use consistent tagging strategies combining version numbers, build timestamps, and environment identifiers:
docker tag myapp:latest myapp:1.2.3-prod-20240115
This makes it easy to identify exactly which version is deployed and when it was built.
Container Naming Conventions
Descriptive container names make docker ps output immediately useful without requiring additional lookups. Use naming patterns that encode function and environment:
docker run --name web-api-prod-01 -d nginx
Better than generic names like container1 or app, this name immediately conveys purpose and environment.
Conclusion
Mastering docker ps, docker images, docker exec, and docker logs is fundamental to effective container management and DevOps operations. These commands provide the visibility and control necessary for deploying, monitoring, and troubleshooting containerized applications at scale. The docker ps command enables container lifecycle visibility, docker images manages your image repository, docker exec allows direct interaction with running containers for debugging and administration, and docker logs provides application and system visibility for troubleshooting and monitoring. Combining these commands with appropriate filtering, formatting, and automation creates a powerful toolkit for production Docker environments. This article is part of the Docker Complete Course on learnwithirfan.com, which provides comprehensive training for DevOps engineers seeking to master containerization and orchestration technologies.
Final Thoughts
Docker ps images exec logs Explained is worth reviewing with a practical lens: understand the risk or opportunity, map it to your environment, and take clear next steps instead of reacting to headlines.
FAQ: Docker ps images exec logs Explained
What should you know about Docker ps, images, exec, and logs: Complete Command Reference Guide?+
Docker command-line interface provides powerful tools for managing containerized applications. Among the most frequently used commands are docker ps , docker images , docker exec , and docker logs .
What should you know about Understanding Docker Container Management Fundamentals?+
Before diving into specific commands, it is essential to understand the Docker architecture and container lifecycle. Docker containers are lightweight, standalone, executable packages containing everything needed to run an application.
What should you know about Basic Docker ps Syntax and Output?+
The docker ps command is your primary tool for querying container status. In its simplest form, it lists all currently running containers with essential information about each.
What should you know about Essential Docker ps Flags and Options?+
Docker ps supports numerous flags that modify its behavior and output format. The most critical flag is --all or -a , which displays both running and stopped containers.
What should you know about Advanced Filtering Scenarios?+
In production environments with hundreds of containers, basic listing is insufficient. Docker supports filtering by multiple criteria simultaneously.
Need help with infrastructure or security?
Work directly with Muhammad Irfan Aslam for Linux, cybersecurity, cloud, Docker, DevOps, CI/CD, or infrastructure support.
Hire Me for Support