Sau nhiều lần thử không thành công, cuối cùng mình cũng đã có thể ảo hóa macOS để chạy thử ứng dụng iOS. Nhưng trước làm theo, thì bạn nên biết đây không phải là một giải pháp ổn định và có một số vấn đề về hiệu suất. Mình vì một số lý do nên mới cần phải làm như vậy.
Mình sẽ sử dụng QEMU để giả lập máy mac và bên trong nó, chúng ta sẽ sử dụng xCode để giả lập iOS. Quá trình này sẽ không hề nhẹ. Kho lưu trữ trên github của Docker OSX có giải thích về cách sử dụng iPhone qua usb thay vì giả lập, nhưng mình không có iPhone :((.
Docker OSX là gì
Docker OSX là một image docker sử dụng QEMU để chúng ta có thể giả lập một hệ điều hành.
Bạn có thể tìm hiểu thêm về Docker tại đây.
Thông số phần cứng khi giả lập iOS bằng Docker
Thông số kỹ thuật máy tính của mình được coi là khá ổn để thực hiện việc này, tuy nhiên, mình vẫn cảm thấy độ trễ khi sử dụng Docker OSX + xCode + Visual Studio Code + Dev Server. (Cái máy như cái lò sưởi :v)
- OS: Manjaro Linux x86_64
- Kernel: 4.19.220-1-MANJARO
- Shell: zsh 5.8
- Độ phân giải: 1440×900
- DE: GNOME 41.2
- WM: Mutter
- WM Theme: Orchis-orange-compact
- Icons: Win11-purple-dark [GTK2/3]
- Terminal: gnome-terminal
- CPU: Intel i7-3770 (8) @ 3.900GHz
- GPU: NVIDIA GeForce GTX 1050 Ti
- RAM: 4105MiB / 15985MiB
- SSD: Crucial BX500 240gb (Khuyến cáo nên sử dụng SSD nhé)
Cài đặt
Đầu tiên, cần phải cài đặt docker trên máy tính của bạn. Mình sử dụng Manajaro, vì vậy mình chỉ cần mở terminal và nhập các lệnh sau:
Cài đặt docker: pacman -S docker
Chạy docker: systemctl start docker.service
Bật docker khởi động cùng hệ thống:systemctl enable docker.service
Kiểm tra docker:docker run hello-world
Tiếp theo, chúng ta sẽ tải docker osx và chạy nó bằng lệnh dưới:
docker run -it --device /dev/kvm -p 50922:10022 -e DEVICE_MODEL="iMacPro1,1" -e WIDTH=1440 -e HEIGHT=900 -e RAM=8 -e INTERNAL_SSH_PORT=23 -e AUDIO_DRIVER=alsa -e CORES=2 -v /tmp/.X11-unix:/tmp/.X11-unix -e "DISPLAY=${DISPLAY:-:0.0}" -e GENERATE_UNIQUE=true -e MASTER_PLIST_URL=https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-custom.plist sickcodes/docker-osx:big-sur
Bạn có thể kiểm tra ý nghĩa của từng flag tại github của docker osx. Nhưng để tóm tắt ngắn gọn thì mình đã chỉ định độ phân giải, bộ nhớ, lõi cpu, phiên bản và những thứ khác.
Sau đó, osx docker sẽ được tải xuống và khởi tạo.
Khi trình giả lập mở ra, hãy chọn macOS Base System
Khi hệ thống được khởi động, hãy chọnDisk Utility
Bây giờ, chúng ta sẽ tìm phân vùng đã chuẩn bị và chọn Erase.
Để định dạng, các tùy chọn phải hoàn toàn giống như hình dưới:
Nhấp vào Erase, đợi quá trình kết thúc và sau đó bạn có thể đóng cửa sổ Disk Utility.
Tiếp theo, chọn Reinstall macOS Big Sur
, chấp nhận các điều khoản và chọn phân vùng chúng ta vừa tạo macOS và bắt đầu cài đặt. (Quá trình này có thể mất tầm 30 phút tới 1 tiếng).
Hệ thống sẽ tự khởi động lại (hoặc không), mình phải làm điều đó theo cách thủ công vì nó không khởi động lại. Trong trường hợp đó, hãy đóng cửa sổ QEMU.
Trong terminal, chúng ta sẽ nhập:
docker ps -a
Để biết ID container của chúng ta là gì và thì các bạn cần nhập lệnh dưới:
docker start ID
Sau đó, hệ thống sẽ tự động khởi động lại (hoặc không), nên hãy đóng QUEMU lại và khởi động lại container.
Khi hệ thống khởi động, hãy chọn tùy chọn macOS Installer
và đợi quá trình kết thúc. Khi kết thúc, hệ thống sẽ khởi động lại.
Vậy là macOS đã được cài đặt thành công rồi đó. Chọn macOS
.
Màn hình chào mừng của macOS đã xuất hiện, lúc này bạn cần thiết lập macOS.
Khi định cấu hình hệ thống, nhưng đừng đăng nhập AppleID.
Khi quá trình đó hoàn tất, màn hình của chúng ta sẽ xuất hiện và chúng ta sẽ đợi cho đến khi thanh dock xuất hiện vì sau đó, hệ thống sẽ ổn định nhất.
Bây giờ, chúng tôi sẽ sử dụng brew để cài đặt các package (gói) nhanh hơn.
Mở terminal trong macOS và cài đặt brew
bằng lệnh dưới đây:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Nhập mật khẩu của bạn và đợi quá trình kết thúc.
Bây giờ, chúng ta sẽ cài đặt xcode trên Apple Store.
Lúc này, chúng ta mới cần đăng nhập AppleID.
Sau đó, mở xcode và chấp nhận các điều khoản và đợi cài đặt các dependencies.
Tiếp theo vào Preferences -> Locations -> Command-Line Tools, chọn phiên bản xCode.
Khi quá trình cài đặt hoàn tất, chúng ta sẽ mở lại terminal và cài đặt cocoapods bằng lệnh dưới. Nó đóng vai trò là trình quản lý packager của xCode.
brew install cocoapods
Cuối cùng, macOS của chúng ta sẽ được cài đặt và cấu hình để chạy các dự án.
Chạy ứng dụng với React Native
Tiếp theo, chúng ta sẽ thử chạy 1 chương trình React Native đơn giản. Mình chỉ test trên iOS thôi nhé.
Mở tterminal và nhập các lệnh sau:
Cài đặt node: brew install node
Cài đặt yarn (không bắt buộc): npm install -g yarn
Tạo dự án RN: npx react-native init teste
Nếu yêu cầu bạn cài đặt lại cocoapods, hãy chọn tùy chọn có brew.
Truy cập vào thư mục dự án: cd teste
Truy cập vào thư mục ios: cd ios
Cài đặt các dependencies: pod install
Quay lại thư mục gốc: cd ..
Liệt kê tất cả các thiết bị có sẵn (không bắt buộc): xcrun simctl list devices
Chạy dự án với xcode: npx react-native run-ios --simulator="iPhone 13"
Chạy ứng dụng với Cordova
Tiếp theo là chạy dự án với Quasar để kiểm tra xem mọi thứ chúng ta đã làm có hoạt động hay không.
Quasar sử dụng Cordova / Capacitor cho iOS và Android.
Cài đặt node: brew install node
Cài đặt yarn: npm install -g yarn
Cài đặt quasar: yarn global add @quasar/cli
Cài đặt cordova: yarn global add cordova
*Tạo dự án với Quasar: quasar create teste
Truy cập vào thư mục dự án: cd teste
Thêm cordova vào dự án của bạn: quasar mode add cordova
Truy cập vào thư mục cordova: cd src-cordova
Thêm iOS vào dự án: cordova platform add ios
Xác minh xem mọi thứ có ổn không: cordova requirements
Liệt kê tất cả thiết bị có sẵn (không bắt buộc): cordova emulate iOS --list
Cài đặt các dependencies: yarn
Quay lại thư mục gốc: cd ..
Cài đặt các dependencies: yarn
Chạy quasar với chế độ phát triển trên iOS: quasar dev -m iOS -e "iPhone 8, 15.2"
Tạo kết nối các thư mục qua SSH
Bây giờ ứng dụng của chúng ta đã chạy trên macOS, nhưng sẽ có một số vấm đề: Mở code editor hoặc IDE bên trong macOS là một trải nghiệm rất tệ vì máy chạy chậm, lỗi, mapping bàn phím,… Vì vậy, mình đã nghiên cứu giải pháp tạo kết nối tệp bằng SSH.
Ngoài ra, mình có thể mở máy chủ phát triển bên trong macOS và tạo kết nối trực tiếp từ linux hoặc macOS của mình để nó cập nhật cả hai bên, giống như hai chiều. Điều này đảm bảo chúng ta tận dụng hết tính năng trong chế độ phát triển, chẳng hạn như fast refresh.
Kết nối từ linux đến mac
Đầu tiên, chúng ta cần cho phép kết nối qua ssh thông qua mac. Để làm điều này, chúng ta cần mở terminal và nhập:
Lệnh để mở chỉnh sửa tệp cấu hình ssh: sudo nano /etc/ssh/sshd_config
Tìm PasswordAuthentication
và đặt yes
và xóa # ở dòng đầu.
Lưu file lại.
Vào System Preferences -> Sharing -> Remote Login và kích hoạt all users:
Lệnh khởi động lại ssh: sudo launchctl stop com.openssh.sshd && sudo launchctl start com.openssh.sshd
Bây giờ, trong terminal linux:
Cài đặt sshfs: sudo pacman -S sshfs
Lấy IP container: docker inspect -f '' ID_CONTAINER
Tạo thư mục: mkdir projeto
Lệnh để mở một kết nối mới tới mac: sudo sshfs USER_MAC@IP_CONTAINER:/PATH/OF/PROJECT/ON/MAC /PATH/ON/LINUX -p 23
Ví dụ:
Được rồi, bây giờ chúng ta có thể mở VSCode trên linux và cập nhật tệp trực tiếp trên mac.
Kết nối từ Mac với Linux
Cũng tương tự như trên, nhưng gói sshfs trên mac có thể được cài đặt bằng lệnh dưới đây:
Cài đặt sshfs: brew install --cask macfuse && brew install gromgit/fuse/sshfs-mac
Trên Linux:
Lệnh chỉnh sửa tệp cấu hình ssh: sudo nano /etc/ssh/sshd_config
Tìm PasswordAuthentication
và đặt yes
và xóa # ở dòng đầu.
Lưu lại file.
Lệnh khởi động lại SHH trên Manjaro: sudo systemctl restart sshd.service
Trên Mac, chúng ta sẽ tạo một thư mục để mở kết nối.
Tạo thư mục: mkdir projeto
Lệnh mở kết nối mới tới linux: sudo sshfs USER_LINUX@IP_HOST:/PATH/LINUX /PATH/MAC -p 23
Khi chúng ta gõ lệnh sẽ xảy ra lỗi.
Mở preferences và nhấp vào Allow
Khởi động lại máy mac của bạn.
Bây giờ, chúng ta có thể mở kết nối: (SSH của mình được mở ở một cổng khác, nhưng mặc định là 22)
Sau khi hoàn tất, chúng ta có thể cập nhật từ một trong hai bên. Vậy là xong rồi đó, rất thích hợp cho việc remote, code team nhé.