[Java Backend Zero to Hello] BÀI 7.4: DOCKER CƠ BẢN
📚 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 /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