Lecture Overview
In this session, we'll explore the fundamental Docker commands that allow you to work with the three core components of Docker: images, containers, and volumes. By the end of this session, you'll have a practical understanding of how to create, manage, and interact with these components using the Docker command-line interface (CLI). These skills form the foundation of working with Docker in your development workflow.
Docker Command Structure
Before diving into specific commands, let's understand the general structure of Docker commands:
docker [command] [subcommand] [options] [arguments]
- command: The main Docker command (e.g.,
container,image,volume) - subcommand: The specific action to perform (e.g.,
create,start,remove) - options: Flags that modify the command behavior (e.g.,
-dfor detached mode,-vfor volume mounts) - arguments: Parameters for the command (e.g., container name, image name)
Docker also supports a more traditional command style for many operations:
docker run nginx # Instead of docker container run nginx
Both forms work, but we'll focus primarily on the newer command structure as it's more consistent and clearer about which Docker object you're working with.
Analogy: Docker commands are like giving instructions to a warehouse manager. You first specify which department you want to talk to (images, containers, volumes), then what action you want them to take (create, list, remove), followed by any special conditions (options) and finally what items you're referring to (arguments).
Working with Docker Images
Docker images are the blueprints for containers. They contain all the code, runtime, libraries, and dependencies your application needs. Let's explore the essential commands for working with images:
Listing Images
To see what images are available on your system:
docker image ls
# or the shorter form
docker images
Example output:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 3 weeks ago 142MB
python 3.10 a7830c32cb83 4 weeks ago 917MB
ubuntu latest 27941809078c 5 weeks ago 77.8MB
Pulling Images
To download an image from a registry (default is Docker Hub):
docker image pull [OPTIONS] NAME[:TAG]
# Examples:
docker image pull nginx
docker image pull python:3.9
docker image pull redis:alpine
If you don't specify a tag, Docker uses latest by default.
Best practice: Always specify a version tag in production to ensure consistency. The latest tag can change over time as new versions are released.
Searching for Images
To search for images available on Docker Hub:
docker search [OPTIONS] TERM
# Example:
docker search python
Image Details
To see detailed information about an image:
docker image inspect [OPTIONS] IMAGE
# Example:
docker image inspect nginx
This provides a JSON output with comprehensive details about the image, including its layers, configuration, and creation metadata.
Building Images
To build an image from a Dockerfile:
docker image build [OPTIONS] PATH
# Example:
docker image build -t myapp:1.0 .
The -t flag tags the image with a name (and optionally a tag), and the path . tells Docker to look for a Dockerfile in the current directory.
Example Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Removing Images
To delete an image from your local system:
docker image rm [OPTIONS] IMAGE [IMAGE...]
# or the shorter form
docker rmi [OPTIONS] IMAGE [IMAGE...]
# Examples:
docker image rm nginx
docker image rm python:3.8
docker image rm a7830c32cb83 # Remove by image ID
You can remove multiple images by listing them with spaces between.
Note: You cannot remove an image if it's being used by a container. You'll need to stop and remove the container first.
Saving and Loading Images
To save an image to a tar archive (useful for transferring without a registry):
docker image save -o filename.tar IMAGE
# Example:
docker image save -o myapp.tar myapp:1.0
To load an image from a tar archive:
docker image load -i filename.tar
# Example:
docker image load -i myapp.tar
Tagging Images
To create a new tag for an existing image:
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
# Example:
docker image tag myapp:1.0 myapp:latest
docker image tag myapp:1.0 registry.example.com/myapp:1.0
Real-world application: When developing a web application, you might pull a base image like python:3.9-slim, build your application on top of it with a Dockerfile, tag it with your application name and version, and then push it to a registry for deployment. Each image version represents a specific state of your application, enabling easy rollbacks if needed.
Working with Docker Containers
Containers are running instances of Docker images. They are isolated environments where your applications run. Here are the essential commands for managing containers:
Creating and Running Containers
To create and start a container in one command:
docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
# or the shorter form
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# Examples:
docker container run nginx
docker container run -d --name my-nginx -p 8080:80 nginx
docker container run -it --rm ubuntu bash
Common options:
-d, --detach: Run container in background--name: Assign a name to the container-p, --publish: Publish container's port to the host-v, --volume: Bind mount a volume-e, --env: Set environment variables-it: Interactive mode with a terminal--rm: Automatically remove the container when it exits
Analogy: If an image is like a blueprint for a house, then a container is like an actual house built from that blueprint. Running a container is like moving into the house - you're making the static blueprint into a living, functional space. The options are like specifying features of the house: whether it's connected to the city water supply (-p), what furniture goes in it (-v), and whether it should be demolished when you move out (--rm).
Listing Containers
To list running containers:
docker container ls
# or the shorter form
docker ps
To list all containers (including stopped ones):
docker container ls -a
# or
docker ps -a
Starting and Stopping Containers
To stop a running container:
docker container stop [OPTIONS] CONTAINER [CONTAINER...]
# or
docker stop [OPTIONS] CONTAINER [CONTAINER...]
# Example:
docker container stop my-nginx
To start a stopped container:
docker container start [OPTIONS] CONTAINER [CONTAINER...]
# or
docker start [OPTIONS] CONTAINER [CONTAINER...]
# Example:
docker container start my-nginx
To restart a container:
docker container restart [OPTIONS] CONTAINER [CONTAINER...]
# or
docker restart [OPTIONS] CONTAINER [CONTAINER...]
# Example:
docker container restart my-nginx
Removing Containers
To remove a container:
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
# or
docker rm [OPTIONS] CONTAINER [CONTAINER...]
# Example:
docker container rm my-nginx
To force removal of a running container:
docker container rm -f my-nginx
To remove all stopped containers:
docker container prune
Viewing Container Logs
To view the logs of a container:
docker container logs [OPTIONS] CONTAINER
# or
docker logs [OPTIONS] CONTAINER
# Examples:
docker container logs my-nginx
docker container logs --follow my-nginx # Stream the logs
docker container logs --tail 100 my-nginx # Show only the last 100 lines
Executing Commands in Running Containers
To run a command inside a running container:
docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
# or
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
# Examples:
docker container exec my-nginx ls -la
docker container exec -it my-nginx bash # Interactive shell
Common use case: Using exec to get a shell in a running container for debugging:
docker exec -it my-python-app /bin/bash
# Now you're inside the container and can run commands
ls -la
cat /etc/hosts
python -m pip list
exit # Exit the container shell
Copying Files To/From Containers
To copy files between your host and a container:
docker container cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker container cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
# or
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
# Examples:
docker container cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf # From container to host
docker container cp ./index.html my-nginx:/usr/share/nginx/html/ # From host to container
Inspecting Containers
To view detailed information about a container:
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
# or
docker inspect [OPTIONS] CONTAINER [CONTAINER...]
# Example:
docker container inspect my-nginx
To view container resource usage statistics:
docker container stats [OPTIONS] [CONTAINER...]
# or
docker stats [OPTIONS] [CONTAINER...]
# Examples:
docker container stats # All containers
docker container stats my-nginx # Specific container
Working with Docker Volumes
Volumes are the preferred way to persist data generated and used by Docker containers. Let's explore the essential commands for working with volumes:
Creating Volumes
To create a named volume:
docker volume create [OPTIONS] [VOLUME]
# Example:
docker volume create my-data
Note: You don't always need to explicitly create volumes. When you use a volume mount in a docker run command with a volume that doesn't exist, Docker will create it automatically.
Listing Volumes
To list all volumes:
docker volume ls [OPTIONS]
# Example:
docker volume ls
Inspecting Volumes
To view detailed information about a volume:
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
# Example:
docker volume inspect my-data
This will show you where the volume is stored on your host machine, along with other metadata.
Using Volumes with Containers
To use a volume when running a container:
docker container run -v volume_name:/container/path [OTHER_OPTIONS] IMAGE
# Examples:
docker container run -v my-data:/app/data nginx
docker container run -v postgres_data:/var/lib/postgresql/data postgres:13
Analogy: If containers are like temporary rental apartments, volumes are like storage units that remain even after you move out. When you rent a new apartment (start a new container), you can connect it to your existing storage unit (volume) to access your persistent belongings (data).
Bind Mounts
Bind mounts are similar to volumes but mount a specific directory from your host into the container:
docker container run -v /host/path:/container/path [OTHER_OPTIONS] IMAGE
# Example:
docker container run -v $(pwd):/app nginx
This is particularly useful during development to reflect code changes immediately in the container.
Practical development example:
docker container run -v $(pwd):/app -p 5000:5000 -w /app python:3.9 python app.py
This command:
- Mounts the current directory into /app in the container
- Publishes port 5000
- Sets the working directory to /app
- Uses the python:3.9 image
- Runs the command
python app.py
Any changes you make to your code on the host will be immediately available in the container.
Removing Volumes
To remove a volume:
docker volume rm [OPTIONS] VOLUME [VOLUME...]
# Example:
docker volume rm my-data
To remove all unused volumes:
docker volume prune
Warning: Removing a volume permanently deletes all data stored in it. Make sure to back up any important data before removing volumes.
Volume Drivers
Docker supports various volume drivers for different storage backends:
docker volume create --driver=local my-local-volume
docker volume create --driver=nfs my-nfs-volume
The default is the local driver, but plugins exist for many storage systems like NFS, Amazon EBS, and more.
Real-world application: In a production environment, you might use a cloud provider's volume driver to ensure data persistence even if containers move between hosts. For example, using Amazon EBS volumes with Docker containers running on AWS ensures that your data survives even if the underlying instance fails.
Combining Commands: Common Workflows
Let's explore some common workflows that combine various Docker commands:
Development Workflow with Python
# Pull a Python image
docker pull python:3.9-slim
# Run a container with the current directory mounted, in interactive mode
docker run -it --rm -v $(pwd):/app -w /app python:3.9-slim bash
# Inside the container:
pip install -r requirements.txt
python app.py
# The application is now running, and you can access it from your host
# Press Ctrl+C to stop the application
# Exit the container
exit
# The container is automatically removed due to the --rm flag
Running a Database with Persistent Storage
# Create a volume for database data
docker volume create postgres_data
# Run a PostgreSQL container with the volume
docker run -d --name my-postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres_data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:13
# Check container status
docker ps
# View logs to ensure the database started properly
docker logs my-postgres
# When done, stop the container
docker stop my-postgres
# Later, restart the container - data persists
docker start my-postgres
Building and Testing a Web Application
# Build a Docker image from the current directory
docker build -t mywebapp:1.0 .
# Run the application
docker run -d --name webapp -p 8080:80 mywebapp:1.0
# Check if it's running
docker ps
# Test it
curl http://localhost:8080
# View the logs
docker logs webapp
# Make changes and rebuild
docker stop webapp
docker rm webapp
docker build -t mywebapp:1.1 .
docker run -d --name webapp -p 8080:80 mywebapp:1.1
Cleanup Workflow
# Stop all running containers
docker stop $(docker ps -q)
# Remove all containers
docker rm $(docker ps -a -q)
# Remove unused images
docker image prune -a
# Remove unused volumes
docker volume prune
Warning: The cleanup workflow removes all containers, unused images, and volumes. Use with caution in shared or production environments.
Command Cheat Sheet
Image Commands
| Command | Description |
|---|---|
docker image ls |
List images |
docker image pull NAME[:TAG] |
Download an image |
docker image build -t NAME:TAG PATH |
Build an image from a Dockerfile |
docker image rm IMAGE |
Remove an image |
docker image prune |
Remove unused images |
docker image inspect IMAGE |
View image details |
Container Commands
| Command | Description |
|---|---|
docker container run IMAGE |
Create and start a container |
docker container ls |
List running containers |
docker container ls -a |
List all containers |
docker container stop CONTAINER |
Stop a container |
docker container start CONTAINER |
Start a stopped container |
docker container rm CONTAINER |
Remove a container |
docker container exec -it CONTAINER COMMAND |
Run a command in a running container |
docker container logs CONTAINER |
View container logs |
docker container inspect CONTAINER |
View container details |
docker container prune |
Remove all stopped containers |
Volume Commands
| Command | Description |
|---|---|
docker volume create VOLUME |
Create a volume |
docker volume ls |
List volumes |
docker volume inspect VOLUME |
View volume details |
docker volume rm VOLUME |
Remove a volume |
docker volume prune |
Remove all unused volumes |
Common Options
| Option | Description |
|---|---|
-d, --detach |
Run container in background |
--name NAME |
Assign a name to the container |
-p, --publish HOST:CONTAINER |
Publish container ports to the host |
-v, --volume SOURCE:TARGET |
Mount a volume or bind mount |
-e, --env KEY=VALUE |
Set environment variables |
-it |
Interactive mode with terminal |
--rm |
Remove container when it exits |
Common Patterns and Best Practices
Naming Conventions
- Use descriptive names for containers and volumes
- Consider using project names as prefixes
- Version your image tags (e.g.,
myapp:1.0,myapp:1.1)
Working with Containers
- Use
--rmfor temporary containers to avoid accumulating stopped containers - Use
-dfor services that need to run in the background - Always check logs when something isn't working as expected
- Use
execfor debugging instead of starting new containers
Data Management
- Use named volumes for persistent data
- Use bind mounts for development
- Regularly back up important volumes
- Be cautious with
prunecommands as they can delete important data
Resource Management
- Set resource limits for containers in production (memory, CPU)
- Monitor container resource usage with
docker stats - Clean up unused resources regularly to free up disk space
Real-world strategy: In a development workflow, create a script or alias for common Docker commands to simplify repetitive tasks. For example, a script that starts your development environment with the right volumes, port mappings, and environment variables can save time and reduce errors.
Docker Command Scripting Examples
Here are a few examples of useful scripts that combine Docker commands for common tasks:
Python Development Environment
Create a bash script called dev_env.sh:
#!/bin/bash
# Start a Python development environment
docker run --rm -it \
--name python-dev \
-v "$(pwd):/app" \
-w /app \
-p 5000:5000 \
-e FLASK_ENV=development \
-e FLASK_APP=app.py \
python:3.9 \
bash -c "pip install -r requirements.txt && flask run --host=0.0.0.0"
Database Backup Script
Create a script to backup a PostgreSQL database container:
#!/bin/bash
# Backup a PostgreSQL database
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="./backups"
mkdir -p "$BACKUP_DIR"
# Execute pg_dump inside the container
docker exec -i postgres_container pg_dump -U postgres my_database > "$BACKUP_DIR/backup_$TIMESTAMP.sql"
echo "Backup created: $BACKUP_DIR/backup_$TIMESTAMP.sql"
Cleanup Script
A script to clean up Docker resources safely:
#!/bin/bash
# Clean up Docker resources
echo "Stopping all running containers..."
docker stop $(docker ps -q)
echo "Removing stopped containers..."
docker container prune -f
echo "Removing unused images..."
docker image prune -f
echo "Removing unused volumes (except named ones)..."
docker volume prune -f
echo "Cleanup complete."
Note: Make scripts executable with chmod +x script_name.sh before running them.
Troubleshooting Common Issues
Container Won't Start
- Check logs:
docker logs container_name - Inspect configuration:
docker inspect container_name - Port conflicts: Ensure the published ports aren't already in use
- Resource limits: The container might need more resources than available
Volume Issues
- Permission problems: Check file permissions in bound directories
- Volume not found: Verify the volume exists with
docker volume ls - Data not persisting: Ensure you're mounting volumes correctly
Image Build Failures
- Dockerfile syntax: Check for syntax errors
- Build context: Ensure you're building from the right directory
- Network issues: Verify internet connectivity for package installations
General Debugging Steps
- Check container logs:
docker logs container_name - Inspect configuration:
docker inspect container_name - Run an interactive session:
docker exec -it container_name bash - Check docker daemon logs:
sudo journalctl -u docker(on Linux) - Verify system resources:
docker system df
Example debugging process: If a container exits immediately after starting, follow these steps:
- Check the exit code:
docker ps -a(look at the STATUS column) - View logs:
docker logs container_name - If the logs don't show anything useful, try running the container in interactive mode:
Then execute the command that would normally start your application to see errors directly.docker run -it --rm image_name sh - Check if the issue is related to volume mounts or environment variables by simplifying the run command.
Command Exploration Tools
Docker provides several ways to learn more about available commands:
Getting Help
To see all available Docker commands:
docker --help
To get help on a specific command:
docker COMMAND --help
# Examples:
docker container --help
docker container run --help
docker volume create --help
Exploring Docker Info
To see information about your Docker installation:
docker info
This provides details about:
- The Docker version
- Storage driver
- Logging driver
- Number of containers and images
- System-wide configuration
Docker System Commands
To view disk usage:
docker system df
To clean up all resources (containers, networks, images, volumes):
docker system prune -a --volumes
Warning: The prune command with --volumes will remove all unused volumes and their data. Use with extreme caution.
Key Takeaways
- Docker has a consistent command structure:
docker [command] [subcommand] [options] [arguments] - Images are read-only templates for containers, built from Dockerfiles
- Containers are running instances of images, providing isolated environments for applications
- Volumes are the preferred way to persist data beyond a container's lifecycle
- Common workflows involve pulling images, creating containers with volumes, and managing their lifecycle
- Proper naming and tagging help maintain organization in Docker environments
- Docker provides extensive help documentation through
--helpflags - Regular cleanup of unused resources helps maintain system performance
With these basic commands, you have the foundation to work effectively with Docker in your development workflow.
Looking Ahead
In our afternoon session, we'll apply these commands by running your first container, exploring Docker Hub for public images, creating a Dockerfile, and building your own image. The commands you've learned today will be the tools you use throughout the rest of the course and your Docker journey.
Discussion Questions
- What Docker commands do you think you'll use most frequently in your development workflow? Why?
- How might persistent volumes in Docker change the way you think about application data?
- What challenges do you anticipate when working with Docker images and containers?
- How could you use Docker commands in an automated CI/CD pipeline?
- Compare Docker's approach to running applications with your current development workflow. What advantages do you see?
Additional Resources
- Docker CLI Reference - Comprehensive documentation of all Docker commands
- Docker Volumes Documentation - In-depth information on Docker storage
- Docker Get Started Guide - Official tutorial with practical examples
- Docker Cheat Sheet - Community-maintained reference guide
- Play with Docker - Browser-based environment to practice Docker commands