Introduction to Docker
Build, ship, and run applications with containers
Docker is a platform for developing, shipping, and running applications in containers. Containers package an application with all its dependencies, ensuring consistency across development, testing, and production environments.
Why Docker?#
Consistency#
Containers include everything an application needs to run, eliminating "it works on my machine" problems.
Isolation#
Containers run in isolated environments, preventing conflicts between applications and improving security.
Portability#
Containers can run anywhere Docker is installed—on your laptop, in CI/CD pipelines, or in production clouds.
Efficiency#
Containers share the host OS kernel, making them lighter than virtual machines while providing similar isolation.
Core concepts#
Images#
An image is a read-only template containing instructions for creating a container. Images are built from Dockerfiles.
1FROM node:20-alpine2WORKDIR /app3COPY package*.json ./4RUN npm install5COPY . .6EXPOSE 30007CMD ["npm", "start"]Containers#
A container is a runnable instance of an image. Containers are isolated but can share resources with the host.
1# Run a container2docker run -d -p 3000:3000 my-app34# List running containers5docker ps67# Stop a container8docker stop <container-id>Dockerfile#
A Dockerfile is a text file containing instructions to build an image.
1# Base image2FROM python:3.11-slim34# Set working directory5WORKDIR /app67# Copy requirements8COPY requirements.txt .910# Install dependencies11RUN pip install --no-cache-dir -r requirements.txt1213# Copy application code14COPY . .1516# Run the application17CMD ["python", "app.py"]Docker Compose#
Docker Compose defines and runs multi-container applications.
1# docker-compose.yml2version: "3.9"3services:4 web:5 build: .6 ports:7 - "3000:3000"8 environment:9 - NODE_ENV=production10 depends_on:11 - redis1213 redis:14 image: redis:7-alpine15 volumes:16 - redis-data:/data1718volumes:19 redis-data:Building images#
Basic build#
1docker build -t my-app:latest .Multi-stage builds#
Reduce image size by using multi-stage builds:
1# Build stage2FROM node:20-alpine AS builder3WORKDIR /app4COPY package*.json ./5RUN npm ci6COPY . .7RUN npm run build89# Production stage10FROM node:20-alpine11WORKDIR /app12COPY --from=builder /app/dist ./dist13COPY --from=builder /app/node_modules ./node_modules14EXPOSE 300015CMD ["node", "dist/index.js"]Best practices#
Use specific image tags#
1# Good2FROM node:20.10-alpine34# Avoid5FROM node:latestMinimize layers#
Combine RUN commands to reduce layers:
1# Good2RUN apt-get update && \3 apt-get install -y curl && \4 rm -rf /var/lib/apt/lists/*Use .dockerignore#
Exclude unnecessary files from the build context:
1node_modules2.git3*.md4.envRun as non-root user#
1RUN addgroup -S appgroup && adduser -S appuser -G appgroup2USER appuserIntegration with DevOps Hub#
Build and push Docker images in your pipelines:
1stages:2 - name: build3 jobs:4 - name: docker-build5 runner: ubuntu-latest6 steps:7 - checkout8 - run: |9 docker build -t my-registry/my-app:${{ github.sha }} .10 docker push my-registry/my-app:${{ github.sha }}