Docker cho phép nhiều ứng dụng dùng chung một VPS rất tiện, nhưng mặc định container không tự có giới hạn tài nguyên chặt chẽ. Một process lỗi, memory leak hoặc workload đột biến có thể chiếm phần lớn CPU/RAM của host và kéo theo các service khác. Bài viết này hướng dẫn đặt giới hạn CPU, RAM và PID bằng Docker CLI hoặc Docker Compose, giải thích OOM, swap, CPU throttling và cách chọn mức giới hạn dựa trên số liệu thực tế.
Khi chạy nhiều container trên cùng VPS, một câu hỏi rất quan trọng là: nếu một container bị memory leak hoặc CPU loop thì các container còn lại có bị ảnh hưởng không?
Có. Theo Docker Docs, mặc định container không có resource constraints và có thể dùng tài nguyên mà kernel host cho phép. Nếu RAM cạn, Linux có thể kích hoạt OOM killer; nếu CPU bị dùng hết, các service khác sẽ phải tranh scheduler time.
Vì vậy, resource limit không phải tối ưu “cho đẹp”. Nó là cách giới hạn blast radius khi một workload hoạt động bất thường.
Nếu bạn mới cài Docker, nên đọc trước bài Hướng dẫn cài Docker và Docker Compose trên VPS Ubuntu. Nếu VPS đã thường xuyên CPU cao, bài VPS Ubuntu CPU cao sẽ giúp xác định nguyên nhân trước khi đặt giới hạn.
Vì sao Docker container có thể chiếm hết tài nguyên VPS?
Container dùng chung kernel với host Linux. Docker sử dụng cgroup và scheduler của kernel để áp giới hạn CPU, memory, PID và một số loại I/O.
Nếu bạn không đặt giới hạn:
- container web có thể mở quá nhiều worker;
- Node.js/Python app bị memory leak có thể ăn dần RAM;
- job encode/build có thể dùng toàn bộ CPU;
- database container có thể mở cache/buffer quá lớn;
- fork bomb hoặc lỗi process có thể tạo quá nhiều PID;
- Docker daemon và service khác trên host bị cạnh tranh tài nguyên.
Resource limit không sửa bug ứng dụng, nhưng giúp một container khó kéo sập toàn bộ máy hơn.
Kiểm tra tài nguyên VPS trước khi đặt limit
Xem số CPU:
nproc
Xem RAM:
free -h
Xem Docker đang dùng gì:
docker stats
docker stats hiển thị gần realtime:
- CPU %;
- memory usage / limit;
- network I/O;
- block I/O;
- số PID.
Đừng đặt limit chỉ theo cảm giác. Hãy quan sát workload bình thường và peak trước.
Giới hạn RAM bằng docker run
Ví dụ giới hạn container ở 512 MB RAM:
docker run -d \
--name web \
--memory=512m \
nginx:alpine
Docker hỗ trợ -m hoặc --memory để đặt hard limit.
Kiểm tra:
docker inspect web --format '{{.HostConfig.Memory}}'
Nếu process trong container vượt giới hạn và không còn đường giải phóng memory, container có thể bị OOM kill.
Memory reservation khác memory limit thế nào?
Docker có hai khái niệm hữu ích:
Hard limit
--memory=512m
Container không được vượt quá mức memory hard limit đã đặt.
Soft reservation
--memory-reservation=384m
Reservation là mức mềm, có ý nghĩa khi host bắt đầu có memory pressure.
Ví dụ:
docker run -d \
--name api \
--memory=512m \
--memory-reservation=384m \
my-api:latest
--memory-reservation nên thấp hơn --memory nếu bạn dùng cả hai.
Cẩn thận với swap
--memory-swap dễ bị hiểu nhầm.
Ví dụ:
docker run -d \
--memory=512m \
--memory-swap=768m \
my-app:latest
Trong trường hợp này, tổng memory + swap tối đa là 768 MB, nghĩa là phần swap tiềm năng là khoảng 256 MB.
Swap có thể giúp tránh OOM ngay lập tức nhưng chậm hơn RAM rất nhiều. Một ứng dụng đang swap liên tục thường sẽ tăng latency mạnh.
Đừng dùng swap để che việc thiếu RAM kéo dài.
Nếu VPS chưa có swap và bạn muốn hiểu cách cấu hình, xem bài Hướng dẫn tạo Swap trên VPS Ubuntu.
Có nên tắt OOM killer cho container?
Docker có tùy chọn --oom-kill-disable, nhưng không nên bật máy móc.
Nếu vô hiệu hóa OOM killer mà không có memory limit hợp lý, host có thể rơi vào memory starvation nghiêm trọng.
Với production nhỏ, cách an toàn hơn thường là:
- đặt memory limit;
- theo dõi memory usage;
- restart policy phù hợp;
- alert khi container bị OOM;
- sửa memory leak hoặc workload gốc.
Giới hạn CPU bằng --cpus
Cách dễ hiểu nhất:
docker run -d \
--name worker \
--cpus="1.5" \
my-worker:latest
Theo Docker Docs, --cpus="1.5" giới hạn container ở mức tương đương tối đa khoảng 1,5 CPU theo quota scheduler.
Ví dụ VPS 4 vCPU:
--cpus="0.5"→ tối đa khoảng nửa CPU;--cpus="1.0"→ tối đa khoảng một CPU;--cpus="2.0"→ tối đa khoảng hai CPU.
Đây là ceiling, không phải reservation đảm bảo hiệu năng.
--cpu-shares khác --cpus thế nào?
--cpu-shares là trọng số tương đối khi CPU bị tranh chấp.
Ví dụ:
docker run -d --cpu-shares=1024 app-a
docker run -d --cpu-shares=512 app-b
Khi CPU dư, cả hai vẫn có thể dùng nhiều CPU. Khi CPU thiếu, container có shares cao hơn được ưu tiên tương đối hơn.
Nếu mục tiêu là “container này không được vượt quá 1 CPU”, dùng --cpus thường dễ hiểu hơn.
Giới hạn container vào core cụ thể
Bạn có thể dùng:
docker run -d --cpuset-cpus="0,1" my-app
Container chỉ được schedule lên CPU 0 và 1.
cpuset hữu ích cho một số workload đặc thù, nhưng với VPS nhỏ thường không cần thiết. Pin core quá sớm có thể làm sử dụng CPU kém linh hoạt hơn.
Giới hạn PID để giảm rủi ro process runaway
Ví dụ:
docker run -d \
--pids-limit=200 \
my-app:latest
Nếu app bình thường chỉ cần vài chục process/thread, PID limit giúp giảm rủi ro một lỗi sinh process vô hạn.
Không đặt quá thấp với app có nhiều worker/thread.
Docker Compose: đặt CPU và RAM ngay trong compose.yaml
Docker Compose hiện hỗ trợ các trường service-level như cpus, mem_limit và pids_limit.
Ví dụ:
services:
app:
image: my-app:latest
restart: unless-stopped
cpus: 1.0
mem_limit: 512m
mem_reservation: 384m
pids_limit: 200
Kiểm tra cấu hình đã render:
docker compose config
Sau đó triển khai:
docker compose up -d
Kiểm tra:
docker stats
Với project production, luôn đọc release notes/Compose Specification tương ứng phiên bản Docker Compose bạn đang chạy.
Cách khác: deploy.resources
Compose Deploy Specification cũng mô tả:
services:
app:
image: my-app:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Tuy nhiên, hỗ trợ deploy phụ thuộc platform/implementation. Với Docker Compose trên một VPS đơn lẻ, các field service-level như cpus và mem_limit thường dễ kiểm tra trực tiếp hơn.
Chọn memory limit bao nhiêu là hợp lý?
Không có con số đúng cho mọi container.
Một quy trình thực tế:
- chạy workload với traffic đại diện;
- theo dõi bằng
docker statshoặc Prometheus; - ghi nhận median và peak memory;
- cộng headroom hợp lý;
- test dưới peak;
- giảm/tăng theo dữ liệu.
Ví dụ một API thường dùng 180–220 MB và peak 320 MB. Đặt limit 256 MB có thể gây OOM trong peak, trong khi 512 MB có thể hợp lý hơn.
Đừng đặt limit sát mức bình thường đến mức garbage collector hoặc temporary allocation không còn headroom.
Chọn CPU limit bao nhiêu?
CPU có tính burst khác RAM.
Một web app có thể cần CPU cao trong vài giây nhưng bình thường rất thấp. Nếu giới hạn quá chặt, latency sẽ tăng dù host còn CPU dư.
Nên theo dõi:
- CPU trung bình;
- CPU p95/p99 nếu có metric;
- request latency;
- queue length;
- CPU throttling;
- load của toàn host.
Nếu container worker batch chạy nền, limit CPU thường dễ áp mạnh hơn để nó không tranh tài nguyên với website front-end.
Ví dụ phân bổ cho VPS 4 vCPU / 8 GB RAM
Giả sử có:
- web app;
- worker;
- PostgreSQL;
- Redis;
- monitoring agent.
Đừng chia đúng 8 GB cho container. Host Linux, Docker daemon, filesystem cache và service hệ thống vẫn cần RAM.
Ví dụ mang tính minh họa:
- app: 1 GB;
- worker: 1 GB;
- database: 3 GB;
- Redis: 512 MB;
- monitoring: 512 MB;
- phần còn lại làm headroom cho host/cache.
Các con số phải được thay bằng số liệu workload thật.
Khi container bị OOMKilled
Kiểm tra trạng thái:
docker inspect ten-container --format '{{.State.OOMKilled}}'
Xem exit code:
docker inspect ten-container --format '{{.State.ExitCode}}'
Xem log:
docker logs --tail 200 ten-container
Và kernel log:
journalctl -k | grep -i -E 'oom|out of memory|killed process'
Nếu đúng OOM, câu hỏi tiếp theo không phải luôn là “tăng limit”, mà là:
- workload có tăng thật không;
- app có memory leak không;
- cache trong app có phình vô hạn không;
- số worker có quá nhiều không;
- query có trả dataset quá lớn không.
Khi CPU bị throttling
Container chạm CPU quota có thể bị throttle. Dấu hiệu thực tế thường là:
- latency tăng;
- throughput không tăng dù request tăng;
- CPU của container bám sát ceiling;
- host vẫn còn idle CPU.
Nếu app luôn chạm ceiling trong giờ cao điểm, limit có thể quá thấp hoặc workload thực sự cần scale.
Resource limit không thay monitoring
Bạn vẫn cần xem xu hướng theo thời gian.
Nếu đã có Prometheus/Grafana, bài Giám sát VPS bằng Prometheus, Node Exporter và Grafana có thể làm nền để theo dõi host. Với Docker, có thể bổ sung cAdvisor hoặc metric application tùy nhu cầu.
Lỗi thường gặp khi đặt limit
Chia hết RAM cho container
Host cần RAM. Nếu tổng hard limit của container bằng đúng tổng RAM, máy vẫn có thể gặp pressure.
Đặt database RAM quá thấp
Database cần cache/buffer. Limit quá thấp có thể làm disk I/O tăng và hiệu năng giảm mạnh.
Dùng swap như RAM thật
Swap là lớp đệm, không phải thay thế RAM cho workload latency-sensitive.
Đặt CPU limit quá thấp cho web app
Burst CPU bị chặn có thể làm response chậm dù server chưa hết CPU.
Tắt OOM killer để “không bị chết container”
Điều này có thể chuyển rủi ro từ một container sang toàn host nếu cấu hình sai.
Checklist triển khai
- Đo CPU/RAM hiện tại bằng
docker stats. - Chừa RAM cho host.
- Đặt memory hard limit theo peak + headroom.
- Cân nhắc memory reservation nếu phù hợp.
- Đặt CPU limit cho workload dễ runaway.
- Dùng PID limit nếu app có nguy cơ sinh process nhiều.
- Không tắt OOM killer tùy tiện.
- Theo dõi OOMKilled và restart count.
- Test dưới tải thật trước production.
- Đo latency sau khi áp limit.
FAQ
Docker container mặc định có giới hạn RAM không?
Không. Docker Docs nêu rằng mặc định container không có resource constraints và có thể dùng tài nguyên host theo scheduler/kernel cho phép.
--memory=512m có nghĩa container luôn được dành 512 MB không?
Không. Đây là hard limit tối đa, không phải lượng RAM được reserve riêng ngay từ đầu.
--cpus=1 có làm container chỉ chạy trên đúng một core cố định không?
Không. Nó giới hạn quota CPU tương đương một CPU; scheduler vẫn có thể chạy process trên các core khác nhau. Nếu muốn pin core cụ thể, dùng --cpuset-cpus.
Có nên đặt limit cho database container không?
Có thể, nhưng phải hiểu memory model và cache của database. Đặt quá thấp có thể gây OOM hoặc làm hiệu năng giảm mạnh.
Resource limit có chống được memory leak không?
Không sửa được leak, nhưng giới hạn mức thiệt hại tới host và container khác. Bạn vẫn phải sửa nguyên nhân gốc.
Kết luận
Giới hạn CPU và RAM cho Docker trên VPS là một lớp bảo vệ vận hành quan trọng khi nhiều container chia sẻ cùng host. Hãy dùng --memory, --cpus, PID limit hoặc các trường tương ứng trong Docker Compose, nhưng đặt giá trị dựa trên metric thật thay vì copy cấu hình cố định từ Internet.
Nếu sau khi tối ưu và đặt limit mà tổng workload hợp lệ vẫn chạm trần CPU/RAM thường xuyên, có thể tham khảo các gói VPS tại HUONG CLOUD và chọn tài nguyên theo dữ liệu sử dụng thực tế.
Nguồn tham khảo
- Docker Docs — Resource constraints: https://docs.docker.com/engine/containers/resource_constraints/
- Docker Docs — Compose services: https://docs.docker.com/reference/compose-file/services/
- Docker Docs — Compose Deploy Specification: https://docs.docker.com/reference/compose-file/deploy/
Kết luận
Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.
Chưa biết nên chọn gói nào?
Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.
Xem bảng giá VPS →