Trong quá trình làm phần mềm, mình tin chắc rằng nhiều bạn đã từng gặp phải vấn đề như sau: Đóng vai trò bạn là một lập trình viên, sau khi hoàn thiện sản phẩm, bạn chỉnh chu và đóng gói rất cẩn thận sản phẩm và chuyển sang cho bên tester để họ test, tuy nhiên oái oăm thay sản phẩm bạn chuyển sang cho tester lại không chạy ổn định hoặc thậm chí là không thể chạy nổi trên máy của họ mặc dù trước khi đóng gói & chuyển giao thì bạn đã kiểm tra rất kỹ lưỡng. Vấn đề nằm ở đâu? Hóa ra là môi trường của 2 máy của bạn và tester rất khác nhau, bạn xây dựng sản phẩm chạy trên .NET Framework 4.5 trong khi máy tester chỉ cài .NET Framework 2.0, sản phẩm của bạn sử dụng một số API từ thư viện Office Primary Interop Assemblies của Office 2013 tuy nhiên máy của tester lại chỉ cài Office 2003, và rất nhiều nguyên nhân “củ chuối” khác thậm chí nhiều nguyên nhân không phải do khác phiên bản phần mềm, thư viên mà liên quan đến cấu trúc mạng khác nhau, policy bảo mật khác nhau của 2 máy. Vậy làm thế nào để giảm thiểu những vấn đề phát sinh liên quan đến sự phụ thuộc của phần mềm vào môi trường của hệ thống khi chuyển giao? Câu trả lời là công nghệ ảo hóa!
Bài viết ngày hôm nay mình sẽ chia sẻ với các bạn về một công nghệ ảo hóa đang “làm mưa làm gió” trong cộng đồng cộng nghệ trên Thế giới, công nghệ đó có tên là “Container“. Ngoài ra, trong bài viết này mình cũng sẽ giới thiệu về dịch vụ Azure Container Service, một dịch vụ cho phép triển khai và quản lý các container trên Microsoft Azure một cách hiệu quả.
Container là gì?
Container là giải pháp để giải quyết vấn đề làm sao để chuyển giao phần mềm một cách đáng tin cậy (không phát sinh lỗi) giữa các môi trường máy tính khác nhau. Chẳng hạn như giữa máy tính của lập trình viên với máy của tester, giữa môi trường staging (hay còn được gọi là môi trường tiền thực tế) với môi trường thực tế hay thậm trí giữa máy chủ riêng đặt tại trung tâm dữ liệu với máy ảo trên cloud.
Container giải quyết vấn đề trên bằng cách tạo ra một môi trường bị cô lập (isolated) chứa mọi thứ mà phần mềm cần để có thể chạy được bao gồm mã nguồn, các thư viện runtime, các thư viện hệ thống, các công cụ hệ thống, … (gọi là sự phụ thuộc hoặc các phụ thuộc) mà không bị các yếu tố liên quan đến môi trường hệ thống làm ảnh hưởng tới cũng như không làm ảnh hưởng tới các phần còn lại của hệ thống.
Đặc điểm kỹ thuật của container

Trên là mô hình kiến trúc của container bao gồm các thành phần chính là server (máy tính vật lý hoặc máy ảo), host OS (hệ điều hành cài đặt trên server) và các container.
Mỗi một ứng dụng (App A và App B) sẽ có những sự phụ thuộc riêng của nó bao gồm cả về phần mềm (các dịch vụ hay thư viện) lẫn cả về phần cứng (CPU, bộ nhớ, lưu trữ). Các ứng dụng này sẽ được Container Engine, một công cụ ảo hóa tinh gọn, được cài đặt trên host OS, nó sẽ cô lập sự phụ thuộc của các ứng dụng khác nhau bằng cách đóng gói chúng thành các container. Các tiến trình (process) trong một container bị cô lập với các tiến trình của các container khác trong cùng hệ thống tuy nhiên tất cả các container này đều chia sẻ kernel của host OS (dùng chung host OS).
Với mô hình trên, sự phụ thuộc của ứng dụng vào tầng OS cũng như cơ sở hạ tầng được loại bỏ giúp việc triển khai phương pháp “deploy anywhere” (triển khai ở bất kỳ nơi đâu) của container được hiệu quả hơn. Thêm vào đó, do chia sẻ host OS nên container có thể được tạo gần như một cách tức thì, giúp việc scale-up & scale-down theo nhu cầu được thực hiện một cách nhanh chóng.
Container khác gì so với máy ảo (Virtual Machine – VM)?

Cùng xét mô hình kiến trúc của VM: Mỗi ứng dụng được ảo hóa bao gồm chính ứng dụng đấy và cũng chứa các phụ thuộc của nó giống như bên container. Tuy nhiên bên VM sẽ kèm theo thêm 1 guest OS. Điều này dẫn tới việc đóng gói ứng dụng được ảo hóa sẽ có dung lượng lên tới hàng GB.
Khác với container là chia sẻ host OS đồng nghĩa với việc các container sẽ có OS giống nhau thì với máy ảo, mỗi một VM có thể có OS khác so với các VM khác và thậm trí OS của các VM hoàn toàn có thể khác với host OS.
Xét về tính linh hoạt: Nếu như bạn muốn bảo trì máy host, với container thì khi bảo trì mà buộc phải khởi động lại máy thì đồng nghĩa với việc hoạt động của các container có trong máy đó sẽ bị gián đoạn. Tuy nhiên với VM, bạn hoàn toàn có thể di chuyển các VM có trong máy cần được bảo dưỡng sang tạm các máy tính khác. Điều này giúp ứng dụng có trong các VM hoạt động mà không bị gián đoạn.
Xét về tính an toàn: Với container, do dùng chung OS nên nếu có lỗ hổng nào đấy ở kernel của host OS thì nó sẽ ảnh hưởng tới toàn bộ container có trong host OS đấy. Ngoài ra hãy thử tưởng tượng với host OS là Linux, nếu trong trường hợp ai đấy hoặc một ứng dụng nào đấy có trong container chiếm được quyền superuser, điều gì sẽ xảy ra? Về lý thuyết thì tầng OS sẽ bị crack và ảnh hưởng trực tiếp tới máy host bị hack cũng như các container khác trong máy đó (hacker sử dụng quyền chiếm được để lấy dữ liệu từ máy host cũng như từ các container khác trong cùng máy host bị hack chẳng hạn). Với VM thì sẽ khó hơn, ứng dụng trong các VM chạy với các guest OS riêng biệt của chúng và giao tiếp với host OS thông qua hypervisor, về lý thuyết thì hypervisor vẫn có khả năng có những lỗ hổng để hacker khai thác nhưng vì nó không có nhiều chức năng như một kernel của OS (thông thường hypervisor chỉ có các chức năng cơ bản như kết nối mạng, quản lý tiến trình ứng dụng, …) nên kể cả khi hypervisor có bị hack vào thì cũng khó có thể gây ra các hậu quả nghiệm trọng như lấy được dữ liệu từ các VM chẳng hạn.
Với những tính năng ưu việt riêng của từng công nghệ ảo hóa, các nhà phát triển có thể nghĩ đến việc “trộn” 2 công nghệ ảo hóa này với nhau để xây dựng một giải pháp ảo hóa linh hoạt và an toàn hơn bằng cách triển khai các container trong máy ảo.
Container trong Máy Ảo (Virtual Machine)

Với việc triển khai các container trong máy ảo, chỉ với một máy host, các nhà phát triển có thể triển khai được nhiều container chạy trên các hệ điều hành khác nhau bằng việc khai thác đặc tính của VM là mỗi VM có một guest OS chạy riêng biệt.
Với những dự án đòi hỏi phải ảo hóa một lượng lớn ứng dụng, việc sử dụng ít VM và dùng nhiều container sẽ giúp giảm chi phí cho việc lưu trữ.
Ngoài ra, việc triển khai các container trong máy ảo cũng giúp tăng tính linh hoạt của các container khi mà việc bảo dưỡng máy host không còn là “cơn ác mộng” với các ứng dụng trong container nữa.
Tại sao container lại đang được quan tâm nhiều đến vậy?
Với đặc tính nhanh gọn của mình, container rất phù hợp với xu hướng phát triển phần mềm hiện đại ngày nay khi mà yếu tố thời gian được đặt lên hàng đầu. Ngoài ra, container sử dụng công nghệ triển khai cũng như định dạng đóng gói thống nhất (unified), chỉ cần cài đặt Container Engine vào các máy cần tạo/dùng container và người dùng hoàn toàn yên tâm có thể sử dụng được các container được đóng gói một cách dễ dàng. Và còn một điểm cũng rất quan trọng để hút được sự quan tâm đó là container được sự hỗ trợ rất lớn từ cồng đồng công nghệ như Ubuntu, Redis, WordPress, …
Giới thiệu Docker – Container Engine mã nguồn mở
Docker là một dự án mã nguồn mở, phát triển các công cụ, dịch vụ về container như Docker Engine – Container Engine của Docker hay Docker Hub – Giống với NuGet, nơi chia sẻ các thư viện phần mềm, Docker Hub là nơi để lập trình viên chia sẻ các Docker image của họ.
Docker image là nền tảng của container, có thể hiểu Docker image như là một template của container, nó sẽ tạo ra container khi thực hiện câu lệnh chạy image đó. Nếu nói với ngôn ngữ lập trình hướng đối tượng, Docker image là class, còn container là thực thể (instance) của class đó.
Docker hỗ trợ nhiều nền tảng hệ điều hành khác nhau bao gồm Linux, Windows và cả Mac. Ngoài ra, Docker còn hỗ trợ nhiều dịch vụ điện toán đám mây nổi tiếng như Microsoft Azure hay Amazon Web Services. Vậy Docker hoạt động như thế nào? Hãy xem phần demo của mình bên dưới demo về cách dùng Docker để tạo và sử dụng container trên Linux.
Demo Linux Container
Trước tiên là mình cần có một máy tính chạy Linux đang hoạt động. Mình sử dụng Microsoft Azure để tạo một máy ảo chạy Ubuntu Server.
Sau khi đã có máy tính chạy Linux, mình sẽ kết nối với máy tính đó thông qua giao thức SSH
và mình sử dụng PuTTY để làm việc này.
Sau khi kết nối được vào máy tính và đăng nhập vào thành công, bước tiếp theo cần làm đó là cài đặt Docker vào máy tính đó, mình sẽ chạy lần lượt chuỗi tập lệnh sau để thực hiện cài đặt Docker:
sudo apt-get update curl -sSL https://get.docker.com/ | sh
Sau khi cài đặt Docker thành công, hãy thử cài đặt một container mẫu. Việc cài đặt một container bằng Docker khá đơn giản, trong bài viết này mình sẽ thực hiện cài container có tên là Drupal để tạo một trang web sử dụng hệ quản trị nội dung mã nguồn mở Drupal.
Cài đặt Drupal container
Trước tiên mình sẽ kéo image Drupal từ Docker Hub về để khởi tạo container từ image này bằng câu lệnh sau:
sudo docker run --name some-drupal -p 8080:80 -d drupal
Tham khảo thêm về mã lệnh docker run
tại đây.
Đợi 1 lúc Docker sẽ kéo image Drupal về cho bạn và khởi tạo container & chạy nó.
Bạn có thể kiểm tra các container nào đang chạy bằng câu lệnh sau:
sudo docker ps
hoặc sử dụng câu lệnh sau để liệt kê tất cả các container bao gồm cả đang chạy lẫn đang không hoạt động:
sudo docker ps -a
Sau khi khởi tạo thành công container Drupal, bạn gõ địa chỉ ip của server và kèm cổng 8080 để truy cập vào trang web Drupal mà bạn vừa tạo:
http://<server_ip>:8080
Nếu thấy xuất hiện giao diện cài đặt Drupal tức là quá chình cài đặt container của mình đã thành công.
Với sự bùng nổ của việc sử dụng container cùng với những lợi ích lớn mà nó mang lại, gã khổng lồ phần mềm Microsoft không muốn bỏ qua cơ hội màu mỡ này với việc cho ra mắt tính năng mới có tên Windows Container.
Windows Container
Windows Containers cung cấp giải pháp ảo hóa sử dụng công nghệ container cho hệ điều hành Windows. Windows Container có 2 loại:
- Windows Server Containers, thực hiện việc đóng gói & chạy các container trên máy tính sử dụng hệ điều hành Windows Server
- Hyper-V Containers, đóng gói từng container vào trong một máy ảo gọn nhẹ sử dụng công nghệ Hyper-V.
Windows Server Containers
Windows Server Container, thực hiện việc đóng gói & chạy các container trên máy tính sử dụng hệ điều hành Windows Server.
Với việc cho ra mắt tính năng mới này, lập trình viên giờ đây có thể đóng gói được những ứng dụng của họ vào trong container và chạy trực tiếp chúng trên Windows Server. Ngoài ra hỗ trợ mới này cũng cho phép lập trình viên sử dụng những công cụ phát triển quen thuộc như Visual Studio để xây dựng các ứng dụng chạy trong container .
Hyper-V Containers
Hyper-V Container đóng gói từng container vào trong một máy ảo gọn nhẹ sử dụng công nghệ ảo hóa Hyper-V (dạng mô hình container chạy trong máy ảo).
Hyper-V Container sử dụng chung tập API với Windows Server Container giúp đảo bảo tính nhất quán trong việc quản lý và triển khai. Ngoài ra Hyper-V Container cũng sử dụng các container image giống với Windows Server Container, giúp đảm bảo tính tương thích của các Windows Container image này.
Ngoài ra, vì ứng dụng mô hình container chạy trong VM nên các Hyper-V Container sẽ bị cô lập gần như tuyệt đối với máy host do các container này sử dụng kernel của các guest OS riêng biệt.
Windows Container hoạt động như thế nào? Hãy xem phần demo của mình dưới đây.
Demo Windows Container – Windows Server Containers
Giống với Linux Container, trước tiên là mình cần có một máy tính chạy Windows Server đang hoạt động. Mình sử dụng Microsoft Azure để tạo một máy ảo chạy Windows Server. Lưu ý rằng phiên bản Windows Server phù hợp để sử dụng được tính năng Windows Container này là Windows Server 2016 Technical Preview 5 trở lên. Xem yêu cầu hệ thống của Windows Container tại đây.
Khi đã có máy tính chạy Windows Server, mình sẽ kết nối với máy tính đó sử dụng ứng dụng Remote Desktop Connection.
Sau khi kết nối được vào máy tính và đăng nhập vào thành công, bước tiếp theo cần làm đó là cài đặt tính năng containers vào máy tính đó để có thể sử dụng được Windows Container. Mình sẽ chạy đoạn mã sau bằng PowerShell để bật tính năng containers lên:
Install-WindowsFeature containers
Sau khi cài đặt tính năng containers vào máy tính thành công, mình cần phải khởi động lại máy tính của mình để thay đổi có hiệu lực.
Windows Container sử dụng Docker Engine làm Container Engine của mình. Do vậy mình cần phải cài đặt nó để có thể sử dụng được tính năng này.
Sau khi máy tính đã được khởi động lại, bước tiếp theo cần làm đó là cài đặt Docker vào máy tính của mình. Mình sẽ chạy đoạn mã sau bằng PowerShell để thực hiện tải về file cài đặt của Docker:
Invoke-WebRequest "https://get.docker.com/builds/Windows/x86_64/docker-1.12.0.zip" -OutFile "$env:TEMP\docker-1.12.0.zip" -UseBasicParsing
Sau đó mình sẽ tiến hành giải nén file cài của Docker vào thư mục Program Files bằng câu lệnh sau:
Expand-Archive -Path "$env:TEMP\docker-1.12.0.zip" -DestinationPath $env:ProgramFiles
Việc tiếp theo mình cần làm là thêm thư mục của Docker vào đường dẫn hệ thống:
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Docker", [EnvironmentVariableTarget]::Machine)
Lưu ý: Bạn cần phải khởi động lại PowerShell để tiếp tục!
Sau đó mình sẽ đăng ký cho Docker chạy dưới dạng Windows service bằng câu lệnh sau:
dockerd --register-service
Sau tất cả các bước trên, mình tiến hành cho chạy Docker service:
Start-Service docker
Sau khi đã chạy thành công Docker service, giờ mình sẽ tiến hành cài đặt một container mẫu từ Docker Hub. Mình sẽ chọn container IIS của Microsoft để tiến hành cài đặt làm container demo.
Cài đặt IIS container
Để tiến hành cài đặt container IIS, mình sẽ chạy đoạn mã lệnh sau bằng PowerShell:
docker run -d -p 80:80 microsoft/iis ping -t localhost
Tham khảo thêm về mã lệnh docker run
tại đây.
Giống với bên Linux, bạn có thể kiểm tra xem container nào đang chạy bằng cách chạy đoạn mã lệnh sau:
docker ps
Sau khi cài đặt container IIS thành công, mình sẽ truy cập vào IP của máy tính để xem xem mình đã cấu hình đúng chưa? Nếu mọi thứ chính xác thì mình sẽ nhìn được thấy màn hình giới thiệu của IIS.
Ngoài hỗ trợ đem tính năng container vào hệ điều hành của mình, Microsoft cũng có một bước tiến mạnh hơn đó là tích hợp công nghệ ảo hóa này vào trong dịch vụ điện toán đám mây Microsoft Azure của mình với việc việc cho ra mắt dịch vụ Azure Container Service. Vậy Azure Container Service là gì? Hãy cùng đón xem phần 2 của bài viết này nhé!
Happy Dockerizing!
một bài giới thiệu quá hay … 😀 … Tks a .. 😛
Bài viết hay quá, đúng cái mình cần 😀
Welcome Gấu 🙂
Tuyệt vời Dũng ơi. Bài viết quá tâm huyết!
thank you anh Thuận đã quan tâm và đọc bài viết ^___^
Sau khi cài đặt container II xong thì giả sử em muốn chuyển nó sang máy linux xài có xài được không anh?
còn việc chuyển container từ máy vật lý xài windows 2016 này sang máy vật lý xài windows 2016 khác thì chuyển thế nào anh?
Bài viết quá hay