aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa pipeline CI/CD từ commit đến deploy cho team nhỏ

Docker Compose: container đã chạy chưa chắc database đã sẵn sàng

Suong Nguyen by Suong Nguyen
22/10/2026
in DevOps
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn chạy docker compose up, database và API cùng khởi động, nhưng API báo không kết nối được. Chạy lại một lúc sau thì mọi thứ bình thường. Đây thường là khác biệt giữa tiến trình container đã được tạo và dịch vụ bên trong đã sẵn sàng nhận công việc.

Bài viết dành cho môi trường phát triển với Docker Compose plugin v2. Ví dụ chọn PostgreSQL 17 và Python 3.12 làm các image minh họa, không khẳng định đó là phiên bản mới nhất. Tài liệu được đối chiếu ngày 22/10/2026; cấu hình cần được chạy kiểm tra trong môi trường của bạn trước khi dùng cho hệ thống thật.

Ba điều kiện phục vụ ba mục đích

depends_on dạng danh sách thể hiện quan hệ khởi động, nhưng không tự chờ database sẵn sàng. Dạng đầy đủ cho phép chọn điều kiện tương ứng:

  • service_started: dịch vụ phụ thuộc đã được khởi động.
  • service_healthy: healthcheck của dịch vụ phụ thuộc đã đạt.
  • service_completed_successfully: một tác vụ như migration đã kết thúc thành công.

Hãy định nghĩa thứ ứng dụng thực sự cần. Nếu ứng dụng cần schema đã được tạo, kiểm tra cổng database mở vẫn chưa đủ. Nếu chỉ muốn chứng minh chuỗi khởi động, có thể dùng một ứng dụng demo nhỏ rồi thay nó bằng image của dự án.

Một ví dụ cục bộ với bước tạo schema

Lưu nội dung sau thành compose.yaml. HTTP server chỉ minh họa bước cuối sau migration; nó không phải API có truy vấn PostgreSQL.

services:
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: demo
      POSTGRES_DB: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}
    volumes:
      - demo_pg:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h 127.0.0.1 -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}"']
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 10s

  migrate:
    image: postgres:17-alpine
    environment:
      PGPASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
    command:
      - psql
      - -h
      - db
      - -U
      - demo
      - -d
      - app
      - -v
      - ON_ERROR_STOP=1
      - -c
      - CREATE TABLE IF NOT EXISTS startup_probe (id integer PRIMARY KEY);

  web:
    image: python:3.12-alpine
    working_dir: /tmp
    command: ['python', '-m', 'http.server', '8000']
    ports:
      - '127.0.0.1:8080:8000'
    depends_on:
      migrate:
        condition: service_completed_successfully

volumes:
  demo_pg:

pg_isready kiểm tra trạng thái nhận kết nối của PostgreSQL. Nó không chứng minh tài khoản ứng dụng đã có mọi quyền hoặc schema nghiệp vụ đã đúng. Bước migrate chạy một câu SQL thật với ON_ERROR_STOP=1, vì vậy lỗi SQL phải làm tác vụ thất bại thay vì cho bước sau tiếp tục như thể đã xong.

Dấu $$ giữ việc mở rộng biến cho shell bên trong container. Nếu dùng một dấu $ không đúng chỗ, Compose có thể thay giá trị từ môi trường máy chủ trước khi healthcheck chạy. Hai môi trường đó không nhất thiết chứa cùng giá trị.

Chạy và quan sát đúng từng lớp

Đặt POSTGRES_PASSWORD bằng một giá trị riêng cho thử nghiệm cục bộ, không commit vào repository và không dùng lại mật khẩu production. Kiểm tra phiên bản plugin và cú pháp trước khi khởi động:

docker compose version
docker compose config --quiet
docker compose up -d
docker compose ps -a
docker compose logs migrate
docker compose exec db psql -U demo -d app -c "SELECT to_regclass('public.startup_probe');"
curl http://127.0.0.1:8080

ps -a giúp bạn thấy cả tác vụ đã thoát như migration. Đừng xem trạng thái exited của tác vụ một lần là lỗi nếu exit code đúng bằng 0. Ngược lại, database healthy nhưng migration thất bại là dấu hiệu phải đọc log migration, không nên tăng thời gian chờ database theo cảm tính.

Các giá trị 5 giây, 3 giây và 10 lần trong ví dụ là tham số minh họa. Chúng chưa được đo trên workload của bạn. Điều chỉnh dựa trên thời gian khởi động thực tế, loại ổ đĩa và thao tác kiểm tra, thay vì sao chép rồi xem đó là một cam kết thời gian sẵn sàng.

Healthcheck không thay thế phục hồi kết nối

Một database có thể healthy lúc API khởi động rồi mất kết nối sau đó. Ứng dụng vẫn cần timeout, quản lý connection pool và chính sách retry phù hợp. Đừng để một tác vụ ghi nghiệp vụ bị retry vô hạn; nếu có khả năng tạo trùng, cần thiết kế hợp đồng idempotency riêng.

Cũng không nên suy từ depends_on rằng mọi lần container phụ thuộc bị lỗi đều tự động khởi động lại toàn bộ chuỗi. Điều kiện khởi động và hành vi phục hồi trong thời gian chạy là hai việc cần cấu hình, kiểm chứng riêng. Healthcheck phản ánh kết quả phép thử bạn viết, nên một lệnh chỉ kiểm tra “tiến trình tồn tại” có thể bỏ sót lỗi ứng dụng thật.

Lỗi dễ gặp khi sửa theo thói quen

Chèn sleep 30 có thể làm lần thử hiện tại qua được nhưng không gắn với điều kiện sẵn sàng. Tăng timeout kết nối cũng không sửa được sai hostname hoặc mật khẩu. Trong mạng Compose, hostname thường là tên service như db, không phải localhost của container API.

Khi thử lại database có named volume, nhớ rằng dữ liệu và cấu hình khởi tạo ban đầu có thể vẫn còn. Đổi biến khởi tạo không có nghĩa database cũ tự thay mọi tài khoản. Kiểm tra dữ liệu hiện có trước khi quyết định tạo môi trường mới; không xóa volume chỉ để che đi nguyên nhân lỗi.

Kết luận

Hãy dùng một điều kiện có thể quan sát cho mỗi chặng: database nhận kết nối, migration thành công, rồi ứng dụng khởi động. Sau khi chuỗi đó rõ ràng, tiếp tục kiểm chứng khả năng phục hồi khi một dịch vụ mất kết nối trong lúc hệ thống đang chạy.

Nguồn tham khảo

  • Docker: Control startup and shutdown order
  • Dockerfile reference: HEALTHCHECK
  • PostgreSQL 17: pg_isready

Tags: Docker ComposeHealthcheckPostgreSQL
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa pipeline CI/CD từ commit đến deploy cho team nhỏ

GitHub Actions: kiểm tra pull request Node.js trước khi merge

by Suong Nguyen
21/10/2026
0

Thiết lập một workflow kiểm tra lint, test và build cho pull request, dùng lockfile để cài dependency và đọc đúng kết quả CI.

Minh họa pipeline CI/CD từ commit đến deploy cho team nhỏ

CI/CD cơ bản cho team dev nhỏ

by admin
02/07/2026
0

CI/CD giúp team nhỏ giảm lỗi release bằng cách tự động hóa kiểm thử, build và deploy theo một quy trình có thể lặp lại.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native: tránh bàn phím che form với KeyboardAvoidingView và ScrollView
  • Phỏng vấn JavaScript: giải thích event loop, microtask và async/await
  • Deep link mobile an toàn: đúng domain chưa đủ, còn route và quyền đọc

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply