模仿 vscode-server 把原生程式碼目錄對映到外網

2022-12-29 06:00:15


本文模仿 vscode-server 效果,藉助 ssh 、反向代理 的方式把原生程式碼對映到外網,通過 Web IDE 開啟。

概述

vscode 推出了一個新的功能 —— vscode-server,可以把原生的程式碼對映到外網(vscode.dev),通過瀏覽器(Web IDE)修改和偵錯程式碼。

使用者PC 通過安全隧道與 vscode.dev 通訊,連線成功後,使用者將獲得一個裝置程式碼和 URL,你可以任意的可聯網裝置上開啟這個URL 並驗證 GitHub 帳戶後,就可以通過vscode 的 web 版編輯你的PC上的程式碼。

不足的是瀏覽器上使用時會有點卡頓,主要受到網速的影響,而且需要使用github賬號登入,不太方便。

操作步驟:準備一個github的賬號,然後在 vscode UI 或者 code tunnel命令 生成一個外網url,存取這個url就可以在任意聯網裝置上通過瀏覽器瀏覽你本機的程式碼,如果需要偵錯需要安裝一下vscode 外掛。

分析

本地電腦 與 vscode.dev 連線時採用的安全隧道技術,再通過 vscode.dev 存取本地電腦的資料夾,具體的安全隧道技術細節比較複雜這裡不展開,不過從實現的角度,還是有現成的技術可以作為解決方案。首先,為了方便和安全對映本地資料夾目錄到容器;然後,把容器的webide、ssh埠對映到外網;最後,就可以在瀏覽器輸入外網地址存取webide,或者 vscode 的remote ssh功能對原生程式碼進行修改。

解決方案

首先你需要準備 一臺公網的伺服器,以及這臺伺服器對應的公網ip 或者 域名。

  • 啟動一個包含開發偵錯環境的 webide docker 容器,使用 SmartIDE 在原生程式碼目錄下 執行 smartide start 即可

    建立一個容器,檔案對映到你本地資料夾,不直接對映本地會比較安全,也簡單很多,本地作業系統需要對映22會很折騰;另外用 SmartIDE 啟動容器會方便很多,否則你還要自己寫一個映象,環境多了還要維護幾個,乾脆就不折騰了吧。

  • 通過 ssh遠端轉發 或者 ngrok內網穿透 的方式把容器的 SSH埠、WebIDE埠對映到外網
  • 通過瀏覽器開啟外網地址開啟程式碼視窗,或者 通過 VSCode 的 Remote Development (包含Remote SSH) 外掛進行開發偵錯。

準備一臺VM

比較推薦使用 azure 雲,最好是選擇 Ubuntu 系統,包管理更加方便,而且軟體版本也比較新。

建立容器

SmartIDE 建立

## 進入到程式碼目錄
cd CODE_FOLDER

## 執行 smartide start
## 可以到模板庫 https://gitee.com/smartide/smartide-templates.git 檢視您需要的程式碼模板,即開發語言 和 WebIDE型別
## 比如,我是一個 golang 專案,需要使用VSCode 的 webide,指令碼是 
smartide start golang --type vscode 

檢視 SSH 和 WebIDE 對應的埠,如果命令列視窗關閉,也可以通過docker ps命令檢視。

整個過程不算太快,需要花大改2-3分鐘;看到 「SmartIDE 啟動完畢」 的字眼的時候可以關閉命令列,或者 ctrl + c 退出也不會有影響,應該容器已經安裝到你 PC 的docker上了。

直接使用 docker 建立

相比smartide建立的容器,目測簡單一些,但是實際還是有些麻煩,比如本地埠佔用問題,具體的開發語言支援問題 等等,都可能需要自己再編排一下 Dockerfile,而 SmartIDE 把這些坑都踩過了。

  • webide 使用 theia,這個WebIDE的特點是擴充套件性強
  • 開放ssh服務,方便vscode remote ssh連線
  • 需要的開發環境,需要重新編排Dockerfile,這裡暫時略過
## LOCAL_CODE_FOLDER 替換為原生程式碼資料夾路徑
docker run -it --restart always                  \
                     -p              8000:3000     \
                     -p              8022:22       \
                     -v     "LOCAL_CODE_FOLDER:/home/project" \
                     --name theia                  \
                     -d                            \
                                 brjapon/theia-arm64

SSH 遠端轉發

遠端主機設定

## 首先登入 遠端主機
ssh remote_user@remote_host 

## 修改 「/etc/ssh/sshd_config」 , GatewayPorts 執行網路連結埠,AllowTcpForwarding 允許tcp轉發,詳情 https://www.jianshu.com/p/e87bb207977c
## GatewayPorts yes
## AllowTcpForwarding yes
vim /etc/ssh/sshd_config

## 複製本地 ~/.ssh 目錄下的 id_rsa、id_rsa.pub 到遠端主機的 ~/.ssh 目錄下

## 重啟服務 / 重啟遠端主機
systemctl restart sshd

遠端轉發

ssh -N -R 0.0.0.0:remote-port:target-host:target-port  remote_user@remotehost

例如:ssh -N -R 0.0.0.0:8022:0.0.0.0:6822 -R 0.0.0.0:6800:0.0.0.0:6900 [email protected]
參考:https://wangdoc.com/ssh/port-forwarding#遠端轉發

  • remote_port 是你希望連線到遠端主機的埠,如果是雲(比如 Azure)上的主機需要開啟這個埠
  • target-host 本地可以存取的目標 host
  • target-port 本地存取 target-host 使用的埠,比如上面SimpleHTTPServer的 8080
  • remote_user 是連線到遠端主機的使用者名稱
  • remote_host 是遠端主機的地址

內網穿透

目前比較多人用的內網穿透工具有幾個: NPS 支援tcp、udp,以及http、socket5代理,web管理端比較強大;FRP 高效能的反向代理,支援tcp、udp、http、https等;ngrok 知名度最高,1.7以後閉源,但有公網服務可以使用比較方便。
建議使用FRP,NPS 的管理端太重沒有必要,ngrok v1.7後閉源且私有化部署非常費勁(按照網上的辦法部署了多次都是失敗),建議大家避坑。

ngrok

以下直接使用 ngrok.com 官網的服務,國內的也有,但不好用。

## 官網 (https://dashboard.ngrok.com/get-started/setup) 註冊賬號,下載使用者端;
## 進入 rgrok 命令列工具所在目錄;
## 複製token,替換「ngrok_token」 
ngrok config add-authtoken ngrok_token 
## 對映 本地埠 到外網,替換 contarner_binding_port 為本地埠
ngrok tcp localhost:contarner_binding_port

這種效果上最簡單的,藉助公網上的 ngrok 服務,直接對映出去,如圖可以看到內網的資料夾中的內容已經完全對映到了外網,包括隱藏資料夾 bin、obj

frp

從 (releases)[https://github.com/fatedier/frp/releases] 下載作業系統對應的安裝包

├── frpc              使用者端命令列工具
├── frpc.ini          使用者端組態檔
├── frpc_full.ini     使用者端完整設定範例
├── frps              伺服器端命令列工具
├── frps.ini          伺服器端組態檔
└── frps_full.ini     伺服器端完整設定範例

伺服器端

修改組態檔 frps.ini ,範例可以參考 frps_full.ini,完成後 通過 ./frps -c frps.ini 可以啟動 server

[common]
bind_port = 8088
# token 資訊,使用者端也要保持一致
token=smartide666

# dashboard,可以檢視連線情況
dashboard_addr = 0.0.0.0
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin

在 /lib/systemd/system/ 下建立 frps.service

sudo vim /lib/systemd/system/frps.service

錄入以下內容

[Unit]
Description=frps daemon

[Service]
Type=simple
#此處把 frps_folder_path 替換成 frps的實際安裝目錄
ExecStart=frps_folder_path/frps -c frps_folder_path/frps.ini

[Install]
WantedBy=multi-user.target

伺服器自啟動 / 啟動

# 自啟動
sudo systemctl enable frps

# 啟動
sudo systemctl start frps

使用者端

編輯 frpc.ini 檔案

[common]
server_addr = test001.southeastasia.cloudapp.azure.com
server_port = 8088
token = smartide666

[web]
type = tcp
local_ip = 127.0.0.1
local_port = 6900
remote_port = 6900

[ssh]
type = ssh
local_ip = 127.0.0.1
local_port = 6922
remote_port = 6922

啟動 frpc,如果是 mac/linux 自動的方法可以參考 frp 伺服器端設定

./frpc -c ./frpc.ini

效果如下