What is Docker?
Think of Docker like shipping containers for software. Before shipping containers, loading cargo was chaotic - different sizes, shapes, and handling requirements. Shipping containers standardized everything.
Docker does the same for software. It packages your application with everything it needs (code, runtime, libraries, settings) into a standardized container that runs the same way everywhere.
THE PROBLEM DOCKER SOLVES:
Developer: "It works on my machine!"
Operations: "Well, it doesn't work on the server..."
WITH DOCKER:
┌─────────────────────────────────────┐
│ Docker Container │
│ ┌─────────────────────────────┐ │
│ │ Your Application │ │
│ │ + Java Runtime │ │
│ │ + Dependencies │ │
│ │ + Configuration │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
Runs the same EVERYWHERE!
Why Use Docker?
- Consistency: Same environment from development to production
- Isolation: Each container is independent, no conflicts
- Portability: Run on any machine with Docker installed
- Speed: Containers start in seconds, not minutes like VMs
- Scalability: Easily run multiple instances
- Version Control: Version your infrastructure like code
Key Concepts
Image vs Container
IMAGE = Recipe (Blueprint)
- Read-only template
- Contains instructions to create a container
- Can be shared and reused
CONTAINER = Dish (Running Instance)
- Running instance of an image
- Has its own isolated environment
- Can be started, stopped, deleted
Analogy:
Image = Cookie Cutter
Container = Cookie (made from the cutter)
Dockerfile
A text file with instructions to build an image - like a recipe for your container.
# Dockerfile for a Spring Boot application
# Start from a base image with Java
FROM eclipse-temurin:17-jdk-alpine
# Set working directory inside container
WORKDIR /app
# Copy the JAR file
COPY target/myapp.jar app.jar
# Expose the port your app runs on
EXPOSE 8080
# Command to run when container starts
ENTRYPOINT ["java", "-jar", "app.jar"]
Essential Docker Commands
# BUILD an image from Dockerfile
docker build -t myapp:1.0 .
# RUN a container from an image
docker run -p 8080:8080 myapp:1.0
# LIST running containers
docker ps
# LIST all containers (including stopped)
docker ps -a
# STOP a container
docker stop container_id
# REMOVE a container
docker rm container_id
# LIST images
docker images
# REMOVE an image
docker rmi image_id
# VIEW container logs
docker logs container_id
# EXECUTE command in running container
docker exec -it container_id /bin/sh
Dockerfile Best Practices
# GOOD: Multi-stage build (smaller final image)
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# This results in a smaller image because:
# - Build stage has Maven + JDK (large)
# - Final image only has JRE + JAR (small)
Docker Compose
When you need multiple containers (app + database + cache), Docker Compose manages them all with one file.
# docker-compose.yml
version: '3.8'
services:
# Your Spring Boot application
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=secret
depends_on:
- db
- redis
# PostgreSQL database
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=mydb
- POSTGRES_PASSWORD=secret
volumes:
- postgres_data:/var/lib/postgresql/data
# Redis cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Docker Compose Commands
# Start all services
docker-compose up
# Start in background (detached)
docker-compose up -d
# Stop all services
docker-compose down
# View logs
docker-compose logs -f
# Rebuild and start
docker-compose up --build
When to Use Docker?
USE DOCKER WHEN:
✓ You want consistent environments across dev/staging/prod
✓ Working with microservices
✓ Need easy local development setup for new team members
✓ Deploying to cloud platforms (AWS, Azure, GCP)
✓ Running CI/CD pipelines
MIGHT NOT NEED DOCKER WHEN:
✓ Simple scripts or one-off tasks
✓ Legacy applications that are hard to containerize
✓ Learning basic programming (adds complexity)
Best Practices
- Use official base images: They're secure and well-maintained
- Keep images small: Use Alpine variants, multi-stage builds
- Don't run as root: Create a non-root user in your Dockerfile
- Use .dockerignore: Exclude unnecessary files from build context
- Tag your images: Use meaningful version tags, not just "latest"
- Use environment variables: For configuration that changes between environments
Master Docker with Expert Mentorship
Our Full Stack Java program covers Docker containerization and deployment. Learn to deploy microservices with guidance from industry experts.
Explore Java Program