Docker Introduction: Complete Guide to Containerization
A comprehensive introduction to Docker and containerization technology, covering fundamental concepts, key components, comparison with virtual machines, and practical setup guidance.
What is Docker?
Docker is a container technology: A tool for creating and managing containers.
Docker is an open-source containerization platform by which you can pack your application and all its dependencies into a standardized unit called a container.
Understanding Containers in Software Development
A container is a standardized unit of software - a package of code and dependencies to run that code.
Key Characteristics:- Lightweight: Containers are light in weight, making them highly portable
- Isolated: Isolated from the underlying infrastructure and from each other
- Consistent: You can run the docker image as a docker container in any machine where docker is installed, regardless of the operating system
- Predictable: The same container always yields the exact same application and execution behavior - no matter where or by whom it might be executed
Key Components of Docker
| Component | Description | Purpose |
|---|---|---|
| Docker Engine | Core part of Docker | Handles the creation and management of containers |
| Docker Image | Read-only template | Used for creating containers, containing the application code and dependencies |
| Docker Hub | Cloud-based repository | Used for finding and sharing container images |
| Dockerfile | Script with instructions | Contains instructions to build a Docker image |
| Docker Registry | Storage and distribution system | Store images in both public and private modes |
Why Containers?
Why would we want independent, standardized "application packages"?
Problem 1: Different Development and Production Environments
We often have different development and production environments. We want to build and test in the same environment as we later run our app in production.
"We want to have the exact same environment for development and production → This ensures that it works exactly as tested."
Problem 2: Inconsistent Team Development Environments
Different development environments within a team/company. Every team member should have the exact same environment when working on the same project.
"It should be easy to share a common development environment/setup with (new) employees and colleagues."
Problem 3: Clashing Tools Between Projects
Clashing tools/versions between different projects. When switching between projects, tools used in project A should not clash with the tools used in project B.
"We don't want to uninstall and re-install local dependencies and runtime all the time."
Solution Approach 1: Virtual Machines
What Are Virtual Machines?
Virtual machines provide virtual operating systems encapsulated in their own shell, independent from our host operating system.
With virtual machines, we have our host operating system (Windows, macOS, or Linux), and then on top of that, we install the virtual machine - essentially a computer inside our computer.
Virtual Machine Architecture: Each VM runs a complete guest OS
Virtual Machines: Pros and Cons
| Pros | Cons |
|---|---|
|
|
The Overhead Problem with Virtual Machines
- Virtual Operating System Overhead: Every virtual machine is like a standalone computer running on top of our machine
- Resource Consumption: Each VM requires significant memory, CPU, and hard drive space
- Duplication Problem: If you have multiple VMs using the same OS (e.g., Linux), it's installed separately in every machine, wasting enormous amounts of space
- Scalability Issues: The problem compounds with more virtual machines - each adding identical OS overhead
"Virtual machines solve the environment reproducibility problem but not in a perfect way. The overhead and resource duplication make them inefficient for modern cloud-native applications."
Solution Approach 2: Docker and Containers
- Containers are the key concept
- Docker is the de facto standard tool for creating and managing them
How Docker Containers Work
Docker Container Architecture: Containers share the host OS kernel
- Host Operating System: Windows, macOS, Linux - whatever your base system is
- Built-in Container Support: We utilize built-in container support that our operating system has (or emulated container support that Docker provides)
- Docker Engine: One lightweight tool installed on the system
- Containers: Spin up containers containing our code and the crucial tools/runtimes the code needs
Container Configuration and Sharing
Containers can be configured and described with a configuration file. This file can be shared with others so they can recreate the container.
Image Building and Distribution:You can build the container into an image and share that image with others to ensure everyone can launch the same container on their systems.
Containers vs Virtual Machines: Comprehensive Comparison
| Aspect | Docker Containers | Virtual Machines |
|---|---|---|
| OS Impact | Low impact on OS | Bigger impact on OS |
| Performance | Very fast | Slower |
| Disk Space | Minimal disk space usage | Higher disk space usage |
| Sharing & Distribution | Easy - sharing, re-building, and distribution | Challenging - can be complex |
| Encapsulation Level | Encapsulate apps/environments | Encapsulate "whole machines" |
| Boot Time | Seconds | Minutes |
| Resource Efficiency | Share host OS kernel - highly efficient | Each VM needs complete OS - inefficient |
Docker Setup
Docker Setup: Complete architecture overview
Understanding What You Install
When you install Docker (whether Docker Desktop, Docker Toolbox, or directly on Linux), you're primarily installing the Docker Engine.
Docker Engine Includes:- Docker Daemon: A background process that keeps running and ensures Docker works - the "heart of Docker"
- Command Line Interface (CLI): The tool you'll use throughout to run commands, create images and containers
- REST API: Interface for programs to interact with the daemon
Note: On macOS and Windows, Docker needs a Linux environment to run. Docker Desktop uses built-in OS features to create this environment efficiently. Older systems may need Docker Toolbox, which uses VirtualBox to create a virtual machine running Linux.
Docker Installation Options
Option 1: Docker Desktop (Recommended)
Docker Desktop is the recommended way of running Docker on macOS and Windows.
System Requirements:- macOS: Mac hardware from 2010 or newer
- Windows: Windows 10 64-bit (Pro, Enterprise, or Education) with Hyper-V enabled
- Linux: Native Docker Engine installation
- Uses built-in OS virtualization features
- Greater performance
- Doesn't clutter your system
- Easy installation and management
- Includes GUI dashboard
Option 2: Docker Toolbox (Legacy Systems)
If your system doesn't fulfill Docker Desktop requirements, there's an alternative: Docker Toolbox.
What is Docker Toolbox?Docker Toolbox is a legacy tool (replaced by Docker Desktop) that was historically the only solution for all platforms. It installs:
- VirtualBox: Creates a virtual machine on your system
- Docker Engine: Runs inside the VirtualBox VM
- Docker CLI: Command-line interface
- Docker Machine: Tool to manage the VM
- Docker Compose: Tool for multi-container applications
- Older macOS systems (pre-2010 hardware)
- Windows 7, Windows 8, or Windows 10 Home
- Systems that don't support Hyper-V
Important: Make sure your system supports virtualization before installing Docker Toolbox. On Windows 8/7, use tools like Speccy or Hardware-Assisted Virtualization Detection Tool to verify.
Docker Installation: Step-by-Step
Installing Docker Desktop
- Visit Official Site: Go to docs.docker.com
- Download and Install: Click on "Download and install" section
- Check Requirements: Verify your system meets the requirements listed
- Download Installer: Get the installer for your platform
- Run Installer: Execute the downloaded installer and follow wizard steps
- Start Docker: Launch Docker Desktop after installation
- Verify Installation: Open terminal and run:
docker --version
docker run hello-world
Installing Docker Toolbox (If Needed)
- Verify Virtualization Support: Ensure your system can run virtual machines
- Visit Toolbox Releases: Search for "Docker Toolbox releases" on GitHub
- Download Latest Version:
- Windows: Download the .exe installer
- macOS: Download the .pkg package
- Run Installer: Execute the downloaded file
- Choose Components: Ensure these are selected:
- VirtualBox (creates the virtual machine)
- Docker Engine
- Docker Machine
- Docker Compose
- Kitematic (optional GUI)
- Configure Options:
- Check "Add Docker binaries to PATH"
- Choose installation location
- Select desktop shortcuts (optional)
- Complete Installation: Click Install and wait for setup to finish
- Launch Docker: Double-click "Docker Quickstart Terminal" shortcut
- Verify Setup: The terminal should show the Docker whale logo and you can run:
docker --version
Installing Docker on Linux
sudo apt-get update
# Install prerequisites
sudo apt-get install ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Set up repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 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-compose-plugin
# Verify installation
sudo docker run hello-world
Post-Installation Setup
- Start Docker Daemon: Ensure Docker Desktop is running (or Docker service on Linux)
- Test Installation:
docker run hello-world
This pulls a test image and runs it in a container. If successful, you'll see a welcome message.
- Linux: Manage Docker as Non-Root User (Optional):
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
Recommended Development Environment
While you'll primarily run Docker commands in the command line, you'll also work with configuration files (Dockerfiles) and application code. A good code editor is essential.
Recommended Editor: Visual Studio Code- Why VS Code?
- Free and open-source
- Available for macOS, Windows, and Linux
- Integrated terminal
- Excellent Docker support
- Download: Visit code.visualstudio.com
- Install: Run the installer and follow setup wizard
VS Code Configuration for Docker Development
- Theme (Optional):
- Go to: File → Preferences → Color Theme
- Select: "Dark+ (default dark)" for better visibility
- View Settings:
- Menu: View → Appearance
- Show/hide: Side bar, Status bar, Activity bar as needed
- Essential Extensions:
- Docker Extension:
• Click Extensions icon (or Ctrl+Shift+X)
• Search: "Docker"
• Install: Docker by Microsoft
• Benefits: Syntax highlighting, IntelliSense for Dockerfiles, container management - Prettier Extension (Optional):
• Search: "Prettier - Code formatter"
• Install for automatic code formatting
• Helps keep configuration files clean
- Docker Extension:
- Integrated Terminal:
- Access: View → Terminal (or Ctrl+`)
- Benefit: Run Docker commands directly in VS Code
- Auto-opens in your project directory
- Opening Projects:
- File → Open Folder
- Select folder containing your project
- VS Code opens with file explorer on left
Basic Docker Commands
docker --version
# Pull an image from Docker Hub
docker pull ubuntu:latest
# List all images
docker images
# Run a container
docker run -it ubuntu:latest /bin/bash
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# Stop a container
docker stop <container_id>
# Remove a container
docker rm <container_id>
# Remove an image
docker rmi <image_id>
Creating Your First Docker Container
Let's create a real Docker container to validate your installation and understand the basic workflow. This example uses a simple Node.js application, but remember: you don't need to know Node.js. The concepts apply to any programming language.
Example Application Overview
This example is a basic Node.js application that:
- Starts a web server on port 3000
- Listens for GET requests
- Returns simple HTML response: "Hi there!"
- Includes dummy database connection code (simulates async operations)
- Requires Node.js version 14.3 or higher (uses top-level await)
Project Structure:
├── app.mjs # Application code
├── package.json # Dependencies list
└── Dockerfile # Docker configuration
Running Without Docker (Traditional Way)
- Visit nodejs.org and download Node.js
- Install Node.js on your system
- Open terminal in project folder
- Run:
npm install(installs dependencies from package.json) - Run:
node app.mjs(starts the server)
Problems with This Approach:
- Requires Node.js installation on every machine
- Version conflicts between projects
- "Works on my machine" syndrome
- Team members need exact same setup
Running With Docker (The Better Way)
Instead of installing Node.js locally, we create a container that includes everything needed.
Key Concept:Containers are based on Images. First, we create an image (blueprint), then run containers from that image.
Step 1: Create a Dockerfile
Create a file named Dockerfile (no extension) in your project root:
FROM node:14
# Set working directory in container
WORKDIR /app
# Copy package.json to working directory
COPY package.json .
# Install dependencies inside container
RUN npm install
# Copy application code
COPY . .
# Expose port 3000 to outside world
EXPOSE 3000
# Command to run when container starts
CMD ["node", "app.mjs"]
FROM node:14- Start with Node.js 14 environment (downloaded from Docker Hub)WORKDIR /app- Create and use /app directory in container filesystemCOPY package.json .- Copy dependency list into containerRUN npm install- Install dependencies inside containerCOPY . .- Copy rest of application codeEXPOSE 3000- Document that app uses port 3000CMD ["node", "app.mjs"]- Run the application when container starts
Step 2: Build the Docker Image
Open terminal in your project directory and run:
- Docker finds the Dockerfile in current directory
- Downloads Node.js base image from Docker Hub
- Executes each instruction in the Dockerfile
- Creates a new image with all setup complete
- Outputs: "Successfully built [IMAGE_ID]"
💡 Tip: On Windows, you might see the image ID displayed differently. Look for it in the output.
⚠️ Troubleshooting: If you get an error, ensure Docker Desktop is running in the background.
Step 3: Run the Container
Run the container with port mapping:
docker run- Start a new container-p 3000:3000- Port mapping (host:container)[IMAGE_ID]- The ID from the build step (or use image name)
By default, containers are isolated. The -p flag "publishes" a container port to your host machine:
- First 3000: Port on your local machine (localhost)
- Second 3000: Port inside the container
- Result: localhost:3000 on your machine → port 3000 in container
After Running: Your terminal will appear "stuck" - this is normal! The container is running and the web server is active.
Step 4: Test Your Containerized Application
- Open a web browser
- Visit:
http://localhost:3000 - You should see: "Hi there!"
- ✅ Application is running in a container
- ✅ No Node.js installed on your system
- ✅ No npm install run in your project folder
- ✅ Everything runs isolated in the container
- ✅ Same container works on any machine with Docker
Step 5: Stop the Container
Option 1: From Terminal (Quick):
Option 2: From Another Terminal (Proper Way):
- Open a new terminal window or tab
- List running containers:
docker ps
- Copy the container name (auto-generated, like "festive_maxwell")
- Stop the container:
docker stop [CONTAINER_NAME]
Verify: Try accessing localhost:3000 again - it should not be reachable. The container has stopped.
What You Accomplished
- ✅ Verified Docker installation works correctly
- ✅ Created your first Dockerfile
- ✅ Built a Docker image
- ✅ Ran a containerized application
- ✅ Understood port mapping
- ✅ Managed container lifecycle (start/stop)
- ✅ Experienced the power of containerization
You ran a Node.js application without installing Node.js on your system. Everything ran in an isolated, portable container that works identically on any machine with Docker!
Key Docker Workflow
- Create a Dockerfile: Define your application environment
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"] - Build the Image: Create a container image from the Dockerfile
docker build -t my-app:1.0 .
- Run the Container: Start your application
docker run -d -p 3000:3000 --name my-app-container my-app:1.0
- Push to Registry: Share your image
docker tag my-app:1.0 username/my-app:1.0
docker push username/my-app:1.0 - Deploy Anywhere: Pull and run on any system
docker pull username/my-app:1.0
docker run -d -p 3000:3000 username/my-app:1.0
When to Use Docker vs Virtual Machines
| Use Case | Use Docker Containers | Use Virtual Machines |
|---|---|---|
| Microservices | ✅ Ideal - lightweight, fast | ❌ Too heavy |
| CI/CD Pipelines | ✅ Fast build and deploy | ❌ Slow boot times |
| Development Environments | ✅ Easy sharing, consistency | ⚠️ Possible but heavy |
| Testing Different OS | ❌ Shares host kernel | ✅ Full OS isolation |
| Legacy Monolithic Apps | ⚠️ May need modification | ✅ Run as-is |
| High-Density Deployment | ✅ Hundreds of containers | ❌ Limited by resources |
Docker Use Cases
- Microservices Architecture: Package each service independently
- Continuous Integration/Deployment: Consistent build and test environments
- Development Environments: Onboard developers quickly with pre-configured environments
- Application Isolation: Run multiple versions of dependencies without conflicts
- Cloud Migration: "Lift and shift" applications to cloud platforms
- Scaling Applications: Quickly spin up multiple instances
- Testing: Create isolated test environments
Docker Best Practices
- Use Official Base Images: Start with trusted images from Docker Hub
- Keep Images Small: Use multi-stage builds and minimal base images (Alpine)
- One Process Per Container: Follow the single responsibility principle
- Use .dockerignore: Exclude unnecessary files from build context
- Don't Run as Root: Create and use non-root users for security
- Leverage Build Cache: Order Dockerfile instructions to maximize caching
- Tag Images Properly: Use semantic versioning (e.g., app:1.0.0)
- Health Checks: Implement container health checks
- Use Environment Variables: Configure containers through environment variables
- Scan for Vulnerabilities: Regularly scan images for security issues
Key Takeaways
- Docker = Containerization Platform: Tool for creating and managing containers
- Containers = Standardized Software Units: Package code and dependencies together
- Key Advantage: Same container works identically everywhere
- Lightweight vs VMs: Share host OS kernel instead of running full OS
- Performance: Fast startup (seconds vs minutes), minimal resource overhead
- Portability: Easy to share, rebuild, and distribute
- Consistency: Exact same environment for development, testing, and production
- Isolation: No conflicts between different project dependencies
- Components: Docker Engine, Images, Containers, Dockerfile, Registries
- Workflow: Write Dockerfile → Build Image → Run Container → Push to Registry → Deploy Anywhere
Docker Ecosystem: Additional Tools
Docker Hub
Docker Hub is a cloud-based repository for hosting and sharing Docker images.
What is Docker Hub?- Central place to store and distribute container images
- Access thousands of official images (Node.js, Python, Nginx, etc.)
- Share your own images publicly or privately
- Automate image builds from GitHub/Bitbucket
- Free for public repositories
docker login
# Tag your image for Docker Hub
docker tag my-app:1.0 username/my-app:1.0
# Push image to Docker Hub
docker push username/my-app:1.0
# Pull image from Docker Hub
docker pull username/my-app:1.0
# Search for images
docker search nginx
Note: You don't need Docker Hub account to pull public images, but you need one to push your own images.
Docker Compose
Docker Compose is a tool that simplifies managing multi-container applications.
Why Docker Compose?- Define entire multi-container setup in one YAML file
- Start all containers with single command
- Manage complex applications easily
- Ideal for microservices architectures
- Perfect for development environments
services:
web:
build: .
ports:
- "3000:3000"
database:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
redis:
image: redis:alpine
docker-compose up
# Start in background
docker-compose up -d
# Stop all services
docker-compose down
# View logs
docker-compose logs
# List running services
docker-compose ps
Note: Docker Compose is included with Docker Desktop. On Linux, you may need to install it separately.
Kubernetes
Kubernetes is a powerful platform for automating deployment, scaling, and management of containerized applications in production.
When You Need Kubernetes:- Deploying containerized applications at scale
- Managing hundreds or thousands of containers
- Need automatic scaling and load balancing
- Self-healing capabilities (restart failed containers)
- Rolling updates and rollbacks
- Production-grade container orchestration
Learning Path: Master Docker basics first, then Docker Compose, then move to Kubernetes for production deployments.