DevOps

Docker Deployment Guide: Containerize Your Applications Like a Pro

RexZ Development Team
1/18/2025
18 min read
1765 words
Docker
Containers
Deployment
DevOps
Microservices

Introduction to Docker Containerization

Docker has revolutionized application deployment by providing lightweight, portable containers that ensure consistency across different environments. This comprehensive guide will teach you everything you need to know about containerizing and deploying applications using Docker.

Why Use Docker?

Docker offers numerous advantages for application deployment:

  • Consistency: Applications run the same way across development, testing, and production
  • Isolation: Each container runs independently without affecting others
  • Portability: Containers can run on any system that supports Docker
  • Scalability: Easy to scale applications horizontally
  • Resource Efficiency: Containers share the host OS kernel, using fewer resources than VMs

Docker Installation

Ubuntu/Debian Installation

# Update package index
sudo apt update

# Install prerequisites
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.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 update
sudo apt install -y docker-ce docker-ce-cli containerd.io

# Add user to docker group
sudo usermod -aG docker $USER

# Start Docker service
sudo systemctl start docker
sudo systemctl enable docker

CentOS/RHEL Installation

# Install yum-utils
sudo yum install -y yum-utils

# Add Docker repository
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# Install Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io

# Start Docker
sudo systemctl start docker
sudo systemctl enable docker

Docker Basics

Essential Docker Commands

# Check Docker version
docker --version

# Run a container
docker run hello-world

# List running containers
docker ps

# List all containers
docker ps -a

# List images
docker images

# Stop a container
docker stop container_name

# Remove a container
docker rm container_name

# Remove an image
docker rmi image_name

Creating Your First Dockerfile

Node.js Application Example

# Dockerfile for Node.js application
FROM node:18-alpine

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Change ownership of the app directory
RUN chown -R nextjs:nodejs /app
USER nextjs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

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

Python Application Example

# Dockerfile for Python application
FROM python:3.11-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Set working directory
WORKDIR /app

# Install system dependencies
RUN apt-get update \
    && apt-get install -y --no-install-recommends gcc \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Create non-root user
RUN adduser --disabled-password --gecos '' appuser
RUN chown -R appuser:appuser /app
USER appuser

# Expose port
EXPOSE 8000

# Start application
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Multi-Stage Builds

Multi-stage builds help reduce image size by separating build dependencies from runtime dependencies:

# Multi-stage Dockerfile for Node.js
# Build stage
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Production stage
FROM node:18-alpine AS production

WORKDIR /app

# Copy only production dependencies and built app
COPY --from=builder /app/node_modules ./node_modules
COPY . .

# Create non-root user
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
RUN chown -R nextjs:nodejs /app
USER nextjs

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

Docker Compose

Docker Compose allows you to define and run multi-container applications:

Installation

# Download Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Make executable
sudo chmod +x /usr/local/bin/docker-compose

# Verify installation
docker-compose --version

Docker Compose Example

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/myapp
    depends_on:
      - db
      - redis
    restart: unless-stopped

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

  redis:
    image: redis:7-alpine
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - app
    restart: unless-stopped

volumes:
  postgres_data:

Docker Compose Commands

# Start services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down

# Rebuild and start
docker-compose up --build -d

# Scale services
docker-compose up --scale app=3 -d

Production Deployment Strategies

Docker Swarm

# Initialize swarm
docker swarm init

# Deploy stack
docker stack deploy -c docker-compose.yml myapp

# List services
docker service ls

# Scale service
docker service scale myapp_app=3

# Update service
docker service update --image myapp:v2 myapp_app

Environment Variables and Secrets

# .env file
NODE_ENV=production
DATABASE_URL=postgresql://user:password@db:5432/myapp
JWT_SECRET=your-secret-key

# Using secrets in Docker Swarm
echo "my-secret-password" | docker secret create db_password -

# docker-compose.yml with secrets
version: '3.8'

services:
  app:
    image: myapp:latest
    secrets:
      - db_password
    environment:
      - DATABASE_PASSWORD_FILE=/run/secrets/db_password

secrets:
  db_password:
    external: true

Best Practices

Security Best Practices

  • Use official base images from trusted sources
  • Keep images updated with security patches
  • Run containers as non-root users
  • Use multi-stage builds to reduce attack surface
  • Scan images for vulnerabilities
  • Use secrets management for sensitive data

Performance Optimization

  • Use .dockerignore to exclude unnecessary files
  • Minimize the number of layers
  • Use specific tags instead of 'latest'
  • Leverage build cache effectively
  • Use Alpine Linux for smaller images

Sample .dockerignore

node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.cache
.DS_Store

Monitoring and Logging

Container Monitoring

# View container stats
docker stats

# View container logs
docker logs -f container_name

# Execute commands in running container
docker exec -it container_name bash

# Copy files from container
docker cp container_name:/app/file.txt ./file.txt

Health Checks

# Dockerfile health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# Docker Compose health check
services:
  app:
    build: .
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

CI/CD Integration

GitHub Actions Example

# .github/workflows/docker.yml
name: Docker Build and Push

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2
    
    - name: Login to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}
    
    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: myapp:latest,myapp:${{ github.sha }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

Troubleshooting Common Issues

Container Won't Start

  • Check logs: docker logs container_name
  • Verify port bindings
  • Check environment variables
  • Ensure dependencies are available

Performance Issues

  • Monitor resource usage: docker stats
  • Optimize Dockerfile for layer caching
  • Use appropriate base images
  • Configure resource limits

Conclusion

Docker containerization provides a robust foundation for modern application deployment. By following these best practices and examples, you can create efficient, secure, and scalable containerized applications. Remember to keep security, performance, and maintainability in mind throughout your containerization journey.

Ready to deploy your containerized applications? Get started with RexZ Cloud VPS hosting with Docker pre-installed and optimized for container workloads.

Related Articles

VPS Setup

Complete VPS Setup Guide: Installing Python, Node.js, Nginx & Essential Tools

Complete step-by-step guide to setting up a VPS from scratch. Learn to install Python, Node.js, Nginx, databases, and essential development tools with security best practices.

25 min read1/20/2025

Enjoyed This Article?

Subscribe to our newsletter for more hosting tips, tutorials, and industry insights

Powered by RexZ Development