Docker

What is Docker?

Docker is a platform for developing, shipping, and running applications in containers. Containers package an application with all its dependencies, ensuring it runs consistently across different environments.

Dockerfile

# Angular Application
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build --prod

FROM nginx:alpine
COPY --from=build /app/dist/my-app /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# .NET Application
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "./"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 80
ENTRYPOINT ["dotnet", "MyApp.dll"]
# Node.js Application
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

Docker Commands

# Build image
docker build -t myapp:latest .

# Run container
docker run -d -p 3000:3000 --name myapp myapp:latest

# List containers
docker ps
docker ps -a

# Stop container
docker stop myapp

# Remove container
docker rm myapp

# View logs
docker logs myapp
docker logs -f myapp  # Follow

# Execute command in container
docker exec -it myapp sh

# Remove image
docker rmi myapp:latest

Multi-Stage Builds

# Optimized build
FROM node:18 AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:18 AS build
WORKDIR /app
COPY --from=dependencies /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:18-alpine AS production
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=dependencies /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

Docker Compose

# docker-compose.yml
version: '3.8'

services:
  # Angular frontend
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "4200:80"
    depends_on:
      - api
  
  # .NET API
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - "5000:80"
    environment:
      - ConnectionStrings__DefaultConnection=Server=db;Database=myapp;User=sa;Password=YourPassword123
    depends_on:
      - db
  
  # Node.js service
  service:
    build:
      context: ./service
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:postgres@postgres:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
  
  # SQL Server
  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=YourPassword123
    ports:
      - "1433:1433"
    volumes:
      - sqldata:/var/opt/mssql
  
  # PostgreSQL
  postgres:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=postgres
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
  
  # MongoDB
  mongodb:
    image: mongo:6
    ports:
      - "27017:27017"
    volumes:
      - mongodata:/data/db
  
  # Redis
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  sqldata:
  pgdata:
  mongodata:

Docker Networking

# Create network
docker network create myapp-network

# Run containers on same network
docker run -d --name api --network myapp-network api:latest
docker run -d --name frontend --network myapp-network frontend:latest

# Containers can communicate using service names
# frontend can access: http://api:5000

Environment Variables

# Dockerfile with env vars
FROM node:18-alpine
WORKDIR /app
COPY . .

ENV NODE_ENV=production
ENV PORT=3000

EXPOSE ${PORT}
CMD ["node", "index.js"]
# Run with env vars
docker run -e DATABASE_URL=postgresql://localhost/mydb \
           -e API_KEY=secret123 \
           myapp:latest

# Using env file
docker run --env-file .env myapp:latest

Volumes

# Named volume
docker run -v mydata:/app/data myapp:latest

# Bind mount
docker run -v $(pwd)/data:/app/data myapp:latest

# Read-only mount
docker run -v $(pwd)/config:/app/config:ro myapp:latest

Health Checks

FROM node:18-alpine
WORKDIR /app
COPY . .

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js

CMD ["node", "index.js"]
// healthcheck.js
const http = require('http');

const options = {
  host: 'localhost',
  port: 3000,
  path: '/health',
  timeout: 2000
};

const request = http.request(options, (res) => {
  if (res.statusCode === 200) {
    process.exit(0);
  } else {
    process.exit(1);
  }
});

request.on('error', () => process.exit(1));
request.end();

Best Practices

# 1. Use specific versions
FROM node:18.17.0-alpine

# 2. Use .dockerignore
# .dockerignore
node_modules
.git
.env
*.log

# 3. Minimize layers
RUN apt-get update && apt-get install -y \
    package1 \
    package2 \
    && rm -rf /var/lib/apt/lists/*

# 4. Use multi-stage builds
FROM node:18 AS build
# Build steps
FROM node:18-alpine AS production
# Production steps

# 5. Don't run as root
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs

# 6. Use COPY instead of ADD
COPY package*.json ./

# 7. Leverage build cache
COPY package*.json ./
RUN npm ci
COPY . .

CI/CD Integration

# GitHub Actions with Docker
name: Docker Build and Push

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - 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:${{ github.sha }},myapp:latest

Interview Tips

  • Explain Docker: Containerization platform
  • Show Dockerfile: Multi-stack examples
  • Demonstrate commands: Build, run, manage
  • Discuss Docker Compose: Multi-container apps
  • Mention best practices: Multi-stage, security
  • Show CI/CD: Integration with pipelines

Summary

Docker packages applications with dependencies into containers for consistent deployment across environments. Use Dockerfiles to define images. Docker Compose orchestrates multi-container applications. Supports all tech stacks including Angular, .NET, Node.js, and databases. Essential for modern DevOps and CI/CD pipelines.

Test Your Knowledge

Take a quick quiz to test your understanding of this topic.

Test Your Cicd Knowledge

Ready to put your skills to the test? Take our interactive Cicd quiz and get instant feedback on your answers.