Isaac.

general

Docker: An Introduction

Docker is a platform that enables developers to automate the deployment, scaling, and management of applications using containerization. Containers are lightweight, portable, and self-sufficient units that package an application and its dependencies together, allowing it to run consistently across different environments.

By Emem IsaacFebruary 2, 20216 min read
#docker#containers#devops
Share:

Docker: An Introduction

Docker has revolutionized how developers build, ship, and run applications. In this guide, we'll explore the fundamentals of Docker and containerization.

What is Docker?

Docker is a containerization platform that packages your application and its dependencies into a standardized unit called a container. Think of it as a lightweight virtual machine that runs on any system.

Key Benefits:

  • Consistency: Your app runs the same everywhere
  • Isolation: Apps don't interfere with each other
  • Efficiency: Containers are lightweight and fast
  • Portability: Ship your app anywhere

Core Concepts

Images

A Docker image is a blueprint or template for creating containers. It contains:

  • Application code
  • Runtime environment
  • System libraries
  • Configuration files
  • Environment variables

Images are built from a Dockerfile and can be stored in registries like Docker Hub.

Containers

A container is a running instance of an image. It's:

  • Isolated from the host system
  • Lightweight (megabytes vs. gigabytes for VMs)
  • Ephemeral (created and destroyed as needed)
  • Consistent across environments

Registries

Docker registries store and distribute images:

  • Docker Hub: Public registry (official images)
  • Private registries: Company-hosted registries
  • Cloud registries: AWS ECR, Azure ACR, Google GCR

Your First Dockerfile

Here's a simple example for a Node.js application:

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

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy application code
COPY . .

# Expose port
EXPOSE 3000

# Start application
CMD ["npm", "start"]

Dockerfile Instructions

| Instruction | Purpose | |-----------|---------| | FROM | Base image to build upon | | WORKDIR | Set working directory in container | | COPY | Copy files from host to container | | RUN | Execute command during build | | EXPOSE | Document which ports the app uses | | ENV | Set environment variables | | CMD | Default command when container starts | | ENTRYPOINT | Configurable container entry point |

Building and Running

Build an Image

# Basic build
docker build -t my-app:1.0 .

# Build with build arguments
docker build --build-arg ENV=production -t my-app:1.0 .

# Build from a specific Dockerfile
docker build -f Dockerfile.prod -t my-app:1.0 .

Run a Container

# Basic run
docker run my-app:1.0

# Run with port mapping
docker run -p 3000:3000 my-app:1.0

# Run in background
docker run -d -p 3000:3000 my-app:1.0

# Run with environment variables
docker run -e NODE_ENV=production -p 3000:3000 my-app:1.0

# Run with volume mount
docker run -v /host/path:/container/path -p 3000:3000 my-app:1.0

# Run interactively
docker run -it -p 3000:3000 my-app:1.0

Common Docker Commands

Image Commands

# List images
docker images

# Pull image from registry
docker pull node:18

# Remove image
docker rmi image-name:tag

# Tag image
docker tag source-image:tag destination-image:tag

# Push image to registry
docker push username/image-name:tag

# Inspect image
docker inspect image-name:tag

Container Commands

# List running containers
docker ps

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

# Stop container
docker stop container-id

# Start container
docker start container-id

# Remove container
docker rm container-id

# View logs
docker logs container-id

# Execute command in running container
docker exec -it container-id bash

# Copy files from container
docker cp container-id:/path/to/file ./local/path

.dockerignore

Similar to .gitignore, the .dockerignore file excludes files from the Docker build context:

node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.DS_Store
dist
build
coverage

This reduces the build context size and speeds up builds.

Best Practices

1. Use Specific Base Image Tags

Bad:

FROM node

Good:

FROM node:18-alpine

2. Minimize Layer Count

Bad:

RUN apt-get update
RUN apt-get install -y git
RUN apt-get install -y curl

Good:

RUN apt-get update && apt-get install -y git curl

3. Use .dockerignore

Exclude unnecessary files to reduce build context and improve security.

4. Order Instructions by Frequency of Change

FROM node:18-alpine
WORKDIR /app

# Copy only package files (changes less frequently)
COPY package*.json ./
RUN npm install

# Copy application code (changes more frequently)
COPY . .

EXPOSE 3000
CMD ["npm", "start"]

This leverages Docker's layer caching for faster rebuilds.

5. Run as Non-Root User

# Create and use a non-root user
RUN useradd -m appuser
USER appuser

6. Keep Images Small

  • Use alpine or slim base images
  • Multi-stage builds for applications
  • Remove build tools in production images

7. Avoid Using Latest Tag

# Specify versions explicitly
FROM node:18.16.1-alpine

Multi-Stage Builds

Multi-stage builds reduce final image size by building in one stage and running in another:

# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Runtime stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]

Docker Compose (Quick Introduction)

Docker Compose runs multiple containers as a service. Here's a simple example:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:password@db:5432/myapp
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Run with:

docker-compose up

Troubleshooting

Container Exits Immediately

Check logs:

docker logs container-id

Permission Denied

Run as non-root user or use sudo:

docker run -u appuser image-name

Out of Disk Space

Clean up unused images and containers:

docker system prune
docker system prune -a  # Also remove unused images

Next Steps

  1. Install Docker: docker.com/products/docker-desktop
  2. Practice: Create Dockerfiles for your applications
  3. Learn Docker Compose: Orchestrate multi-container applications
  4. Explore Registries: Push images to Docker Hub or private registries
  5. Study Production Deployment: Kubernetes, Docker Swarm, cloud platforms

Resources

Conclusion

Docker simplifies application packaging and deployment. Master containerization to:

  • Deploy consistently across environments
  • Simplify development workflows
  • Scale applications efficiently
  • Improve collaboration between teams

Start small, build containers for your projects, and gradually expand your Docker knowledge!

Share:

Written by Emem Isaac

Expert Software Engineer with 15+ years of experience building scalable enterprise applications. Specialized in ASP.NET Core, Azure, Docker, and modern web development. Passionate about sharing knowledge and helping developers grow.

Ready to Build Something Amazing?

Let's discuss your project and explore how my expertise can help you achieve your goals. Free consultation available.

💼 Trusted by 50+ companies worldwide | ⚡ Average response time: 24 hours