Thiết lập môi trường development trên Windows 10 với WSL và Docker

WSL và Docker

Docker là gì thì các bài blog trước trên blog của VietnamLab đã giải thích khá khá (bạn đọc có thể search keyword docker trên blog của Vietnam Lab). Một trong những lợi ích của việc sử dụng Docker là giúp cho việc xây dựng môi trường phát triển trên local environment trở nên dễ dàng và đồng nhất giữa các môi trường và máy tính khác nhau. Tuy nhiên, trước đây người dùng Windows muốn sử dụng Docker thì thường phải cài đặt máy ảo Linux trên Virtual Box hoặc các công cụ ảo hóa khác, sau đó mới cài Docker trên máy ảo đó. Hiện tại thì Docker cũng đã cung cấp bộ cài Docker cho Windows, tuy nhiên do Docker trên Windows sử dụng máy ảo Hyper-V nên các ứng dụng ảo hóa khác sẽ không sử dụng được nữa. Do đó nếu sử dụng Docker trên Windows trực tiếp thì người dùng sẽ không còn một môi trường ảo hóa Linux nào để sử dụng nữa (trừ sử dụng Hyper-V).

WSL (Windows Subsystem for Linux) là một công cụ của Windows 10 giúp chúng ta có thể chạy được các hệ điều hành Linux trực tiếp trên Windows mà không cần phải thông qua một tầng ảo hóa. Vì sao Microsoft làm được điều kì diệu này thì là một topic riêng dành cho các chuyên gia hệ điều hành, chúng ta ở đây sẽ tập trung vào mục tiêu chính của WSL là giúp cho trải nghiệm development trên Windows trở nên tốt hơn và hấp dẫn hơn với developer. Hầu hết các hệ thống web hay service hiện tại đều chạy trên Linux server (trừ những hệ thống sử dụng .Net), do vậy việc có thể sử dụng môi trường tương tự để phát triển trên local là một điều khá quan trọng và  có thể có tính quyết định với developer trong việc lựa chọn nền tảng cho chiếc máy tính của mình. Đó cũng chính là lí do mà Microsoft quyết định phát triển WSL.

Nếu bạn đã từng làm việc với Docker thì chắc sẽ có cùng cảm nhận như mình, Docker dùng tiện và cảm thấy ngon nhất khi chạy trên Linux. Dùng Docker trên máy ảo Linux Virtualbox thì performance không được ổn lắm, dùng Docker riêng cho Windows (dù cũng là thông qua một máy ảo Hyper-V) thì ổn hơn, nhưng sử dụng trực tiếp trên Windows thì trải nghiệm không thể được như Linux. Vậy tại sao không kết hợp Docker với WSL, một mũi tên trúng 2 đích, đem lại trải nghiệm tốt nhất cho developer chúng ta.

Cài đặt WSL và Docker

WSL

Trước hết ta cần phải enable WSL và cài đặt 1 hệ điều hành Linux trên Windows 10.

Để enable WSL, vào Control Panel -> Turn Windows features on or off rồi select option Windows Subsystem for Linux như ở hình dưới.

Nếu không có option này thì bạn chịu khó update Windows 10 lên bản mới nhất :D Sau đó Windows sẽ restart, sau đó chỉ cần vào Microsoft Store, tìm một hệ điều hành Linux và cài đặt thôi, như ví dụ ở dưới là Ubuntu

Sau khi cài đặt thành công, từ Start Menu chỉ cần tìm ứng dụng Ubuntu, chạy ứng dụng sau đó cài đặt user ban đầu là xong. Ta đã có một hệ điều hành Ubuntu chạy trên Windows với hầu hết các tính năng như khi chạy trên máy ảo hay máy vật lý

Docker

Docker thì quá đơn giản chỉ việc down bộ bài Docker for Windows từ trang chủ của Docker về cài đặt (https://docs.docker.com/docker-for-windows/install/). Ở trang chủ của Docker có hướng dẫn đầy đủ từ A -> Z. Lần đầu chạy docker, nếu Windows của bạn chưa enable Hyper-V, thì docker sẽ thông báo để enable Hyper-V, sau đó mở cmd lên là bạn có thể test thử docker được rồi.

Thiết lập WSL và Docker

Docker

Đầu tiên ta phải thiết lập để Docker daemon cung cấp một endpoint cho chúng ta kết nối đến mà không cần thông qua TLS (chống chỉ định nếu máy tính của bạn có thể access được từ public network, còn trong các trường hợp khác thì không lo vì endpoint này chỉ access được từ localhost).

End point này sẽ giúp Docker Client ở trong WSL có thể connect được với Docker daemon chạy trên Windows.

Tiếp theo sẽ là thiếp lập shared driver để container có thể access được dữ liệu trên ổ cứng. Về bản chất thì Docker trên Windows vẫn chạy thông qua máy ảo Hyper-V, nên ta vẫn cần có bước này.

Trong trường hợp bạn gặp thông báo lỗi Error: A firewall is blocking file sharing between Windows and the containers khi share folder thì hãy check lại xem firewall rules của mình nhé. Docker sử dụng một internal virtual network tên là DockerNat để thực hiện việc share folder này nên cần setup để cho 2 IP 10.0.75.1 (host Windows) và  10.0.75.2 (máy ảo) có thể kết nối được với nhau thông qua các cổng TCP: 139, 445, UDP:  137, 138.

WSL

Đăng nhập vào Ubuntu với WSL sau đó cài đặt Docker trên Ubuntu theo hướng dẫn ở trang chủ Docker (https://docs.docker.com/install/linux/docker-ce/ubuntu/).

Sau đó cài đặt docker-compose sử dụng pip

# Install Python and PIP.
sudo apt-get install -y python python-pip

# Install Docker Compose into your user's home directory.
pip install --user docker-compose

Vì docker-compose sẽ được cài đặt vào folder $HOME/.local/bin nên cần add folder này vào $PATH

# .bashrc or .profile
export PATH="$PATH:$HOME/.local/bin"

Sau đó để Docker client có thể connect được với Docker daemon chạy trên windows ta cần config để Docker client kết nối với endpoint ta thiết lập ở setting của Docker. Dưới đây là câu lệnh cho bạn nào sử dụng bash, với các shell khác thì cần sửa đổi chút:

echo "export DOCKER_HOST=tcp://localhost:2375" >> ~/.bashrc && source ~/.bashrc

Giờ thì ta đã có thể chạy thử và kiểm tra xem Docker đã chạy ngon ở trên WSL chưa

docker info

docker run -it hello-world

Tuy nhiên vẫn còn một vấn đề ta cần phải giải quyết. Khi sử dụng volume mount  cho container ở trên WSL thì Docker cho windows sẽ yêu cầu sử dụng đường dẫn full path theo filesystem trên windows, ví dụ như là: /c/Users/linhtm/Dev/abczyz (do các drive của Windows như C:\ hay D:\ sẽ được mount trực tiếp vào path /c hay /d trên máy ảo Hyper-V)

docker run --rm -v /c/Users/linhtm/Dev/abcxyz:/data alpine ls /data

Trên WSL, các drive của Windows lại được mount ở /mnt/ folder do vậy câu lệnh trên phải trở thành như dưới đâyy và sẽ xảy ra lỗi vì Docker trên Windows sẽ không nhận ra được đường dẫn mnt ở trong WSL

docker run --rm -v /mnt/c/Users/linhtm/Dev/abcxyz:/data alpine ls /data

Cách xử lý thì ta có thể dùng bind mount để mount /mnt/c vào /c

sudo mkdir /c
sudo mount --bind /mnt/c /c

Ta có thể add dòng lệnh trên vào file .profile hay .bashrc để việc mount sẽ được tự động thực hiện mỗi lần access vào WSL

Ngoài ra ta có thể setting lại WSL để tự động mount các drive Windows vào /. Tạo file /etc/wsl.conf với nội dung như ở dưới đây.

# /etc/wsl.conf

[automount]
root = /
options = "metadata"

Sau đó sign out và sign in windows để restart WSL và thế là ta đã có Docker hoạt động ngon nghẻ trên WSL

Kết luận

Chỉ tốn một chút thời gian và công sức là ta đã có một môi trường Linux với Docker phục vụ đầy đủ các nhu cầu phát triển thông thường. Tất nhiên do Docker trên Windows vẫn chạy thông qua máy ảo Hyper-V nên performance không thể ngang bằng chạy trực tiếp trên Linux, nhưng cũng khá ổn cho việc phát triển trên môi trường local. Theo thông báo của Microsoft thì WSL 2 sắp tới sẽ kèm luôn theo một kernel Linux do đó có thể cài trực tiếp Docker trên WSL không cần phải thông qua các bước setup như trên. Tuy nhiên, từ đây đến lúc đó thì chúng ta có thể tạm hài lòng với sự kết hợp giữa WSL và Docker trên Windows.

Tham khảo