Khắc phục lỗi 'Essential container in task exited' trong AWS ECS Fargate

intermediate☁️ AWS2026-06-26| AWS ECS Fargate, Docker, AWS Task Definitions

Error Message

Essential container in task exited. Exit Code: 1 (or 137, 127)
#aws-ecs#fargate#docker#khắc-phục-lỗi

Vấn đềBạn nhấn triển khai (deploy) trên ECS service của mình, nhưng thay vì ứng dụng chạy bình thường, các task của bạn lại chuyển sang trạng thái STOPPED chỉ trong vài giây. AWS Console thường hiển thị một thông báo mơ hồ và gây khó chịu: Essential container in task exited. Điều này xảy ra vì container chính — cái mà bạn đánh dấu là 'essential' — đã không vượt qua được kiểm tra sức khỏe (health check) hoặc bị lỗi (crash) ngay khi khởi động.

Câu trả lời thực sự nằm ở Exit Code. Nếu container của bạn bị crash trước khi driver awslogs kịp gửi log đến CloudWatch, bạn có thể cảm thấy như mình đang dò lỗi trong bóng tối. Hiểu rõ các mã lỗi này là cách nhanh nhất để đưa dịch vụ của bạn hoạt động trở lại.

Các Exit Code phổ biến và ý nghĩa của chúng- Exit Code 1: Lỗi crash ứng dụng chung. Lỗi này thường xuất phát từ lỗi runtime, thiếu biến môi trường hoặc kết nối cơ sở dữ liệu bị thất bại.- Exit Code 127: Không tìm thấy lệnh (Command not found). ENTRYPOINT hoặc CMD của bạn trỏ đến một script hoặc tệp thực thi không tồn tại bên trong image của container.- Exit Code 137: Hết bộ nhớ (Out of Memory - OOM). Fargate agent đã dừng container của bạn vì nó cố gắng sử dụng nhiều RAM hơn mức 512MB hoặc 1GB mà bạn đã phân bổ trong task definition.## Cách tìm nguyên nhân gốc rễĐừng lãng phí thời gian xem các sự kiện dịch vụ (service events) ở cấp độ cao. Chúng hiếm khi cung cấp lỗi cụ thể. Thay vào đó, hãy đi sâu vào từng task bị lỗi:

  • Mở ECS Cluster và chọn Service của bạn.- Chuyển đến tab Tasks và thay đổi bộ lọc thành Stopped.- Nhấp vào Task ID của lần lỗi gần nhất.- Mở rộng phần Containers. Kiểm tra kỹ trường Exit CodeReason.## Các giải pháp hiệu quả### 1. Giải quyết Exit Code 1: Crash ứng dụng khi khởi chạyHầu hết các lỗi Exit Code 1 là do vấn đề cấu hình. Nếu ứng dụng Node.js của bạn yêu cầu biến DB_HOST nhưng lại nhận giá trị undefined, nó có khả năng sẽ bị crash trong giai đoạn khởi tạo (bootstrap).
  • Kiểm tra CloudWatch Logs: Tìm các lỗi "Module not found" hoặc stack trace. Nếu không có log, lỗi crash đã xảy ra trước khi logging agent kịp khởi động.- Xác minh quyền của Secret Manager: Đây là một sai lầm phổ biến. Task Execution Role của bạn (không phải Task Role) cần có quyền để lấy các secret. Nếu không có secretsmanager:GetSecretValue, ứng dụng của bạn sẽ không nhận được thông tin xác thực cần thiết để bắt đầu.``` // Chính sách thiết yếu cho Task Execution Role của bạn { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue", "kms:Decrypt" ], "Resource": ["arn:aws:secretsmanager:region:account:secret:app-db-creds-*"] } ] }

### 2. Giải quyết Exit Code 127: Lỗi đường dẫn và quyền truy cậpLỗi này xảy ra khi container khởi động, nhưng Linux shell không thể tìm thấy script khởi động của bạn. Nó đặc biệt phổ biến khi ghi đè các lệnh trong Task Definition.
- **Sử dụng đường dẫn tuyệt đối:** Thay vì dùng `./start.sh`, hãy dùng `/usr/src/app/start.sh`.- **Sửa lỗi xuống dòng:** Các script được viết trên Windows thường sử dụng ký tự xuống dòng `CRLF`. Container Linux yêu cầu `LF`. Nếu bạn thấy lỗi `sh: /start.sh: not found` nhưng tệp rõ ràng là có tồn tại, thì ký tự xuống dòng có thể là thủ phạm. Hãy chạy `dos2unix` trên các script của bạn trước khi build image.- **Thiết lập quyền:** Đảm bảo Dockerfile của bạn có lệnh `RUN chmod +x /path/to/script.sh`.### 3. Giải quyết Exit Code 137: Giới hạn bộ nhớFargate khắt khe hơn so với môi trường Docker cục bộ. Nếu một ứng dụng Java Spring Boot tăng vọt lên 2.1GB trong khi khởi động trên một task 2GB, Fargate sẽ dừng nó ngay lập tức.
- **Tăng kích thước Task:** Thử tăng gấp đôi dung lượng bộ nhớ (ví dụ: từ 2GB lên 4GB) để xem task có ổn định hay không.- **Tối ưu hóa JVM:** Đối với các ứng dụng Java, hãy sử dụng `-XX:MaxRAMPercentage=75.0`. Điều này yêu cầu JVM tuân thủ các giới hạn của container thay vì cố gắng chiếm dụng toàn bộ bộ nhớ của máy chủ bên dưới.### 4. Lỗi mạng (Kịch bản "Không có Log")Nếu task của bạn dừng với lỗi `ResourceInitializationError: unable to pull secrets or registry auth`, container thực sự chưa bao giờ được chạy. Đây là một điểm nghẽn về mạng trong VPC của bạn.
- **Subnet công cộng:** Bạn phải thiết lập **Auto-assign Public IP** thành `ENABLED` để task có thể kết nối với dịch vụ ECR qua internet.- **Subnet riêng tư:** Đảm bảo bạn đã thiết lập NAT Gateway. Ngoài ra, hãy cấu hình VPC Endpoints (Interface Endpoints) cho ECR, S3 và CloudWatch để lưu lượng truy cập luôn nằm trong mạng AWS.## Xác minh và Triển khaiSau khi áp dụng bản sửa lỗi, chẳng hạn như cập nhật IAM policy hoặc tăng RAM, bạn phải triển khai các thay đổi một cách chính xác:
- Tạo một **New Revision** (phiên bản mới) cho Task Definition của bạn.- Cập nhật Service để sử dụng phiên bản mới nhất này.- Theo dõi tab **Tasks**. Một lần triển khai thành công sẽ chuyển từ trạng thái `PROVISIONING` sang `RUNNING` và duy trì ở đó.- Xác nhận **Health Status** hiển thị `HEALTHY`. Điều này cho thấy load balancer hoặc kiểm tra sức khỏe của container cuối cùng đã nhận được phản hồi.## Danh sách kiểm tra tóm tắt- Kiểm tra **Stopped Reason** trong chi tiết Task, không chỉ trong các sự kiện của Service.- Phân biệt giữa **Task Execution Role** (dùng để kéo image/secret) và **Task Role** (dùng cho logic ứng dụng).- Luôn sử dụng đường dẫn tuyệt đối trong các lệnh Docker để ngăn chặn lỗi 127.- Cấu hình `awslogs` ngay lập tức để bạn có thể ghi lại stdout/stderr trong những giây đầu tiên quan trọng khi thực thi.

Related Error Notes