Last updated: April 13, 2025
1. Introduction to Docker
Docker is a platform that enables developers to build, package, and run applications in isolated environments called containers. These containers bundle an application with all its dependencies, ensuring consistent behavior across different environments—from development to testing to production. This guide introduces essential Docker commands for beginners and explores Podman as an alternative containerization solution.
Containers differ from traditional virtual machines (VMs) in that they share the host system's kernel, making them more lightweight and efficient. This allows you to run multiple containerized applications on a single host without the overhead of running multiple operating systems.
2. Installation & Setup
2.1 Installing Docker
Docker installation varies by operating system. Here are condensed instructions for the most common platforms:
Windows
For Windows 10/11 Pro, Enterprise, or Education with Hyper-V capability:
- Download and install Docker Desktop for Windows.
- Follow the installation wizard.
- Start Docker Desktop from the Start menu.
macOS
- Download and install Docker Desktop for Mac.
- Drag Docker to your Applications folder.
- Launch Docker from Applications.
Linux (Ubuntu)
# Update package index
sudo apt-get update
# Install prerequisites
sudo apt-get install ca-certificates curl gnupg
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add your user to the docker group (avoid using sudo with docker)
sudo usermod -aG docker $USER
# Apply group changes to current shell session
newgrp docker
2.2 Verifying Installation
To verify that Docker is correctly installed, run the following command in your terminal or command prompt:
docker --version
docker run hello-world
The first command displays the installed Docker version, and the second pulls and runs the
hello-world
image, which confirms that Docker can download images and run containers.
3. Basic Docker Commands
3.1 Working with Images
Docker images are templates or blueprints used to create containers. They are read-only and contain the application code, libraries, dependencies, tools, and other files needed to run an application.
Pulling Images
Download an image from Docker Hub or another registry:
docker pull [IMAGE_NAME]:[TAG]
Example:
docker pull nginx:latest
Listing Images
View all downloaded images:
docker images
Or with the newer syntax:
docker image ls
Building Images
Create a custom image from a Dockerfile:
docker build -t [NAME]:[TAG] [DOCKERFILE_PATH]
Example with a Dockerfile in the current directory:
docker build -t myapp:1.0 .
Removing Images
Delete an image:
docker rmi [IMAGE_NAME]:[TAG]
Example:
docker rmi nginx:latest
3.2 Container Operations
Containers are runnable instances of images. You can think of them as lightweight, isolated environments that include everything needed to run your application.
Running Containers
Start a new container from an image:
docker run [OPTIONS] [IMAGE_NAME]:[TAG] [COMMAND] [ARGS]
Common options:
-d
: Run in detached mode (background)-p [HOST_PORT]:[CONTAINER_PORT]
: Port mapping--name [NAME]
: Assign a name to the container-v [HOST_PATH]:[CONTAINER_PATH]
: Mount a volume-e [KEY]=[VALUE]
: Set environment variables--rm
: Remove container when it exits
Example: Running an Nginx web server on port 8080 in detached mode:
docker run -d -p 8080:80 --name my-nginx nginx:latest
Listing Containers
View all running containers:
docker ps
View all containers (including stopped ones):
docker ps -a
Starting and Stopping Containers
Stop a running container:
docker stop [CONTAINER_ID or NAME]
Start a stopped container:
docker start [CONTAINER_ID or NAME]
Restart a container:
docker restart [CONTAINER_ID or NAME]
Removing Containers
Delete a stopped container:
docker rm [CONTAINER_ID or NAME]
Force delete a running container:
docker rm -f [CONTAINER_ID or NAME]
3.3 Interacting with Containers
Containers aren't isolated islands—you often need to interact with them in various ways.
Executing Commands
Run a command inside a running container:
docker exec [OPTIONS] [CONTAINER_ID or NAME] [COMMAND]
Example: Open a bash shell in a running container:
docker exec -it my-nginx bash
The -it
flags allocate a pseudo-TTY and keep stdin open, enabling interactive terminal sessions.
Viewing Container Logs
Display logs of a container:
docker logs [CONTAINER_ID or NAME]
Follow the log output (similar to tail -f
):
docker logs -f [CONTAINER_ID or NAME]
Copying Files
Copy files between a container and your host system:
# From host to container
docker cp [HOST_PATH] [CONTAINER_ID or NAME]:[CONTAINER_PATH]
# From container to host
docker cp [CONTAINER_ID or NAME]:[CONTAINER_PATH] [HOST_PATH]
Example: Copy a configuration file to an Nginx container:
docker cp ./nginx.conf my-nginx:/etc/nginx/nginx.conf
4. Advanced Docker Commands
4.1 Networking
Docker creates isolated network environments for containers to communicate with each other and the outside world.
Listing Networks
docker network ls
Creating a Network
docker network create [NETWORK_NAME]
Running a Container in a Network
docker run --network=[NETWORK_NAME] [IMAGE_NAME]
Connecting a Running Container to a Network
docker network connect [NETWORK_NAME] [CONTAINER_ID or NAME]
Example of connecting containers in a custom network:
# Create a custom network
docker network create myapp-network
# Run a MySQL container in this network
docker run -d --name db --network=myapp-network -e MYSQL_ROOT_PASSWORD=secret mysql:5.7
# Run a WordPress container in the same network that can refer to the MySQL container by its name 'db'
docker run -d --name wordpress --network=myapp-network -p 8080:80 -e WORDPRESS_DB_HOST=db -e WORDPRESS_DB_PASSWORD=secret wordpress
4.2 Volumes & Data Persistence
Docker volumes provide persistent storage for containers.
Creating Volumes
docker volume create [VOLUME_NAME]
Listing Volumes
docker volume ls
Mounting a Volume
docker run -v [VOLUME_NAME]:[CONTAINER_PATH] [IMAGE_NAME]
Example using a volume for a database container:
# Create a volume
docker volume create postgres-data
# Run PostgreSQL with persistent data storage
docker run -d --name my-postgres -v postgres-data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=mysecretpassword postgres:13
Bind Mounts
Bind mounts map a host directory to a container directory, useful for development:
docker run -v /host/path:/container/path [IMAGE_NAME]
Example for development:
docker run -d --name dev-container -v $(pwd)/src:/app/src -p 3000:3000 node:16
4.3 Docker Compose
Docker Compose simplifies managing multi-container applications using a YAML file to configure all services, networks, and volumes.
For a comprehensive guide on Docker Compose, check out our detailed Docker Compose tutorial.
Basic Compose Commands
# Start all services defined in docker-compose.yml
docker compose up
# Run in detached mode
docker compose up -d
# Stop all services
docker compose down
# View logs
docker compose logs
# Scale a specific service
docker compose up -d --scale service_name=3
Example Docker Compose File
Here's a simple docker-compose.yml
example for a web application with a database:
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./website:/usr/share/nginx/html
depends_on:
- app
networks:
- frontend
app:
build: ./app
volumes:
- ./app:/code
depends_on:
- db
networks:
- frontend
- backend
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
POSTGRES_USER: appuser
POSTGRES_DB: appdb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
networks:
frontend:
backend:
volumes:
db-data:
4.4 System Management
Docker provides commands for system-level operations:
System Information
# Show Docker system information
docker info
# Show disk usage by Docker
docker system df
# Display real-time events from Docker
docker events
Cleaning Up
# Remove all stopped containers
docker container prune
# Remove all unused images
docker image prune
# Remove all unused volumes
docker volume prune
# Clean up everything not used (containers, networks, images, volumes)
docker system prune -a
5. Docker Best Practices
Implementing these best practices will help you create more efficient, secure, and maintainable container-based applications:
- Use specific image tags instead of
latest
to ensure consistency and avoid unexpected changes. - Create lightweight images by using minimal base images (Alpine, Slim, etc.) and multi-stage builds.
- Don't run containers as root. Use the
USER
instruction in your Dockerfile to specify a non-root user. - Use environment variables for configuration to keep containers portable across environments.
- Implement health checks to monitor container health and enable automated recovery:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
- Label your images with metadata for better organization and automation:
LABEL maintainer="dev@example.com" \ version="1.0" \ description="Example application"
- Clean up unnecessary files in your Dockerfile to reduce image size.
- Use Docker Compose for complex applications instead of long docker run commands.
- Scan images for vulnerabilities using tools like Docker Scout or Trivy.
- Pin dependencies to specific versions in your application to ensure reproducible builds.
6. Podman: A Docker Alternative
Podman is an open-source, daemonless container engine that provides a Docker-compatible command-line interface. As container technology evolves, Podman has emerged as a compelling alternative to Docker with several distinct advantages.
6.1 Why Consider Podman?
There are several scenarios where Podman might be preferable:
- Rootless Containers: Podman can run containers without root privileges by default, enhancing security by reducing the attack surface. This is especially important in production environments.
- Daemonless Architecture: Unlike Docker, which relies on a daemon process (dockerd)
running in the background, Podman operates without a daemon. This means:
- No single process with root privileges that could be compromised
- No central daemon that could be a single point of failure
- Containers are child processes of the command that started them, allowing for better integration with systemd
- Kubernetes Compatibility: Podman has excellent compatibility with Kubernetes, with support for generating Kubernetes YAML from Podman commands.
- Pod Support: Podman natively supports pods (groups of containers that share namespaces), which is a core concept in Kubernetes.
- Corporate Environments: In corporate settings where Docker Desktop might require licensing for professional use, Podman is a free alternative.
- Red Hat Environments: Podman is the default container engine in Red Hat Enterprise Linux (RHEL) and its derivatives.
6.2 Docker vs. Podman Commands
Transitioning from Docker to Podman is typically straightforward because Podman was designed to be a drop-in replacement. Most Docker commands work identically with Podman:
# Install Podman (Ubuntu example)
sudo apt-get install -y podman
# You can even create an alias to use the docker command with podman
alias docker=podman
Command equivalents:
Operation | Docker Command | Podman Command |
---|---|---|
Run a container | docker run nginx |
podman run nginx |
List containers | docker ps |
podman ps |
Build an image | docker build -t image . |
podman build -t image . |
Pull an image | docker pull alpine |
podman pull alpine |
List images | docker images |
podman images |
Podman-specific commands (not available in Docker):
# Create a pod
podman pod create --name mypod
# Run a container in a specific pod
podman run --pod mypod nginx
# Generate Kubernetes YAML from a container/pod
podman generate kube mypod > pod.yaml
7. Docker vs. Podman: Feature Comparison
This table compares Docker and Podman across key features to help you decide which tool better suits your needs:
Feature | Docker | Podman |
---|---|---|
Architecture | Client-server with daemon | Daemonless |
Root Privileges | Daemon requires root | Rootless by design |
Container Runtime | containerd (now) / runc | crun / runc |
Pod Support | No native support (only via Docker Compose or Swarm) | Native pod support |
Kubernetes Integration | Partial (via kubectl) | Strong (generate kube, play kube) |
Docker Compose Compatibility | Native | Via podman-compose |
Registry Support | Docker Hub (primary), supports others | Multiple registries by default |
Windows Support | Good native support | Limited (via WSL) |
macOS Support | Docker Desktop | Via virtual machine |
Linux Support | Excellent | Excellent (especially on RHEL/Fedora) |
Security | Good, but daemon with root access is a concern | Better, with rootless operations |
Licensing | Docker Desktop requires paid license for commercial use in larger organizations | Free open-source (Apache License 2.0) |
Corporate Backing | Docker, Inc. | Red Hat |
Maturity | Very mature, established ecosystem | Newer but rapidly maturing |
8. Additional Resources
To deepen your understanding of Docker and Podman, here are some helpful official resources:
Docker Resources
- Docker Official Documentation
- Docker Hub - Official repository for Docker images
- Docker Command Reference
- Docker Compose Documentation
- Docker Getting Started Guide
Podman Resources
- Podman Official Website
- Podman Documentation
- Podman Blog
- Podman Desktop - GUI for Podman
Learning Projects
The best way to learn Docker is through hands-on practice. Try these beginner-friendly projects:
- Containerize a simple web application (like a basic Node.js or Flask app)
- Set up a WordPress site with MySQL using Docker Compose
- Create a development environment with multiple microservices
- Build a CI pipeline using Docker for testing
- Try the same projects with Podman and compare the experience
Related Pages on Our Site
- Docker Compose - A Comprehensive Guide to Multi-Container Applications