Introduction to Docker

Introduction to Docker

Sufi Aurangzeb Hossain
May 9, 2025
13 min read
DockerDevOps

Docker is an open-source platform that revolutionizes how we build, ship, and run applications. It packages your application with all its dependencies into standardized units called *containers*, ensuring they run consistently anywhere – from your local machine to production servers.

Introduction to Docker – Your Containerization Journey Begins Here

Docker is an open-source platform that revolutionizes how we build, ship, and run applications. It packages your application with all its dependencies into standardized units called *containers*, ensuring they run consistently anywhere – from your local machine to production servers.

Why Docker Matters: Solving Real Development Problems

Before containers, developers faced the infamous *it works on my machine* problem. Docker eliminates this by providing:

  • Consistency: Identical environments across development, testing, and production
  • Isolation: Applications run in separate, secure environments
  • Portability: Run anywhere Docker is installed
  • Efficiency: Lightweight compared to virtual machines
  • Speed: Containers start in seconds, not minutes
  • Scalability: Easy to deploy and scale applications

Docker Architecture: Understanding the Building Blocks

Docker follows a client-server architecture:

  1. Docker Client: Command-line interface where you run docker commands
  2. Docker Daemon: Background service that manages containers, images, and networks
  3. Docker Images: Read-only templates used to create containers
  4. Docker Containers: Runnable instances of images
  5. Docker Registry: Cloud repository for storing and sharing images

Installing Docker: Getting Started

On Ubuntu/Linux:

sudo apt-get update
sudo apt-get install docker.io -y
sudo systemctl start docker
sudo systemctl enable docker
docker --version

# Add your user to docker group to avoid using sudo
sudo usermod -aG docker $USER
# Log out and log back in for changes to take effect

On macOS & Windows:

Install Docker Desktop from docker.com/products/docker-desktop – it includes everything you need in one package.

Your First Docker Experience: Hello World

Let's verify your installation with the classic hello-world container:

docker run hello-world

This command automatically downloads the hello-world image and runs it as a container. You should see a welcome message confirming Docker is working correctly!

Core Docker Concepts Explained

Understanding these fundamental concepts is crucial for your Docker journey:

Docker Images – Blueprints for containers

Images are read-only templates containing your application code, runtime, libraries, and dependencies. Think of them as cookie cutters that create consistent cookies every time.

# List all downloaded images
docker images

# Download an image from Docker Hub
docker pull ubuntu:latest

Docker Containers – Running instances of images

Containers are the actual running applications created from images. They're isolated, portable, and can be started, stopped, or deleted.

# Run an interactive Ubuntu container
docker run -it ubuntu bash

# List running containers
docker ps

# List all containers (including stopped)
docker ps -a

Dockerfile – Recipe for building images

A Dockerfile is a text file containing instructions to build a Docker image. It defines the base image, copies files, installs dependencies, and specifies the command to run.

# Simple Dockerfile example
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "app.js"]

Docker Volumes – Persistent data storage

Volumes allow you to persist data even when containers are deleted. They're essential for databases, file uploads, and any data that needs to survive container restarts.

# Mount current directory into container for development
docker run -v $(pwd):/app myapp

# Create and use a named volume
docker volume create mydata
docker run -v mydata:/app/data myapp

Docker Networks – Container communication

Networks enable containers to communicate with each other and the outside world. Docker creates a default network, but you can create custom networks for better isolation.

# Create a custom network
docker network create myapp-network

# Run container on specific network
docker run --network myapp-network myapp

Essential Docker Commands Cheat Sheet

Container Management:

docker ps                    # List running containers
docker ps -a                 # List all containers
docker stop container_id     # Stop a container gracefully
docker start container_id    # Start a stopped container
docker restart container_id  # Restart a container
docker rm container_id       # Remove a stopped container
docker exec -it container_id bash  # Open shell in running container
docker logs container_id           # View container logs
docker logs -f container_id        # Follow logs in real-time
docker stats                       # Show resource usage of containers

Image Management:

docker images                 # List all images
docker rmi image_id           # Remove an image
docker build -t myapp .       # Build image from Dockerfile
docker tag myapp:latest username/myapp:v1.0  # Tag an image

Hands-On Tutorial: Package Your First Application

Let's create a simple Node.js application and containerize it step by step:

Step 1: Create project files

mkdir my-first-docker-app
cd my-first-docker-app

# Create a simple Node.js application
echo 'const http = require("http");
const server = http.createServer((req, res) => {
  res.writeHead(200, {"Content-Type": "text/plain"});
  res.end("Hello from Docker! 🐳\n");
});
server.listen(3000, () => {
  console.log("Server running at http://localhost:3000/");
});' > app.js

# Create package.json
echo '{
  "name": "my-first-docker-app",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  }
}' > package.json

Step 2: Create a Dockerfile

Create a file named *Dockerfile* (no extension) with these contents:

# Use official Node.js runtime as parent image
FROM node:18-alpine

# Set the working directory in the container
WORKDIR /usr/src/app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy application code
COPY . .

# Expose port 3000
EXPOSE 3000

# Define the command to run your app
CMD ["npm", "start"]

Step 3: Build and run your application

# Build the Docker image
docker build -t my-node-app .

# Run the container with port mapping
docker run -p 3000:3000 my-node-app

Open your browser and visit *http://localhost:3000* – you should see *Hello from Docker! 🐳*

Docker Compose: Managing Multi-Container Applications

For real-world applications, you often need multiple services (web server, database, cache). Docker Compose simplifies this with a single configuration file.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      - db

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Essential Compose Commands:

docker compose up              # Start all services
docker compose up -d           # Start in background
docker compose down            # Stop and remove services
docker compose logs            # View logs from all services
docker compose exec web bash   # Access web service container

Docker in Development vs Production

Development Best Practices:

  • Use bind mounts for live code reloading
  • Keep development images separate from production
  • Use docker-compose for local development environments
  • Implement health checks for dependent services

Production Considerations:

  • Use multi-stage builds to minimize image size
  • Never store secrets in images – use environment variables or secrets management
  • Run containers as non-root users for security
  • Implement proper logging and monitoring
  • Use orchestration tools like Kubernetes for scaling

Common Beginner Pitfalls and Solutions

Problem: Permission denied errors

Solution: Add your user to the docker group or use sudo

Problem: Container exits immediately after starting

Solution: Ensure your application runs in foreground mode, not as a daemon

Problem: Can't connect to containerized database

Solution: Use Docker networks and proper service discovery

Problem: Build context too large

Solution: Use .dockerignore file to exclude unnecessary files

# Example .dockerignore file
node_modules
npm-debug.log
.git
.env
Dockerfile
README.md

Next Steps in Your Docker Journey

Congratulations! You now understand Docker fundamentals. Continue learning with these topics:

  • Deep dive into Docker Images and layer caching
  • Mastering Dockerfile best practices
  • Understanding container networking
  • Working with volumes and data persistence
  • Docker security best practices
  • Introduction to container orchestration with Kubernetes

Quick Reference Guide

  • *docker run -p HOST:CONTAINER IMAGE* – Run container with port mapping
  • *docker build -t NAME .* – Build image from current directory
  • *docker compose up* – Start multi-container application
  • *docker exec -it CONTAINER COMMAND* – Execute command in running container
  • *docker logs CONTAINER* – View container output

Remember: Practice makes perfect! Start containerizing your applications and explore the Docker ecosystem. Happy containerizing! 🐳