Bài 26: Docker Compose cho môi trường service nhỏ

<style id="sas-global-polish">
html,body{overflow-x:hidden!important;max-width:100%!important}body #masthead.site-header{position:sticky!important;top:0!important;z-index:100!important;background:rgba(255,255,255,.94)!important;border-bottom:1px solid #e6edf6!important;box-shadow:0 10px 30px rgba(15,23,42,.055)!important;backdrop-filter:blur(14px)!important}body #masthead .site-title-centered{max-width:1320px!important;margin:0 auto!important;padding:10px 24px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:28px!important}body #masthead .site-branding{display:flex!important;align-items:center!important;min-width:250px!important;margin:0!important;padding:0!important;text-align:left!important}body #masthead .site-title{margin:0!important;line-height:1!important;display:flex!important;align-items:center!important}body #masthead img.custom-logo{width:190px!important;max-width:190px!important;height:auto!important;display:block!important}body #masthead .site-description,body #masthead .social-links,body #masthead .top-search{display:none!important}body #masthead .main-navbar{flex:1!important;background:transparent!important;border:0!important;box-shadow:none!important;margin:0!important;padding:0!important}body #masthead .main-navbar .container{max-width:none!important;width:100%!important;margin:0!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:flex-end!important}body #site-navigation{display:flex!important;justify-content:flex-end!important;width:auto!important;float:none!important;margin:0!important;padding:0!important}body #site-navigation ul.main-menu{display:flex!important;align-items:center!important;justify-content:flex-end!important;gap:6px!important;margin:0!important;padding:0!important;list-style:none!important;flex-wrap:wrap!important}body #site-navigation ul.main-menu>li{margin:0!important;padding:0!important;float:none!important;display:block!important}body #site-navigation ul.main-menu>li>a{display:flex!important;align-items:center!important;min-height:38px!important;padding:9px 13px!important;border-radius:999px!important;color:#334155!important;font-size:14px!important;font-weight:800!important;line-height:1!important;text-decoration:none!important;background:transparent!important;transition:.18s ease!important}body #site-navigation ul.main-menu>li.current-menu-item>a,body #site-navigation ul.main-menu>li>a:hover{background:#eff6ff!important;color:#1d4ed8!important}body.content-sidebar #primary,body #primary.content-area,body #primary,body .content-area{float:none!important;width:100%!important;max-width:100%!important;display:block!important;padding:0!important;margin:0!important}body #secondary,body aside#secondary,body .sidebar.widget-area,body .widget-area{display:none!important;visibility:hidden!important;width:0!important;max-width:0!important;padding:0!important;margin:0!important}body #content.site-content,body #content .container,body #content .inside,body .site-content,body .container,body .inside,body #main.site-main{width:100%!important;max-width:100%!important;padding-left:0!important;padding-right:0!important;margin-left:0!important;margin-right:0!important}body:not(.page-id-11) .entry-header,body:not(.page-id-11) .entry-content,body:not(.page-id-11) .entry-footer{max-width:980px!important;margin-left:auto!important;margin-right:auto!important;padding-left:22px!important;padding-right:22px!important}body.archive #main,body.blog #main,body.search #main{max-width:1180px!important;margin:0 auto!important;padding:28px 22px!important}@media(max-width:920px){body #masthead .site-title-centered{display:block!important;padding:10px 16px!important}body #masthead .site-branding{justify-content:center!important;margin-bottom:10px!important}body #masthead img.custom-logo{width:170px!important}body #site-navigation,body #site-navigation ul.main-menu{justify-content:center!important}body #site-navigation ul.main-menu>li>a{font-size:13px!important;padding:8px 10px!important}}@media(max-width:560px){body #site-navigation ul.main-menu{gap:4px!important}body #site-navigation ul.main-menu>li>a{font-size:12px!important;padding:7px 9px!important}body #masthead img.custom-logo{width:150px!important}body:not(.page-id-11) .entry-header,body:not(.page-id-11) .entry-content,body:not(.page-id-11) .entry-footer{padding-left:14px!important;padding-right:14px!important}}
</style>
<style>.sas-lesson{max-width:940px;margin:0 auto;padding:38px 18px 78px;font-family:Inter,"Segoe UI",Arial,sans-serif;color:#344054;font-size:17px;line-height:1.86}.sas-lesson h1,.sas-lesson h2,.sas-lesson h3{color:#172033;letter-spacing:-.02em;line-height:1.22}.sas-lesson h1{font-size:clamp(34px,5vw,56px);margin:0 0 18px}.sas-lesson h2{font-size:29px;margin:38px 0 13px}.sas-lesson h3{font-size:22px;margin:26px 0 10px}.sas-lesson .lead{font-size:18px;color:#667085;line-height:1.78}.sas-lesson .box,.sas-lesson .lab,.sas-lesson .warn,.sas-lesson .check,.sas-lesson .note{padding:20px 22px;border:1px solid #e4e7ec;border-radius:18px;background:#f8fafc;margin:23px 0}.sas-lesson .warn{background:#fff7ed;border-color:#fed7aa}.sas-lesson .lab{background:#eff6ff;border-color:#bfdbfe}.sas-lesson .check{background:#ecfdf3;border-color:#bbf7d0}.sas-lesson .note{background:#f5f3ff;border-color:#ddd6fe}.sas-lesson code{background:#eef2ff;padding:2px 6px;border-radius:6px;color:#1e3a8a}.sas-lesson pre{background:#0b1220;color:#dbeafe;padding:18px;border-radius:15px;overflow:auto;font-size:14px;line-height:1.72}.sas-lesson ul,.sas-lesson ol{line-height:1.86}.sas-lesson table{width:100%;border-collapse:collapse;margin:18px 0}.sas-lesson th,.sas-lesson td{border:1px solid #e4e7ec;padding:11px;text-align:left;vertical-align:top}.sas-lesson th{background:#f8fafc;color:#172033}.sas-lesson .next{margin-top:30px;padding:18px;border-radius:16px;background:#eff6ff;border:1px solid #bfdbfe}</style><div class="sas-lesson"><h1>Bài 26: Docker Compose cho môi trường service nhỏ</h1><p class="lead">Bài này chi tiết hóa Docker Compose theo hướng thực hành: có lab, lệnh mẫu, tình huống thực tế, checklist và bài tập.</p><div class="box"><strong>Sau bài này anh sẽ biết:</strong><ul><li>Docker Compose giải quyết vấn đề gì trong DevOps thực tế.</li><li>Các khái niệm/lệnh quan trọng cần nhớ.</li><li>Cách dựng lab nhỏ để thực hành.</li><li>Cách kiểm tra, rollback và ghi chú vận hành.</li></ul></div><h2>1. Bối cảnh thực tế</h2><p>Docker Compose thuộc nhóm kỹ năng giúp tự động hóa, chuẩn hóa và vận hành hệ thống ở quy mô lớn hơn. Khi server/app nhiều lên, thao tác tay sẽ dễ sai; vì vậy cần quy trình, công cụ và checklist rõ ràng.</p><h2>2. Khái niệm cần nắm</h2><ul><li><strong>State:</strong> trạng thái hiện tại của hệ thống hoặc ứng dụng.</li><li><strong>Config as code:</strong> cấu hình được lưu thành file để review, tái sử dụng.</li><li><strong>Idempotent:</strong> chạy nhiều lần vẫn cho kết quả ổn định.</li><li><strong>Rollback:</strong> quay lại trạng thái an toàn khi triển khai lỗi.</li></ul><h2>3. Lab thực hành</h2><div class="lab"><strong>Mục tiêu:</strong> chạy thử luồng thao tác tối thiểu, hiểu output và biết kiểm tra kết quả.</div><pre>mkdir compose-lab && cd compose-lab
cat > docker-compose.yml <<'EOF'
services:
web:
image: nginx:alpine
ports:
– "8080:80"
restart: unless-stopped
EOF
docker compose config
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080
docker compose logs -f –tail=50
docker compose down</pre><h2>4. Tình huống thực tế</h2><div class="note"><p>Anh cần chạy một service nhỏ gồm web/app/database. Docker Compose giúp mô tả toàn bộ stack trong một file, dễ đưa vào Git và dễ khởi động lại trên server khác.</p></div><h2>5. Quy trình áp dụng an toàn</h2><ol><li>Viết cấu hình hoặc command trong môi trường lab.</li><li>Kiểm tra syntax/plan/status trước khi apply.</li><li>Chạy với phạm vi nhỏ trước.</li><li>Quan sát log, metric và health check.</li><li>Ghi lại thay đổi vào tài liệu vận hành.</li><li>Chuẩn bị rollback hoặc version trước đó.</li></ol><h2>6. Lỗi thường gặp</h2><ul><li>Copy cấu hình từ mạng mà không hiểu biến/môi trường.</li><li>Không lưu file cấu hình vào Git.</li><li>Không kiểm tra log sau khi apply.</li><li>Không có môi trường test/staging.</li></ul><div class="warn"><strong>Lưu ý production:</strong> Công cụ tự động hóa giúp làm nhanh hơn, nhưng cũng có thể làm sai hàng loạt nhanh hơn. Luôn giới hạn phạm vi khi mới triển khai.</div><h2>7. Checklist</h2><div class="check"><ul><li>Có file cấu hình rõ ràng.</li><li>Có bước kiểm tra trước khi apply.</li><li>Có log/health check sau khi apply.</li><li>Có rollback/version cũ.</li><li>Có tài liệu ai chạy, chạy khi nào, kết quả gì.</li></ul></div><h2>8. Bài tập</h2><ol><li>Dựng một lab nhỏ theo lệnh mẫu.</li><li>Chạy lệnh kiểm tra trạng thái trước/sau.</li><li>Tạo một lỗi cấu hình nhỏ và sửa lại.</li><li>Viết checklist production cho chủ đề này.</li></ol><div class="next"><strong>Bài tiếp theo:</strong> Ansible nhập môn cho tự động hóa SysAdmin</div></div>

Chốt ý nhanh

Chủ đề Điểm cần nhớ
Docker Compose Giúp định nghĩa nhiều service trong một file, phù hợp cho lab và môi trường nhỏ.
Góc nhìn SysAdmin Quan trọng là hiểu service nào phụ thuộc service nào, port nào publish ra ngoài và volume nào giữ dữ liệu.
Rủi ro Compose tiện, nhưng nếu không quản lý restart, health check và data volume thì production nhỏ vẫn rất dễ vỡ.

Phần thực hành mở rộng: Docker Compose theo tư duy dựng một stack nhỏ nhưng rõ ràng

Nhiều người mới học Docker Compose chỉ copy YAML rồi chạy. Cách đó giúp service lên nhanh, nhưng không giúp hiểu hệ thống. Bài này nên làm cho người học nhìn được quan hệ giữa web, database, volume, network và thứ tự khởi động.

Lab 1: Dựng stack web + database tối thiểu

mkdir -p ~/compose-lab && cd ~/compose-lab
cat <<'EOF' > docker-compose.yml
services:
  db:
    image: mariadb:11
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: appdb
    volumes:
      - db_data:/var/lib/mysql
  adminer:
    image: adminer
    ports:
      - "8080:8080"
    depends_on:
      - db
volumes:
  db_data:
EOF
docker compose up -d
docker compose ps

Mục tiêu là hiểu một file Compose có thể mô tả nhiều service liên quan với nhau như thế nào.

Lab 2: Đọc log và health của từng service

docker compose logs --tail=50
docker compose logs db
docker compose logs adminer
docker compose ps

Đây là phản xạ rất thực tế: khi stack không lên, phải đọc từng service thay vì chỉ nhìn câu “Exited”.

Lab 3: Kiểm tra volume dữ liệu

docker volume ls
docker volume inspect compose-lab_db_data || docker volume inspect db_data
docker compose down
docker compose up -d

Lab này giúp người học thấy rõ: tắt stack không đồng nghĩa mất dữ liệu nếu volume được gắn đúng.

Lab 4: Thêm biến môi trường và file .env

cat <<'EOF' > .env
APP_PORT=8080
DB_NAME=appdb
EOF

Từ đây, anh có thể chỉ ra vì sao tách cấu hình ra khỏi YAML giúp chỉnh môi trường dễ hơn và giảm hard-code.

Lab 5: Nhận diện rủi ro production nhỏ

  • database và app cùng một host nên host là single point of failure
  • chưa có backup volume/database
  • chưa có health check rõ ràng
  • port publish có thể quá rộng nếu mở public

Tình huống thực tế

Một doanh nghiệp nhỏ thường chạy 2–4 service trên một VPS bằng Compose: web, app, database, reverse proxy. Nếu người vận hành không nắm dependency, log và volume, chỉ một lần restart hoặc update image cũng có thể làm đứt cả stack.

Lỗi phổ biến

  • Dùng depends_on rồi tưởng service phụ thuộc đã “sẵn sàng”, trong khi thật ra mới chỉ “được khởi động”.
  • Không backup dữ liệu volume.
  • Chỉnh YAML trực tiếp mà không kiểm tra lại bằng docker compose config.
  • Mở port database public không cần thiết.

Kết bài

Nếu bài này ngấm, anh sẽ nhìn Docker Compose như một bản mô tả hạ tầng nhỏ gọn chứ không chỉ là file để copy-paste. Từ đây sang Ansible, câu chuyện sẽ tiến thêm một bước: không chỉ chạy nhiều service, mà còn tự động hóa cách cấu hình nhiều máy.

Tác giả: Mạnh Hoàng

Tôi là Hoàng Mạnh, người sáng lập blog SysadminSkills.com. Tôi viết về quản trị hệ thống, bảo mật máy chủ, DevOps và cách ứng dụng AI để tự động hóa công việc IT. Blog này là nơi tôi chia sẻ những gì đã học được từ thực tế – đơn giản, ngắn gọn và áp dụng được ngay.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *