0

[Java Backend Zero to Hello] BÀI 7.4: DOCKER CƠ BẢN

Java Backend Zero to Hello

📚 Bài viết thuộc series Java Backend Zero to Hello 📌 Phần: Phase 7: Testing & DevOps Cơ Bản | Bài 74/86


BÀI 7.4: DOCKER CƠ BẢN

Mục tiêu

  • Hiểu Docker và Container
  • Viết Dockerfile
  • Build và run container
  • Quản lý images và containers

1. DOCKER LÀ GÌ?

Docker là nền tảng đóng gói và chạy ứng dụng trong container - môi trường cô lập, nhẹ, portable.

Lợi ích

  • Consistency - "Works on my machine" không còn là vấn đề
  • Isolation - Mỗi app chạy độc lập
  • Portability - Chạy ở bất kỳ đâu có Docker
  • Efficiency - Nhẹ hơn VM

So sánh với VM

Container VM
Chia sẻ OS kernel OS riêng
Nhẹ (MB) Nặng (GB)
Khởi động giây Khởi động phút
Hiệu năng gần native Overhead lớn

2. CÀI ĐẶT

  • Windows/Mac: Docker Desktop
  • Linux: sudo apt install docker.io

Kiểm tra:

docker --version
docker run hello-world

3. CÁC KHÁI NIỆM

3.1 Image

Template để tạo container (giống class).

3.2 Container

Instance chạy từ image (giống object).

3.3 Dockerfile

File cấu hình để build image.

3.4 Registry

Nơi lưu trữ image (Docker Hub, AWS ECR, ...).

3.5 Volume

Lưu trữ persistent data.

3.6 Network

Kết nối giữa các container.


4. CÁC LỆNH CƠ BẢN

4.1 Image

docker images                    # Liệt kê images
docker pull nginx                # Tải image từ registry
docker rmi nginx                 # Xóa image
docker image prune               # Xóa image không dùng

4.2 Container

docker ps                        # Container đang chạy
docker ps -a                     # Tất cả container
docker run nginx                 # Chạy container
docker stop <id>                 # Dừng container
docker start <id>                # Khởi động lại
docker rm <id>                   # Xóa container
docker logs <id>                 # Xem log
docker exec -it <id> bash        # Vào container

4.3 Run với options

docker run -d                    # Chạy nền
docker run -p 8080:80            # Map port
docker run -v /host:/container  # Mount volume
docker run -e KEY=value         # Environment variable
docker run --name myapp         # Đặt tên
docker run --rm                  # Xóa sau khi dừng

5. DOCKERFILE CHO SPRING BOOT

5.1 Multi-stage build

# Stage 1: Build
FROM eclipse-temurin:17-jdk-jammy AS builder
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline -B

COPY src ./src
RUN ./mvnw package -DskipTests

# Stage 2: Runtime
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app

# Tạo user non-root
RUN addgroup --system spring && adduser --system spring --ingroup spring
USER spring:spring

COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

5.2 Build và run

docker build -t myapp:1.0 .
docker run -p 8080:8080 myapp:1.0

6. DOCKER COMPOSE

Chạy nhiều container cùng lúc.

6.1 docker-compose.yml

version: '3.8'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=password
    depends_on:
      - db
      - redis

  db:
    image: mysql:8
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=mydb
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:7
    ports:
      - "6379:6379"

volumes:
  mysql-data:

6.2 Các lệnh

docker-compose up                # Chạy
docker-compose up -d             # Chạy nền
docker-compose down              # Dừng và xóa
docker-compose logs              # Xem log
docker-compose ps                # Liệt kê services
docker-compose exec app bash     # Vào container

7. VOLUMES

# Tạo volume
docker volume create mydata

# Mount volume
docker run -v mydata:/data mysql

# Bind mount
docker run -v /host/path:/container/path nginx

Trong docker-compose:

services:
  db:
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

volumes:
  mysql-data:

8. NETWORK

# Tạo network
docker network create mynetwork

# Chạy container trong network
docker run --network mynetwork --name db mysql
docker run --network mynetwork --name app myapp

Trong docker-compose, các service tự động cùng network.


9. DOCKERFILE BEST PRACTICES

9.1 ✅ NÊN

# Dùng image nhỏ
FROM eclipse-temurin:17-jre-jammy

# Multi-stage build
FROM builder AS build
...

# Layer caching
COPY pom.xml ./
RUN mvn dependency:go-offline
COPY src ./src

# Non-root user
USER spring:spring

# .dockerignore

9.2 .dockerignore

target/
.git/
.idea/
*.iml
*.log

9.3 ❌ TRÁNH

# Không dùng latest
FROM openjdk:latest  # ❌

# Không chạy nhiều process
CMD java -jar app.jar && /bin/bash  # ❌

# Không copy toàn bộ
COPY . .  # ❌ (không có .dockerignore)

10. PUSH LÊN REGISTRY

10.1 Docker Hub

docker login
docker tag myapp:1.0 username/myapp:1.0
docker push username/myapp:1.0

10.2 Private Registry

docker tag myapp:1.0 registry.example.com/myapp:1.0
docker push registry.example.com/myapp:1.0

11. BÀI TẬP THỰC HÀNH

Bài 1: Dockerfile

Tạo Dockerfile cho Spring Boot app.

Bài 2: Docker Compose

Setup app + MySQL + Redis với docker-compose.

Bài 3: Multi-stage

Tối ưu Dockerfile với multi-stage build.


12. TÓM TẮT

Khái niệm Mô tả
Image Template
Container Instance chạy
Dockerfile Cấu hình build
Docker Compose Multi-container
Volume Persistent storage
Network Kết nối container
Registry Lưu trữ image

Bài tiếp theo: 7.5 Docker Compose


🧭 Điều Hướng Series

⬅️ Bài trước: BÀI 7.3: INTEGRATION TEST

📋 Lộ trình tổng quan: Xem Toàn Bộ Series

➡️ Bài tiếp theo: BÀI 7.5: DOCKER COMPOSE


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí