Bạn có thể chạy Docker trong môi trường production hàng tháng mà không thấy vấn đề gì. Container khởi động, ứng dụng phản hồi, không có gì bị hỏng. Nhưng một cổng mở hoặc một quyền cấu hình sai sẽ tạo ra điểm vào cho kẻ tấn công mà họ không phải công sức để có được. Hầu hết các lỗi bảo mật Docker không trông giống như lỗi cho đến khi có điều gì đó sai.
Bài viết này bao gồm các cấu hình cụ thể có thể đưa môi trường container vào nguy hiểm, những gì mỗi cấu hình cho phép kẻ tấn công thực hiện, và kết thúc với một danh sách kiểm tra mà bạn có thể chạy ngay hôm nay để kiểm tra cấu hình của riêng bạn.
Tại Sao Bảo Mật Docker Khó Hơn Vẻ Ngoài
Container có vẻ bị cô lập. Bạn khởi động một container, nó chạy không gian tiến trình riêng của nó, và từ bên trong, container tiếp theo không tồn tại. Bạn thực sự có sự cô lập, nhưng nó chỉ là một phần. Container chia sẻ kernel của máy chủ, nghĩa là một tiến trình bên trong container có thể, dưới những điều kiện cụ thể, tiếp cận toàn bộ hệ thống máy chủ.
Docker được cấu hình để thuận tiện cho developer, không phải để tăng cường bảo mật production. Root access bật. Tất cả các cổng có thể ràng buộc với tất cả các interface. Không có giám sát runtime. Hầu hết các developer chấp nhận những cài đặt đó, triển khai container, và tiếp tục. Đó là một cách hợp lý để bắt đầu, nhưng nó không phải là một tư thế bảo mật hoàn thiện.
Theo Báo cáo 2024 State of Kubernetes Security từ Red Hat, 67% các tổ chức đã trì hoãn hoặc làm chậm triển khai ứng dụng do lo ngại về bảo mật container hoặc Kubernetes. Sự ma sát này thường không đến từ các cuộc tấn công. Nó đến từ các đội phát hiện ra rằng cấu hình container của họ cần tăng cường bảo mật mà họ chưa xây dựng.
Chúng tôi thường thấy các container chạy trong production với cùng cấu hình mà chúng có trên máy tính cục bộ của một developer. Đó là nơi mà các lỗi bảo mật Docker có xu hướng kết hợp im lặng, mà không có dấu hiệu rõ ràng cho đến khi điều gì đó được kiểm toán hoặc thất bại.
Những lỗi tạo ra các khoảng trống đó là cụ thể, có thể dự đoán được, và hầu hết có thể tránh được, bắt đầu từ cấp độ cấu hình.
Những Lỗi Cấu Hình Docker Phổ Biến
Hầu hết các cuộc xâm nhập container không bắt đầu bằng một zero-day exploit. Chúng bắt đầu với một cấu hình được thiết lập vào ngày đầu tiên, mà không có nhiều suy nghĩ về phơi nhiễm mạng hoặc phạm vi quyền.
Cài đặt mặc định Docker được xây dựng để hoạt động. Khoảng cách giữa hoạt động và an toàn là nơi mà các rủi ro bảo mật container Docker tích lũy, đặc biệt là trong các thiết lập tự lưu trữ được triển khai và không bao giờ được xem xét lại.
Chúng tôi thường thấy mô hình này: các container trên các máy chủ có IP công cộng với các ràng buộc cổng, cài đặt người dùng, và cấu hình mạng chính xác như chúng lúc triển khai ban đầu.
Chạy Container với Quyền Root
Khi bạn khởi động một container Docker mà không chỉ định người dùng, nó chạy với quyền root. Điều này có nghĩa là bất kỳ tiến trình nào bên trong container, bao gồm ứng dụng của bạn, có quyền cấp độ root trong namespace của container.

Root bên trong container không giống như root trên máy chủ, nhưng sự tách biệt không tuyệt đối. Các exploit nâng quyền nhắm mục tiêu runtime, như CVE-2019-5736 runc được ghi chép rõ ràng và các lỗi runtime tương tự, thường yêu cầu một tiến trình container root để thành công.
Các container không phải root loại bỏ yêu cầu tiến trình root mà những exploit đó phụ thuộc vào, làm giảm đáng kể bề mặt tấn công cho loại lỗ hổng đó, mặc dù chúng không loại bỏ hoàn toàn rủi ro escape container.
Thêm chỉ thị USER vào Dockerfile của bạn giải quyết vấn đề này. Một số image chính thức được cung cấp với một người dùng không có quyền mà bạn có thể kích hoạt bằng chỉ thị USER, nhưng nhiều image vẫn còn mặc định là root mà không có người dùng ứng dụng sẵn sàng. Trong những trường hợp đó, bạn tạo người dùng trong Dockerfile trước khi chuyển sang nó. Đối với hầu hết các thiết lập tự lưu trữ, thay đổi này một mình loại bỏ toàn bộ một loại rủi ro nâng quyền.
Để Lộ Quá Nhiều Cổng cho Internet Công Cộng
Khi bạn xuất bản một cổng bằng Docker, Docker viết các quy tắc iptables của riêng nó trực tiếp. Những quy tắc đó chạy trước các quy tắc firewall cấp độ máy chủ. Đây là một hành vi được cộng đồng báo cáo tốt và được ghi chép trong hướng dẫn lọc gói Docker, không phải cấu hình sai, và nó có nghĩa là UFW và các công cụ tương tự không chặn những gì Docker đã mở.

Docker ghi trực tiếp vào iptables, bỏ qua các cấu hình mặc định của UFW và firewalld trên nhiều máy chủ Linux. Điều đó có nghĩa là một cổng được liên kết với 0.0.0.0 có thể truy cập công khai ngay cả khi tường lửa của bạn dường như được cấu hình. Các nhóm bảo mật đám mây và quy tắc chuỗi DOCKER-USER vẫn có thể chặn lưu lượng đó, vì vậy mức độ lộ thực tế phụ thuộc vào cấu hình mạng cụ thể của bạn.
Liên kết dịch vụ với 127.0.0.1 bất cứ khi nào có thể, định tuyến lưu lượng công khai thông qua một reverse proxy, và chỉ expose những gì thực sự cần truy cập bên ngoài. Một reverse proxy là cách đáng tin cậy nhất để kiểm soát những gì bị lộ từ bên ngoài máy chủ.
Bỏ Qua Cách Ly Mạng Giữa Các Container
Bất kỳ container nào trên mạng đó đều có thể truy cập bất kỳ container nào khác mà không có hạn chế. Cầu nối mặc định không áp dụng lọc lưu lượng giữa các container chia sẻ nó, và hầu hết các cài đặt không bao giờ thay đổi cấu hình đó.

Nếu một container bị xâm phạm, liên lạc mở đó trở thành một đường đi để di chuyển ngang. Một container frontend có thể truy cập cơ sở dữ liệu, một API nội bộ, hoặc bất kỳ thứ gì khác trên cùng mạng cầu nối mặc định, ngay cả khi quyền truy cập đó không bao giờ được dự định.
Các mạng do người dùng định nghĩa cung cấp cho bạn quyền kiểm soát rõ ràng về những container nào có thể giao tiếp, nhưng một mạng tùy chỉnh duy nhất được chia sẻ bởi tất cả các dịch vụ của bạn vẫn cho phép lưu lượng giữa các container tự do. Cách ly thực sự yêu cầu đặt các dịch vụ không nên giao tiếp với nhau trên các mạng riêng biệt. Tắt cầu nối mặc định là điểm khởi đầu, không phải là đích đến.
Bỏ Qua Ổ Cắm Docker
Ổ cắm Docker tại /var/run/docker.sock là giao diện điều khiển cho toàn bộ công cụ Docker. Gắn nó vào một container cung cấp cho container đó quyền truy cập API trực tiếp vào daemon chạy trên máy chủ.

Với quyền truy cập đó, một container có thể khởi động các container mới, gắn thư mục máy chủ, kiểm tra và sửa đổi các container đang chạy, và hiệu quả kiểm soát máy chủ. Bề mặt tấn công tương đương với root trên máy chủ, đó là lý do tại sao bất kỳ công cụ nào yêu cầu quyền truy cập ổ cắm đều xứng đáng được đánh giá cẩn thận.
Đối với hầu hết các trường hợp sử dụng, có những lựa chọn thay thế an toàn hơn: các API có phạm vi hoặc các công cụ quản lý Docker không yêu cầu quyền truy cập ổ cắm. Docker-trong-Docker có những sự cân bằng bảo mật và hoạt động riêng của nó và không phải là một sự thay thế đơn giản.
Các sai lầm cấu hình tạo ra phơi bày ban đầu. Lựa chọn hình ảnh và phụ thuộc xác định cách phơi bày đó phức tạp hóa theo thời gian.
Các Sai Lầm Hình Ảnh và Bí Mật Vượt Quá Vòng Đời Container
Khi bạn dừng một container, các sai lầm cấu hình bên trong nó cũng dừng lại. Khi bạn xây dựng lại từ một hình ảnh chứa lỗ hổng hoặc thông tin đăng nhập được mã hóa cứng, vấn đề khởi động lại cùng với container. Các sai lầm ở cấp hình ảnh không được đặt lại giữa các lần triển khai.
Chúng di chuyển cùng với hình ảnh đến mọi môi trường kéo nó, mọi registry lưu trữ nó, và mọi thành viên nhóm chạy nó. Tính bền vững này làm cho quản lý hình ảnh và bí mật trở thành một danh mục rủi ro riêng biệt, đáng để kiểm toán riêng biệt với cấu hình.
Chúng tôi thường thấy mô hình này: một hình ảnh được chọn cẩn thận khi dự án bắt đầu và không bao giờ được xây dựng lại kể từ đó, từ từ trôi dạt khỏi đường cơ sở bảo mật mà nó đại diện ban đầu.
Sử Dụng Hình Ảnh Không Đáng Tin Cậy hoặc Lỗi Thời
Các registry công khai mở cho tất cả mọi người. Các hình ảnh độc hại đã được phân phối thông qua Docker Hub mang theo các máy đào tiền điện tử và backdoor được nhúng trong lịch sử lớp vẫn tồn tại khi container khởi động lại. Xác minh trước khi kéo là điều quan trọng, đặc biệt đối với các hình ảnh từ các nhà xuất bản không chính thức hoặc không xác định.

Vấn đề riêng biệt là độ cũ. Một hình ảnh chính thức mà bạn kéo sáu tháng trước và không bao giờ xây dựng lại kể từ đó đã tích lũy các lỗ hổng Docker chưa được vá lỗi với mỗi CVE được công bố lại các gói của nó. Hình ảnh không bị hỏng. Nó chỉ không còn hiện tại nữa.
Báo cáo Trạng Thái Chuỗi Cung Ứng Phần Mềm 2024 của Sonatype phát hiện rằng 95% thời gian một thành phần dễ bị tấn công được sử dụng, một phiên bản được sửa chữa đã có sẵn, và 80% các phụ thuộc ứng dụng vẫn không được nâng cấp trong hơn một năm. Mô hình đó cũng liên quan đến các hình ảnh cơ sở Docker, vì chúng dựa vào các gói mã nguồn mở tương tự.
Hãy dùng image chính thức từ các nhà phát hành đã được xác minh và ghim tag phiên bản cụ thể thay vì dùng "latest". Thiết lập lịch rebuild định kỳ để giữ cho image của bạn luôn cập nhật.
Hardcoding Secrets trong Docker files và Compose Files
Thông tin xác thực được viết vào file ENV hoặc lệnh ARG trong Docker, hardcoded trong khối environment của Compose, truyền dưới dạng build arguments, hoặc lưu trữ trong file .env được commit vào version control không biến mất khi bạn dừng container. Chúng vẫn tồn tại trong lịch sử image layer hoặc source control, có thể truy cập bởi bất kỳ ai có quyền tiếp cận.

Đây là một trong những lỗi bảo mật Docker bị bỏ qua nhiều nhất vì nó không gây ra vấn đề rõ ràng trong quá trình phát triển. Một khóa API trong lệnh ENV hoạt động bình thường. Nó cũng nằm trong kho lưu trữ của bạn, được nhúng vào image, và phân phối mọi nơi mà image đó được sử dụng.
Modern Docker Compose hỗ trợ cơ chế bí mật gốc giúp gắn kết thông tin xác thực tại runtime mà không cần nhúng chúng vào image. Docker's secrets API và các trình quản lý bí mật bên ngoài tuân theo nguyên tắc tương tự. Đây là những tùy chọn giúp giữ thông tin xác thực hoàn toàn tách biệt khỏi các artifact xây dựng và các file được commit.
Biến môi trường runtime tốt hơn thông tin xác thực được mã hóa cứng, nhưng chúng vẫn bị lộ qua kết quả Docker inspect, logs và crash dumps. Đó là bước tiến so với secret được nhúng sẵn, nhưng chưa phải giải pháp hoàn chỉnh.
Không Cập Nhật Hình Ảnh Container Thường Xuyên
Chạy cùng một image trong nhiều tháng là thói quen phổ biến. Mỗi ngày trôi qua sau khi một lỗ hổng bảo mật mới được công bố, nhưng trước khi bạn rebuild, container của bạn sẽ mang theo một cửa sổ rủi ro ngày càng lớn mà không có bất kỳ thay đổi nào hiển thị.
Lên lịch xây dựng lại hình ảnh một cách nhất quán. Tự động hóa quy trình này ở những nơi có thể, và chạy bộ quét lỗ hổng định kỳ trên các hình ảnh hiện tại của bạn. Mục tiêu không phải là hoàn hảo. Đó là rút ngắn khoảng thời gian giữa lúc bản vá được phát hành và lúc nó được triển khai.
Kiểm soát truy cập và giám sát thường bị xếp hàng chờ khi triển khai nhanh. Đây cũng là những lĩnh vực mà các sự cố dễ bị bỏ sót lâu nhất.
Lỗ hổng trong Kiểm soát Truy cập và Khả năng Hiển thị
Khi container đã chạy ổn định với cấu hình vững chắc và image hiện tại, vẫn còn hai loại lỗi tiềm ẩn. Cả hai đều khó phát hiện: bạn sẽ không nhận ra vấn đề kiểm soát truy cập cho đến khi ai đó lợi dụng nó, và bạn sẽ không phát hiện khoảng trống trong giám sát cho đến khi cần điều tra hoạt động mà không hề được ghi lại.
Giống nhau Nghiên cứu Red Hat 2024 cho thấy 42% các đội ngũ thiếu khả năng để giải quyết các vấn đề bảo mật container và các mối đe dọa liên quan.
Chúng tôi nhận thấy rằng những khoảng trống trong giám sát thường bị phát hiện trong quá trình điều tra sự cố, chứ không phải trước đó. Khi khả năng theo dõi trở thành ưu tiên, thường là vì đang ứng phó với một vấn đề nào đó thay vì ngăn chặn nó.
Xác thực yếu và Bảng điều khiển quản lý để lộ
Một bảng điều khiển quản lý container trên IP công cộng mà không có xác thực không cần kẻ tấn công tinh vi. Nó chỉ cần họ biết địa chỉ. Đó là một thanh rào thấp hơn so với những gì hầu hết các team nhận ra.

Các công cụ giám sát và quản lý tự lưu trữ thường đi kèm giao diện web có thể truy cập trên tất cả các giao diện mạng. Để chúng chạy trên IP công khai mà không có xác thực ở phía trước giống như để một bảng điều khiển quản trị mở cửa.
Xác thực, reverse proxy và cấu hình mạng riêng là nền tảng. Kiểm soát truy cập là một bước cấu hình bạn thêm vào bất kỳ giao diện quản lý nào, không phải thứ được kích hoạt sẵn.
Nguyên tắc tương tự cũng áp dụng cho Docker Quản lý CLI và GUIquyền truy cập cấp admin vào daemon vẫn gặp những rủi ro tương tự bất kể giao diện nào.
Không Giám Sát Hoạt Động Của Container
Nếu một container bị xâm phạm, hoạt động của kẻ tấn công để lại dấu vết: thay đổi hành vi process, kết nối mạng bất thường, và sửa đổi file không mong muốn. Nếu không có log collection, dấu vết đó không tồn tại dưới dạng mà bạn có thể hành động.
Log collection tập trung, container audit logging, và runtime monitoring tools cung cấp dữ liệu để phát hiện hoạt động bất thường trước khi nó trở nên nghiêm trọng hơn. Mục tiêu không phải phân tích từng dòng. Đó là có dữ liệu sẵn sàng khi bạn cần điều tra.
Container setups chạy im lặng trong production mà không có log pipeline và không có alert không phải là low-maintenance. Chúng chưa được kiểm tra. Đó là hai trạng thái vận hành khác nhau.
Tại Sao Môi Trường Infrastructure Cũng Quan Trọng
Container security bắt đầu từ cấu hình, nhưng cấu hình chạy trên top của infrastructure. Một host với networking cấu hình sai, shared resources, hoặc không có network-level filtering tạo ra những điều kiện ảnh hưởng đến mọi container ở trên nó. Cấu hình container setup đúng và server configuration đúng là hai tác vụ riêng biệt.
Nhiều security gaps của Docker được phóng đại bởi những điều kiện mà chính các containers kế thừa:
- Một shared-tenancy server không có hardware isolation giữa các tenants
- Một host kernel chạy mà không được patch
- Một host không có network-level filtering built-in
Điều này không loại bỏ nhu cầu các bước cấu hình ở trên, vì container hardening thích hợp quan trọng bất kể lớp infrastructure. Bắt đầu trên isolated infrastructure loại bỏ một lớp lo lắng khỏi phương trình.
Tại Cloudzy, chúng tôi cung cấp hai tùy chọn tùy thuộc vào những gì setup của bạn yêu cầu:
- Linux VPS: một môi trường sạch để bạn deploy Docker và áp dụng các bước hardening trong bài viết này
- Portainer VPS: một tùy chọn one-click với Portainer pre-installed; server khởi động, và bạn đã ở trong dashboard
Cả hai tùy chọn chạy trên cùng infrastructure: KVM virtualization, AMD Ryzen 9 CPUs tại tối đa 5.7 GHz boost clock, DDR5 memory, NVMe SSD storage, lên đến 40 Gbps network, và DDoS protection miễn phí thông qua BuyVM filtering, trên 12 vị trí toàn cầu với 99.95% uptime SLA.
Để hiểu sâu hơn về việc chạy Portainer trên VPS, chúng tôi bao gồm nó trong một bài viết riêng.
Danh Sách Kiểm Tra Security Thực Tế cho Các Triển Khai Docker
Các security mistakes của Docker ở trên hầu hết đến từ các quyết định cấu hình duy nhất được thực hiện một lần và không bao giờ xem xét lại. Chạy danh sách kiểm tra này so với một setup hiện tại bắt các security gaps. Nó hoạt động như một audit, không phải một deployment guide.
Các security best practices của Docker này bao gồm cách bảo mật các Docker containers chống lại các configuration failures phổ biến nhất được mô tả ở trên.
Tham Chiếu Nhanh: Cả 9 Sai Lầm
| Lỗi | Danh mục | Sửa Chữa Một Dòng |
| Chạy dưới quyền root | Cấu hình | Thêm USER directive tới Dockerfile của bạn |
| Các cổng được liên kết với 0.0.0.0 | Cấu hình | Bind tới 127.0.0.1 và route thông qua một reverse proxy |
| Không cách ly mạng | Cấu hình | Chia các services trên các user-defined networks riêng biệt dựa trên access needs. |
| Docker socket được mounted | Cấu hình | Loại bỏ mount; sử dụng scoped APIs hoặc alternatives |
| Images không đáng tin cậy hoặc lỗi thời | Hình ảnh | Sử dụng images chính thức với version tags cố định |
| Bí mật được mã hóa cứng | Hình ảnh | Di chuyển credentials sang environment variables runtime hoặc secrets manager |
| Không có lịch rebuild image | Hình ảnh | Thiết lập rebuild hàng tháng; tự động hóa khi có thể |
| Bảng điều khiển chưa xác thực | Truy cập | Thêm xác thực và chuyển giao diện quản lý sang mạng riêng tư |
| Không thu thập logs từ containers | Truy cập | Thiết lập logging tập trung và runtime monitoring |
Chúng tôi khuyên bạn chạy nó trên các setup hiện tại trước, vì đó là nơi các lỗ hổng có khả năng xuất hiện nhất.
Containers chạy dưới quyền non-root: Kiểm tra Docker files của bạn xem có USER directive. Nếu không tìm thấy, container chạy dưới quyền root.
Port bindings giới hạn trên localhost hoặc qua proxy: Chạy docker ps và kiểm tra port bindings. Một entry 0.0.0.0:PORT có thể công khai truy cập được trên các hosts nếu không có security group upstream, external firewall, hoặc DOCKER-USER chain rule chặn nó.
Custom bridge networks đang sử dụng: Containers trên default bridge của Docker có thể liên lạc với nhau tự do. Containers trên cùng một user-defined bridge vẫn có thể giao tiếp với nhau, vì vậy hãy chia tách services trên các networks riêng biệt theo ranh giới tin cậy để cách ly thực sự.
Docker socket không được mount trong containers: Kiểm tra Compose files và run arguments. Nếu /var/run/docker.sock xuất hiện như một volume, xác nhận nó cần thiết và có ý định.
Base images từ verified publishers với pinned versions: Một FROM ubuntu:latest pull một version không xác định, có thể lỗi thời. Cố định phiên bản cụ thể.
Không có secrets trong Docker files, Compose files, hoặc build arguments: Image layer history lưu giữ credentials sau khi container bị xóa. Sử dụng Compose secrets, Swarm secrets, build secret mounts, hoặc external secrets manager. Runtime environment variables tốt hơn hardcoded values, nhưng vẫn xuất hiện trong inspect output và logs.
Lịch rebuild image được xác định: Images cũ tích lũy lỗ hổng bảo mật. Một rebuild cadence hàng tháng giữ cho cửa sổ rủi ro có thể quản lý được cho hầu hết các setup.
Giao diện quản lý được bảo vệ bằng xác thực: Bất kỳ dashboard nào trên public IP không có xác thực là một điểm vào mở. Vị trí trên mạng riêng tư là tốt hơn khi có thể.
Đang thu thập nhật ký container: Nếu không có pipeline nhật ký, việc phát hiện sự cố phụ thuộc vào tác động hệ thống có thể nhìn thấy. Đó là tín hiệu quá muộn để hành động.
Kết luận
Cấu hình mặc định của Docker được xây dựng để thuận tiện, không phải bảo mật. Hầu hết các lỗi được đề cập trong bài viết này bắt nguồn từ các cài đặt chưa bao giờ thay đổi sau khi triển khai ban đầu, không phải từ các cuộc tấn công tinh vi.
Các bản sửa chữa chủ yếu là quyết định cấu hình một lần: chỉ thị USER, thay đổi ràng buộc cổng, mạng tùy chỉnh, lịch trình xây dựng lại. Không có cái nào yêu cầu công cụ mới đối với hầu hết các thiết lập.
Thiết lập cấu hình container đúng là nhiệm vụ đầu tiên. Cơ sở hạ tầng nó chạy trên là việc thứ hai. Cả hai đều quan trọng, và cái này không thay thế cho cái kia.