Devops
Em có dùng Docker để chạy app chưa ? Một file Dockerfile mẫu trông như thế nào ? Và em tối ưu dockerfile thế nào ?
Dạ, em đã dùng Docker để đóng gói và chạy ứng dụng Spring Boot trong nhiều dự án. Em xin trả lời như sau:
✅ Mục đích dùng Docker trong dự án
Đóng gói ứng dụng thành image chạy ổn định ở mọi môi trường.
Dễ dàng triển khai lên môi trường dev/staging/prod.
Kết hợp với
docker-compose
để chạy nhiều service: app, database, Redis, Elasticsearch,...
🧾 Dockerfile mẫu cho Spring Boot (Java 17 hoặc 21)
# Base image nhẹ
FROM eclipse-temurin:21-jdk-alpine
# Thêm metadata (tuỳ chọn)
LABEL maintainer="yourname@example.com"
# Tạo thư mục app
WORKDIR /app
# Copy file JAR vào container
COPY target/myapp.jar app.jar
# Expose port
EXPOSE 8080
# Run app
ENTRYPOINT ["java", "-jar", "app.jar"]
🧠 Tối ưu Dockerfile như thế nào?
✅ Dùng image base nhỏ như
alpine
để giảm kích thước.Ví dụ:
temurin:21-jdk-alpine
thay vìopenjdk:21
.
✅ Dùng multi-stage build để không copy cả Maven vào image cuối:
# Stage 1: Build
FROM maven:3.9-eclipse-temurin-21-alpine AS build
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
# Stage 2: Runtime
FROM eclipse-temurin:21-jdk-alpine
WORKDIR /app
COPY --from=build /app/target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
✅ Chỉ copy những gì cần (tránh COPY toàn bộ nếu không cần thiết).
✅ Giảm layer build: dùng ít RUN, COPY,... gộp khi hợp lý.
✅ Chạy ứng dụng không dưới root (nâng cao bảo mật – tuỳ theo yêu cầu hệ thống).
🔧 Kinh nghiệm thực tế
Trong dự án OCOP em đang làm, em dùng Docker để build từng service như
user-service
,product-service
, rồi dùngdocker-compose.yml
để cấu hình network chung, mount volume cho database, cấu hình biến môi trường.env
, v.v. Em cũng dùng multi-stage build để giữ image nhỏ, dễ deploy lên cloud.
CI/CD là gì ? Em đã từng thiết lập pipeline chưa ?
Dạ, em xin trả lời như sau:
✅ CI/CD là gì?
CI (Continuous Integration): Tích hợp liên tục — code mới được merge vào repo sẽ tự động build, test để phát hiện lỗi sớm.
CD (Continuous Delivery / Deployment): Triển khai liên tục — sau khi code qua test, hệ thống sẽ tự động deploy lên môi trường staging hoặc production.
➡️ Mục tiêu: tăng tốc độ release, giảm lỗi do thao tác tay.
🧱 Các bước thường thấy trong một CI/CD pipeline
Checkout source code từ GitHub/GitLab.
Build project (ví dụ:
mvn clean package
).Run unit test, kiểm tra static code (
checkstyle
,PMD
, v.v.).Build Docker image nếu là microservice.
Push image lên Docker Registry (DockerHub, GitLab Registry,...).
Deploy lên môi trường: staging/prod (dùng Docker Compose, Kubernetes, AWS ECS, v.v.).
🛠️ Em đã từng thiết lập CI/CD với những công cụ sau:
GitHub Actions: phổ biến, dễ dùng.
GitLab CI/CD: hỗ trợ Docker Registry tích hợp.
Jenkins: tùy biến mạnh, dùng trong dự án lớn hơn.
🔧 Ví dụ: GitHub Actions cho Spring Boot + Docker
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [ "main" ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '21'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Build Docker Image
run: docker build -t myapp:latest .
- name: Push to DockerHub
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
docker tag myapp:latest your-docker-username/myapp:latest
docker push your-docker-username/myapp:latest
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
docker pull your-docker-username/myapp:latest
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 8080:8080 your-docker-username/myapp:latest
💡 Kinh nghiệm thực tế
Trong dự án OCOP, em thiết lập pipeline để mỗi lần push code lên nhánh main
, GitHub Actions sẽ tự:
Build app, push Docker image,
SSH vào server staging và deploy bằng Docker,
Giảm thời gian deploy từ 20 phút thủ công xuống còn ~2 phút tự động.
Tất cả hoạt động như thế nào
Nhà phát triển đẩy mã: Thay đổi được cam kết lên kho Git.
Quy trình kích hoạt: Hệ thống CI/CD phát hiện thay đổi và bắt đầu quy trình.
Xây dựng Maven: Maven biên dịch mã, giải quyết phụ thuộc và đóng gói artifact.
Kiểm thử tự động: Kiểm thử đơn vị và tích hợp chạy để xác minh chức năng.
Kiểm tra độ phủ: JaCoCo đo độ phủ kiểm thử và áp đặt ngưỡng tối thiểu.
Phân tích tĩnh: Checkstyle, SpotBugs và PMD quét mã để tìm lỗi về kiểu, lỗi và mùi mã.
Phân tích SonarCloud: Kết quả được gửi đến SonarCloud, nơi áp dụng cổng chất lượng.
Quản lý artifact: Artifact được tải lên kho như Nexus.
Triển khai phát triển: Artifact được triển khai lên môi trường phát triển để kiểm tra thêm.
Cổng chất lượng: Nếu bất kỳ cổng nào (độ phủ, lỗi, vi phạm kiểu) thất bại, quy trình dừng và nhà phát triển được thông báo.
Khi deploy ứng dụng lên server em cần lưu ý gì để bảo mật và tối ưu memory ?
Khi deploy ứng dụng Java (Spring Boot) lên server, cần lưu ý các điểm sau để bảo mật và tối ưu memory:
🔐 Bảo mật:
Ẩn thông tin nhạy cảm: Dùng biến môi trường hoặc external config (
application-prod.properties
) thay vì hard-code.Cấu hình HTTPS: Bắt buộc dùng TLS (HTTPS), cài đặt SSL cert hợp lệ.
Giới hạn CORS: Chỉ cho phép domain đáng tin cậy.
Ẩn lỗi chi tiết: Không expose stacktrace hoặc thông báo lỗi ở production.
Bảo vệ endpoint: Dùng Spring Security với JWT/OAuth2 và phân quyền rõ ràng.
Cập nhật dependencies: Luôn dùng phiên bản cập nhật, tránh CVE.
Tắt actuator endpoints không cần thiết: Chỉ mở
/health
,/info
nếu cần, và cần bảo vệ bằng auth.
🧠 Tối ưu memory:
Cấu hình JVM tối ưu: Dùng flags như
-Xms
,-Xmx
, GC phù hợp (G1GC cho hầu hết use case).Giới hạn thread pool: Điều chỉnh
Tomcat max-threads
, connection pool size hợp lý.Dùng caching: Redis/Guava để tránh truy vấn DB lặp lại.
Giải phóng resource đúng cách: Đóng connection, stream, tránh memory leak.
Dùng profiler: Như VisualVM hoặc Prometheus + Grafana để monitor heap, GC, threads.
Giám sát ứng dụng trong production em dùng công cụ nào ? Alert khi nào ?
Dạ, trong production em thường dùng Prometheus + Grafana để giám sát metric hệ thống như CPU, memory, HTTP request, DB connection pool. Em kết hợp với Spring Boot Actuator + Micrometer để expose các metric cho Prometheus scrape.
Log thì em dùng ELK Stack để tập trung log từ nhiều service, dễ theo dõi và truy vấn khi có sự cố. Ngoài ra, em tích hợp Alertmanager để cảnh báo qua Slack hoặc email.
Em cấu hình alert khi:
Memory sử dụng > 80%, hoặc GC xảy ra liên tục.
HTTP 5xx tăng cao, thường > 5% trong 5 phút.
Response time vượt ngưỡng, ví dụ > 2s.
DB connection pool đầy, có thể gây nghẽn.
Hoặc khi service không phản hồi
/health
.
Mục tiêu là phát hiện sớm trước khi ảnh hưởng đến người dùng.
Cách triển khai blue-green deployment là gì ?
Dạ, blue-green deployment là chiến lược deploy giúp giảm downtime và rollback dễ dàng. Cách triển khai như sau:
Có 2 môi trường giống nhau:
Blue (hiện tại đang chạy production)
Green (chứa version mới chuẩn bị deploy)
Triển khai phiên bản mới lên môi trường Green.
Test kỹ môi trường Green (integration, smoke test...).
Khi ổn, chuyển traffic từ Blue sang Green (bằng load balancer hoặc DNS switch).
Nếu có lỗi, rollback nhanh về Blue.
Mô hình này giúp deploy không downtime, an toàn hơn khi cập nhật version mới. Em thường áp dụng với Kubernetes hoặc CI/CD tool như ArgoCD, Jenkins kết hợp NGINX hoặc Istio.
Em đã dùng NGINX reverse proxy trong dự án chưa ?
Dạ rồi, em đã dùng NGINX làm reverse proxy trong một số dự án Spring Boot. Em cấu hình NGINX để:
Chuyển tiếp request từ cổng 80/443 đến cổng nội bộ của ứng dụng (thường là 8080).
Kết hợp SSL (Let's Encrypt) để serve HTTPS.
Cấu hình load balancing cho các instance chạy phía sau.
Thêm cache static content (ảnh, CSS, JS) để giảm tải cho backend.
Giới hạn request rate và chặn IP lạ để tăng bảo mật.
Cụ thể, em dùng file cấu hình như sau để redirect về ứng dụng Java:
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Ngoài ra, em cũng từng dùng NGINX để phục vụ frontend (Vue/Nuxt) và reverse proxy đến backend API.
Mô tả flow cơ bản của CI/CD từ commit đến deploy.
Dạ, flow CI/CD cơ bản gồm các bước sau:
Developer commit code lên Git (GitHub/GitLab/Bitbucket).
CI tool (như Jenkins, GitHub Actions, GitLab CI) được trigger tự động.
Pipeline chạy các bước:
Build
: Compile code (Maven/Gradle).Test
: Unit test, integration test.Static analysis
: Checkstyle, SonarQube nếu có.Package
: Tạo file JAR/WAR hoặc Docker image.
Push artifact lên registry:
Docker Hub hoặc private registry (Harbor, GitHub Container Registry).
CD phase:
Deploy image sang môi trường dev/staging để kiểm thử.
Nếu ổn, deploy tiếp sang production (thường dùng blue-green hoặc rolling update).
Thông báo kết quả qua Slack/email.
Em thường dùng GitHub Actions hoặc GitLab CI kèm Docker và Kubernetes để deploy tự động.
Khi deploy app có traffic cao em cần lưu ý điều gì ?
Dạ, khi deploy ứng dụng có traffic cao, em lưu ý các điểm sau:
🧠 Hiệu năng & Tài nguyên:
Tăng số replica (scale horizontal) để xử lý tải cao.
Cấu hình JVM tối ưu:
Xms
,Xmx
, GC tuning.Connection pool (HikariCP): phải đủ lớn để không nghẽn DB.
🌐 Load balancing & Network:
Load balancer (NGINX/Istio) chia đều traffic.
Keepalive & timeout cấu hình hợp lý để tránh timeout đột ngột.
💾 Caching:
Dùng Redis hoặc cache nội bộ để giảm tải DB.
Cache các request đọc phổ biến (top sản phẩm, trang chủ...).
⚠️ Zero downtime deployment:
Dùng rolling update hoặc blue-green để tránh gián đoạn.
🔔 Monitoring & Auto-scaling:
Dùng Prometheus + Grafana để theo dõi real-time.
Kết hợp HPA (Horizontal Pod Autoscaler) nếu dùng Kubernetes.
🔒 Rate limit & fallback:
Áp dụng rate limiting, circuit breaker (Resilience4j) cho các service critical.
Tất cả nhằm đảm bảo hệ thống không bị nghẽn, gián đoạn khi lượng người dùng tăng đột biến.
Last updated