個人主力操做系統是 windows, 但有時不得不須要一些 linux 下的特性, 好比某些工具沒有 windows 版本, 沒法使用 MakeFile 等.html
自從微軟推出了 Windows Subsystem for Linux (WSL) 以後, 這種狀況已經好了很多了. 具體使用能夠參考 官方 WSL 文檔.java
但我不太習慣使用它, 平常中更偏心的是 docker. 畢竟仍是鏡像方便點, 須要什麼組件就 pull 下來, 用完了或者中間搞壞了, 從新開一個就好了, 成本很低.mysql
jetbrains 的 IDE 是支持 remote development(遠程開發)的, 幸虧, VS Code 也開始支持了.linux
所謂的遠程開發, 就是將遠程的服務器, 或者容器, 或 WSL 做爲開發環境. 本地的代碼實時同步到遠程中, 而各類工具好比命令行都是在遠程環境中運行的.nginx
下面就來介紹下如何使用 VS Code 進行遠程開發.git
首先, 須要在 VS Code 中安裝對應的插件, Remote Development extension pack.github
這實際上是插件集合, 包括了 Remote-SSH , Remote-Containers, Remote-WSL 等.golang
安裝完成以後, 重啓 VS Code. 左下角會出現一個圖標, 相似於 ><
. 點擊以後, 會彈出對應的命令選擇框.web
這裏主要介紹 Remote-Containers
, 其餘的 Remote-SSH 和 Remote-WSL 也相似, 具體能夠參考官方文檔說明.sql
上圖是官方文檔上的構架圖, 能夠看到源代碼是經過卷映射進去的, 命令行和運行 APP 和 Debugger 都是在容器中完成的.
系統要求 直接看官方文檔吧, 這裏再也不解釋. 一般本地裝好 docker 就好了.
要在容器中打開項目, 會面臨多種選擇:
詳細梳理一下流程:
選擇 Remote-Containers: Reopen Folder in Container
, 若是此時本地尚未對應的配置, 就會觸發 新建配置
的過程. 這時可能有多種選項, 取決於本地項目中是否存在 Dockerfile
和 docker-compose.yml
文件.
From a predefined container configuration definition...
. 這個選擇會顯示預約好的配置文件, 能夠根據本身使用的語言或技術棧選擇對應的配置.Dockerfile
: From Dockerfile
. 這會使用本地的 Dockerfile
構建容器.docker-compose.yml
: From docker-compose.yml
. 這個選擇本地的 docker-compose.yml
中的其中一個容器做爲開發環境.選擇 Remote-Containers: Attach to Running Container...
, 會進入到 附加到已運行的容器中
的過程. 此時, 選擇對應的本地容器就好了.
其餘的打開方式包括:
Remote-Containers: Open Folder in Container...
Remote-Containers: Open Workspace in Container...
Remote-Containers: Open Repository in Container...
配置文件保存在 .devcontainer
中:
devcontainer.json
配置選項Dockerfile
若是新建時選擇 Dockerfile
docker-compose.yml
若是新建時選擇 docker-compose.yml
更多配置選項能夠參考 devcontainer.json reference
對於 C++, Go, Rust 等使用 ptrace-based debugger 的語言, 須要開啓如下配置:
修改 devcontainer.json
文件
"runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"]
複製代碼
若是使用 docker-compose.yml
則 修改 docker-compose.yml
文件
# Required for ptrace-based debuggers like C++, Go, and Rust
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined
複製代碼
擴展會被分爲兩個部分, 本地和遠程的.
本地的擴展主要是一些 UI 相關的, 其餘擴展都安裝在容器中的.
這可能對於多語言開發者(潔癖患者)來講是個不錯的狀況, 只要在容器中安裝相應語言所需的擴展就好了, 能夠無縫切換工做流.
對於想要徹底同步本地擴展的用戶, 可使用命令 Install Local Extensions in Dev Container:
將全部的本地擴展都安裝在容器中.
有時候, 不少擴展是必裝的, 能夠在設置中修改默認擴展
:
"remote.containers.defaultExtensions": [
"eamodio.gitlens",
"mutantdino.resourcemonitor"
]
複製代碼
擴展只能運行在一個位置, ui
或 workspace
, 能夠在 devcontainer.json
中強制指定擴展運行的位置.
"settings": {
"remote.extensionKind": {
"ms-azuretools.vscode-docker": "workspace"
}
},
複製代碼
若是你在開發 web 應用, 不少時候都須要進行端口轉發, 以便在本地的瀏覽器中調試, 這個時候可使用端口轉發功能.
在命令面板(F1)中選擇 Remote-Containers: Forward Port from Container...
上面的操做一般用於臨時轉發端口.
若是你有固定的端口要轉發, 能夠選擇如下兩種方式之一:
修改 devcontainer.json
配置文件:
"appPort": [ 3000, "8921:5000" ]
複製代碼
或者若是使用的是 docker-compose.yml
文件, 直接添加端口:
ports:
- "3000"
- "8921:5000"
複製代碼
終端已經變成了容器中的終端, 而不是本地的終端了.
享受 linux 的便利吧.
如今設置文件已經有三份了, 相比普通的用戶設置和工做空間設置, 多了一個容器設置, 優先級是最高的.
也能夠在 devcontainer.json
設置一些默認的容器設置:
"settings": {
"java.home": "/docker-java-home"
}
複製代碼
若是使用 HTTPS 克隆項目, 且使用 憑據助手 則無需任何操做就能夠共享憑據.
若是使用 SSH 密鑰, 主要將 ~/.ssh
安裝到容器中就好了.
不過 windows 上有點小問題, .ssh
中的內容不會直接複製到容器中.
不過官方文檔也提供瞭解決方案.
第一步:
複製 .ssh
文件夾到容器中.
若是使用 Dockerfile 或預約義的配置, 將下面的內容添加到 devcontainer.json
文件中:
"runArgs": [ "-v", "${env:HOME}${env:USERPROFILE}/.ssh:/root/.ssh-localhost:ro" ]
複製代碼
若是使用 docker-compose.yml
, 更新 volumes
字段:
version: "3"
services:
your-service-name-here:
# ...
volumes:
- ~/.ssh:/root/.ssh-localhost:ro
複製代碼
第二步:
複製密鑰, 並設置權限.
將如下內容複製到 devcontainer.json
文件中:
使用 root 身份運行容器時
"postCreateCommand": "mkdir -p /root/.ssh && cp -r /root/.ssh-localhost/* /root/.ssh && chmod 700 /root/.ssh && chmod 600 /root/.ssh/*"
複製代碼
使用非 root 身份運行容器時
"postCreateCommand": "sudo cp -r /root/.ssh-localhost ~ && sudo chown -R $(id -u):$(id -g) ~/.ssh-localhost && mv ~/.ssh-localhost ~/.ssh && chmod 700 ~/.ssh && chmod 600 ~/.ssh/*"
複製代碼
若是已經建立了容器了, 須要運行命令 Remote-Containers:Rebuild Container
從新構建容器, 以使得改變生效.
在項目的 .gitattributes
文件中添加如下內容:
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
複製代碼
如下配置文件來自於 go_web, 這是一個使用 Go 語言創建 web 應用的示例項目.
.devcontainer/devcontainer.json
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
"name": "Existing Docker Compose (Extend)",
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": ["..\\docker-compose.yml", "docker-compose.yml"],
// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "web",
// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/workspace",
// Use 'settings' to set *default* container specific settings.json values on container create.
// You can edit these settings after create using File > Preferences > Settings > Remote.
"settings": {
// This will ignore your local shell user setting for Linux since shells like zsh are typically
// not in base container images. You can also update this to an specific shell to ensure VS Code
// uses the right one for terminals and tasks. For example, /bin/bash (or /bin/ash for Alpine).
"terminal.integrated.shell.linux": null
},
// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created - for example installing git.
// "postCreateCommand": "apt-get update && apt-get install -y git",
// Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [],
// Mount your .ssh folder to /root/.ssh-localhost so we can copy its contents
"runArgs": [
// "-v",
// "${env:HOME}${env:USERPROFILE}/.ssh:/root/.ssh-localhost:ro"
],
// Copy the contents to the correct location and set permissions
"postCreateCommand": "mkdir -p ~/.ssh && cp -r ~/.ssh-localhost/* ~/.ssh && chmod 700 ~/.ssh && chmod 600 ~/.ssh/*"
}
複製代碼
.devcontainer/docker-compose.yml
--- #-------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
version: "3.7"
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
web:
# You may want to add a non-root user to your Dockerfile. On Linux, this will prevent
# new files getting created as root. See https://aka.ms/vscode-remote/containers/non-root-user
# for the needed Dockerfile updates and then uncomment the next line.
# user: vscode
# Uncomment if you want to add a different Dockerfile in the .devcontainer folder
# build:
# context: .
# dockerfile: Dockerfile
# Uncomment if you want to expose any additional ports. The snippet below exposes port 3000.
# ports:
# - 3000:3000
volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- .:/workspace
- ~/.ssh:/root/.ssh-localhost:ro
# Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-in-docker-compose for details.
# - /var/run/docker.sock:/var/run/docker.sock
environment:
GOPROXY: "https://goproxy.io"
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
複製代碼
docker-compose.yml
version: "3.7"
services:
web:
image: golang:1.13
# https://docs.docker.com/compose/compose-file/#init
init: true
volumes:
- .:/home/web
environment:
GOPROXY: "https://goproxy.io"
mysql:
image: mysql:8
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: "1234"
ports:
- 3306:3306
adminer:
image: adminer:4
ports:
- 8080:8080
dbclient:
image: mysql:8
command: mysql -hmysql -uroot -p1234 -D db_apiserver
# mysql -hmysql -uroot -p1234
# source /home/script/db.sql
# select * from tb_users \G;
volumes:
- ./script:/home/script
nginx:
image: nginx:stable-alpine
ports:
- 80:80
volumes:
- ./conf/nginx_web.conf:/etc/nginx/conf.d/nginx_web.conf
command: nginx -g 'daemon off;'
複製代碼