為什么要使用云端開發(fā)環(huán)境
2019年5月份,微軟發(fā)布一組VSCode插件“Remote-Development”。它可以讓開發(fā)者在VSCode中直接訪問遠(yuǎn)程的目錄進(jìn)行開發(fā)工作。這樣我們的代碼和開發(fā)環(huán)境就可以和終端電腦分離了 任斋,并且可以隨意在遠(yuǎn)端搭建多個(gè)不同的開發(fā)環(huán)境隨時(shí)切換盈包。 聽起來是不是有點(diǎn)小激動(dòng)呢?
其實(shí)遠(yuǎn)程開發(fā)的模式并不新鮮挡逼。很久以前我就通過FTP或SFTP鏈接,直接在服務(wù)器上進(jìn)行開發(fā)腻豌。但這種方式成本比較高家坎,需要一臺(tái)遠(yuǎn)程服務(wù)器支持,而且多人同時(shí)使用的時(shí)候可能產(chǎn)生版本依賴的沖突吝梅。這幾年容器技術(shù)和應(yīng)用場(chǎng)景猶如獲得神速力的加持般飛速發(fā)展虱疏。結(jié)合容器技術(shù)可以有效的將不同的開發(fā)環(huán)境進(jìn)行區(qū)隔,并且以容器為單位苏携,進(jìn)行復(fù)制做瞪、遷移變得前所未有的簡(jiǎn)單。
所以使用云端開發(fā)環(huán)境有以下幾個(gè)優(yōu)點(diǎn):
- 有多語(yǔ)言右冻、多環(huán)境的開發(fā)需求時(shí)装蓬,可以避免對(duì)本機(jī)環(huán)境的污染
- 方便遷移、復(fù)制纱扭,甚至可以在小組內(nèi)對(duì)同樣的環(huán)境需求進(jìn)行打包牍帚、分發(fā)
- 在局域網(wǎng)內(nèi)搭建開發(fā)服務(wù)器可以節(jié)省筆記本的負(fù)載,更加有效的提升筆記本的使用效率
先介紹一下 Remote-Developement 插件組
微軟發(fā)布了3個(gè)遠(yuǎn)程開發(fā)插件乳蛾,分別是 “Remote-SSH”暗赶、“Remote-Containers”、“Remote-WSL”肃叶,并將它們放入了插件包 “Remote-Developement” 中一同發(fā)布蹂随。
- Remote-SSH:通過ssh,連接遠(yuǎn)程服務(wù)器因惭。(平平無奇)
- Remote-Containers:連接Docker容器岳锁。(非常驚艷)
- Remote-WSL:連接“Windows Subsystem for Linux”(就是在Win10中安裝的Linux)。
今天我們著重介紹如何使用“Remote-Containers”蹦魔,開始吧激率。
準(zhǔn)備Docker環(huán)境
環(huán)境說明
我的桌面系統(tǒng)是MacOS,和Windows的差異版姑,小伙伴們可以自行腦補(bǔ)柱搜。
在安裝Docker的時(shí)候,我們并不需要安裝官網(wǎng)提供的標(biāo)準(zhǔn)安裝包剥险,因?yàn)槟前?code>Docker Engine和Docker Client
。
所以我們需要安裝的是docker-toolbox
宪肖。MacOS可以通過brew search docker-toolbox
找到表制,其他系統(tǒng)可以通過github下載 https://github.com/docker/toolbox/releases
$ brew cask install docker-toolbox
docker-toolbox包含以下幾部分內(nèi)容
- docker-cli : 客戶端命令行,目前的版本是19.03.1
- docker-machine : 可以在本機(jī)啟動(dòng)用于Docker Engine虛擬機(jī)并管理他們
- docker-compose : docker提供的編排工具健爬,支持compose文件,這個(gè)并不常用么介。
- Kitematic : Docker的客戶端GUI娜遵,官方已經(jīng)廢棄了。
- Boot2Docker ISO : 用于創(chuàng)建Docker Engine虛擬機(jī)的鏡像壤短。由于包中的這個(gè)版本并不是最新的设拟,所以創(chuàng)建虛擬機(jī)的時(shí)候可能會(huì)需要重新下載。
- VirtualBox : 虛擬機(jī)
創(chuàng)建Docker Machine
$ docker-machine create --driver virtualbox \
--virtualbox-cpu-count 2 \
--virtualbox-memory 2048 \
default
Running pre-create checks...
Creating machine...
(default) Copying ${HOME}/.docker/machine/cache/boot2docker.iso to ${HOME}/.docker/machine/machines/default/boot2docker.iso...
(default) Creating VirtualBox VM...
(default) Creating SSH key...
(default) Starting the VM...
(default) Check network to re-create if needed...
(default) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env default
創(chuàng)建成功后久脯,連接到Machine
$ eval $(docker-machine env default)
$ docker version
Client: Docker Engine - Community
Version: 19.03.1
API version: 1.40
Go version: go1.12.5
Git commit: 74b1e89
Built: Thu Jul 25 21:18:17 2019
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.5
API version: 1.40 (minimum version 1.12)
Go version: go1.12.12
Git commit: 633a0ea838
Built: Wed Nov 13 07:28:45 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.2.10
GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339
runc:
Version: 1.0.0-rc8+dev
GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
docker-init:
Version: 0.18.0
GitCommit: fec3683
$
$ # OK,連接成功!
從官方Sample開始
先取得官方的Sample項(xiàng)目纳胧。在github上查找 vscode-remote-try
我們可以找到一堆項(xiàng)目,都是微軟官方提供的不同語(yǔ)言環(huán)境的Sample帘撰。這里我們用 vscode-remote-try-python
作為例子跑慕。
$ git clone https://github.com/microsoft/vscode-remote-try-python.git
$ cd vscode-remote-try-python/
$
$ # 打開項(xiàng)目目錄
$ /Applications/Visual\ Studio\ Code.app/Contents/MacOS/Electron ./
$ # windows 使用命令 "code .\"
Sample的目錄結(jié)構(gòu)
[workspace]
|- .devcontainer : 開發(fā)環(huán)境配置目錄
| |- devcontainer.json : 環(huán)境配置文件
| |- Dockerfile : 環(huán)境的Docker鏡像生成文件
|- .vscode : vscode使用的配置文件(容器端使用)
| |- launch.json : debuger 配置文件(容器端使用)
|- static : Sample項(xiàng)目的靜態(tài)頁(yè)面目錄
| |- index.html : Sample項(xiàng)目首頁(yè)
|- .gitattributes : git 文件屬性定義
|- .gitignore : git 忽略文件
|- app.py : flask項(xiàng)目入口
|- LICENSE
|- README.md
|- requirements.txt : 項(xiàng)目的環(huán)境所需要的python模塊,通過pip安裝
下面我們著重介紹 devcontainer.json
和 Dockerfile
兩個(gè)文件
.devcontainer/devcontainer.json
這個(gè)文件是用于啟動(dòng)開發(fā)容器的配置摧找。點(diǎn)擊查看官方文檔核行。下面我們介紹一下配置屬性。
屬性 | 類型 | 描述 |
---|---|---|
通用參數(shù) | ||
name |
字符串 | 容器顯示名稱 |
extensions |
數(shù)組 | 需要安裝到容器中的vscode擴(kuò)展蹬耘。 缺省值"[]"
|
settings |
json對(duì)象 | 添加到容器中的vscode settings.json
|
postCreateCommand |
字符串,數(shù)組 | 容器創(chuàng)建后第一次啟動(dòng)時(shí)執(zhí)行的一組命令芝雪。命令執(zhí)行目錄是容器中workspaceFolder 指定的目錄。多條命令之間使用&& 進(jìn)行連接综苔。 缺省值 none
|
devPort |
整數(shù) | 允許給vscode server指定一個(gè)端口绵脯。缺省為一個(gè)隨機(jī)可用端口。 |
Dockerfile或Image | ||
image |
字符串 | 必填 使用已存在鏡像時(shí)必填休里。 vscode會(huì)使用鏡像名稱來創(chuàng)建開發(fā)容器蛆挫。 |
dockerFile |
字符串 |
必填 使用Dockerfile時(shí)必填。 指定一個(gè)用來生成Docker鏡像的Dockerfile 文件妙黍。路徑相對(duì)于devcontainer.json 文件悴侵。 可以在這個(gè)地址找到各種Dockerfile 樣例。 |
context |
字符串 | 指定運(yùn)行docker build 命令時(shí)的上下文目錄拭嫁。 路徑是基于devcontainer.json 文件的相對(duì)路徑可免。 缺省值"."
|
appPort |
整數(shù),字符串,數(shù)組 | 容器運(yùn)行時(shí)發(fā)布到Host 的端口。多個(gè)端口用數(shù)組表示做粤。 缺省值"[]"
|
workspaceMount |
字符串 | 覆蓋缺省的mount 參數(shù)浇借。語(yǔ)法參見Docker文檔Docker CLI --mount flag。 可以使用${localWorkspaceFolder} 引用本地的工作區(qū)目錄怕品,或使用${env:VARNAMEHERE} 應(yīng)用環(huán)境變量 |
workspaceFolder |
字符串 | 設(shè)置vscode連接到容器后缺省的工作目錄妇垢。 通常結(jié)合workspaceMount 屬性使用。 |
runArgs |
數(shù)組 | 運(yùn)行容器時(shí)的命令行參數(shù)Docker CLI arguments。 缺省值"[]" 闯估。 可以使用${localWorkspaceFolder} 引用本地的工作區(qū)目錄灼舍,或使用${env:VARNAMEHERE} 應(yīng)用環(huán)境變量 |
overrideCommand |
布爾 | 告訴容器在啟動(dòng)時(shí)是否執(zhí)行命令 /bin/sh -c "while sleep 1000; do :; done" ,用以覆蓋缺省的啟動(dòng)執(zhí)行命令涨薪。 缺省值"true" 骑素。 |
shutdownAction |
枚舉: none,stopContainer | 指定在vscode斷開連接或者關(guān)閉時(shí),是否停止容器刚夺。 缺省值"stopContainer"
|
Docker Compose | ||
dockerComposeFile |
字符串,數(shù)組 |
必填 指定一個(gè)Docker Compose文件献丑,路徑相對(duì)于devcontainer.json 文件。 當(dāng)需要擴(kuò)展Docker Compose配置時(shí)侠姑,可以使用數(shù)組创橄。數(shù)組的順序和重要,后面的文件內(nèi)容會(huì)覆蓋之前的設(shè)置结借。 缺省的.env 文件會(huì)在項(xiàng)目的根路徑下尋找筐摘,但可以通過Docker Compose文件中的env_file 指定另外的路徑。 |
service |
字符串 | 必填 指定啟動(dòng)后vscode連接哪個(gè)service船老。 |
runServices |
數(shù)組 | 指定Docker Compose文件中的哪些services需要啟動(dòng)咖熟。同時(shí)在斷開連接后,這些services將會(huì)根據(jù)shutdownAction 的設(shè)置決定是否關(guān)閉柳畔。 缺省值為所有的services馍管。 |
workspaceFolder |
字符串 | 連接到容器后進(jìn)入的工作目錄。缺省值"/"
|
shutdownAction |
枚舉: none,stopCompose | 指定在vscode斷開連接或者關(guān)閉時(shí)薪韩,是否停止容器确沸。 缺省值"stopCompose"
|
那么我們看看Sample中的.devcontainer
文件內(nèi)容。(為了方便顯示俘陷,我過濾的原文件中的注釋)
{
"name": "Python Sample",
"dockerFile": "Dockerfile",
"appPort": [9000],
"runArgs": ["-u", "vscode"],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"python.pythonPath": "/usr/local/bin/python",
"python.linting.pylintEnabled": true,
"python.linting.pylintPath": "/usr/local/bin/pylint",
"python.linting.enabled": true
},
"postCreateCommand": "sudo pip install -r requirements.txt",
"extensions": [
"ms-python.python"
]
}
根據(jù)這個(gè)配置罗捎,我們可以知道。
-
"dockerFile"
: 開發(fā)容器根據(jù)Dockerfile
創(chuàng)建拉盾。Dockerfile
的路徑是.devcontainer/Dockerfile
-
"appPort"
: 容器啟動(dòng)時(shí)publish
了9000
端口到Host
桨菜。這里的Host
就是我們創(chuàng)建的Docker Machine。 -
"runArgs"
: 容器啟動(dòng)時(shí)捉偏,使用vscode
用戶進(jìn)行登錄倒得。(vscode
用戶在Dockerfile
中創(chuàng)建) -
"settings"
: vscode連接到容器后,會(huì)應(yīng)用如下配置:- 終端使用
bash
- 指定
python
命令的路徑 - 啟用
pylint
- 終端使用
-
"postCreateCommand"
: 容器啟動(dòng)時(shí)安裝requirements.txt
文件中的python modules
夭禽。 - 在容器中安裝vscode擴(kuò)展霞掺,
"ms-python.python"
上述內(nèi)容基本上是在說,容器啟動(dòng)時(shí)需要做的事情讹躯。
這里需要強(qiáng)調(diào)一點(diǎn): Remote-Containers是通過"鏡像"來管理環(huán)境的 菩彬。容器只是運(yùn)行時(shí)環(huán)境缠劝,容器是可以隨時(shí)刪除、重建挤巡,并同時(shí)要保證環(huán)境是持續(xù)可用的剩彬。
所以酷麦,容器運(yùn)行時(shí)的配置都放到了devcontainer.josn
文件中矿卑。
下面我們來看看鏡像的生成 - Dockerfile
.devcontainer/Dockfile
關(guān)于Dockerfile
的格式,參見官方文檔沃饶。
看看Sample中的內(nèi)容母廷。
# 基于官方的"python:3"鏡像
FROM python:3
# 切換到非交互模式避免警告
ENV DEBIAN_FRONTEND=noninteractive
# 指定創(chuàng)建的非root用戶
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# 首先更新系統(tǒng)
RUN apt-get update \
# 安裝vscode server需要的基礎(chǔ)軟件
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
&& apt-get -y install git procps lsb-release \
#
# 安裝 pylint
&& pip --disable-pip-version-check --no-cache-dir install pylint \
#
# 創(chuàng)建一個(gè)非root用戶 (為啥需要這個(gè),請(qǐng)看 - https://aka.ms/vscode-remote/containers/non-root-user)
&& groupadd --gid $USER_GID $USERNAME \
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
# [可選] 添加sudo命令
&& apt-get install -y sudo \
# 將新創(chuàng)建的非root用戶添加到sudoers
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME \
#
# 打掃衛(wèi)生
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Switch back to dialog for any ad-hoc use of apt-get
ENV DEBIAN_FRONTEND=
依靠上述兩個(gè)文件糊肤,vscode會(huì)創(chuàng)建指定的鏡像琴昆,和容器。并連接容器進(jìn)入工作區(qū)馆揉。
但由于在墻內(nèi)业舍,我們安裝的速度會(huì)比較慢,所以我們需要隨上述文件做些修改升酣。提高下載速度舷暮。
更改安裝源,提高下載速度
修改Dockerfile
...
# 將debian的更新源改為aliyun的鏡像
RUN sed -i -e 's/\w\+\.debian\.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
# 首先更新系統(tǒng)
&& apt-get update \
...
# 安裝 pylint (使用aliyun鏡像)
&& pip --disable-pip-version-check --no-cache-dir install pylint -i https://mirrors.aliyun.com/pypi/simple/ \
...
修改devcontainer.json
{
"postCreateCommand": "sudo pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/",
}
現(xiàn)在配置都已經(jīng)準(zhǔn)備好了噩茄,下面我們需要連接安裝好的Docker Engine
現(xiàn)在需要通過vscode連接Docker Engine
vscode連接Docker Engine是通過settings
進(jìn)行配置的下面。我們當(dāng)然可以直接修改全局的settings.json
但這樣會(huì)污染全局參數(shù)。我建議通過workspace
級(jí)別的settings
進(jìn)行設(shè)置绩聘。
我們要?jiǎng)?chuàng)建一個(gè)新的workspace
沥割。
在Sample項(xiàng)目的目錄下,新建一個(gè)文件凿菩,命名為python.code-workspace
,內(nèi)容如下:
{
"folders":[
{
"name":"Python Sample",
"path":"."
}
],
"settings": {
"docker.host": "${DOCKER_HOST}",
"docker.tlsVerify": "1",
"docker.certPath": "${DOCKER_CERT_PATH}"
}
}
執(zhí)行
"docker-machine env default"
會(huì)輸出Docker Machine的連接地址和證書目錄机杜。
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://xxx.xxx.xxx.xxx:2376"
export DOCKER_CERT_PATH="/xxx..."
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell:
# eval $(docker-machine env default)
使用
DOCKER_HOST
,DOCKER_CERT_PATH
對(duì)應(yīng)的值填入上面的json
文件。
然后打開Remote-Containers擴(kuò)展衅谷,選擇Reopen in Container
圖解Remote-Containers的部署過程
vscode連接容器的過程中都做了什么工作呢椒拗?我們可以分析一下連接過程輸出的日志信息。
總結(jié)后的內(nèi)容參見下圖会喝。
1. 連接到Docker Engine:
vscode通過在python.code-workspace
文件中的三項(xiàng)配置連接Docker Engine陡叠。
-
"docker.host"
: 服務(wù)器地址及端口 -
"docker.tlsVerify"
: 使用啟動(dòng)TLS驗(yàn)證 -
"docker.certPath"
: 啟動(dòng)TLS的話,證書存放的路徑
由于我們是使用Docker Machine創(chuàng)建的服務(wù)器和連接肢执,證書的生成和配置docker-machine
命令已經(jīng)幫我們做好了枉阵。
2. 構(gòu)建鏡像
再?gòu)?qiáng)調(diào)一次 Remote-Containers是通過"鏡像"來管理環(huán)境的 。
-
Dockerfile
文件通過devcontainer.json
中的"Dockerfile"
屬性指定预茄。
如果使用Compose
文件兴溜,通過"dockerComposeFile"
屬性指定侦厚。 -
鏡像名稱:
缺省情況下,vscode會(huì)根據(jù)環(huán)境生成一個(gè)鏡像名稱拙徽,格式為vsc-<工作區(qū)目錄名>-<UUID>
刨沦。
我們可以通過在devcontainer.json
中添加"image"
屬性,來指定一個(gè)具體的鏡像名稱膘怕。
注1:如果"image"
對(duì)應(yīng)的鏡像已經(jīng)存在想诅,可以不指定"Dockerfile"
屬性。
注2:如果同時(shí)指定了"image"
岛心,"Dockerfile"
,vscode的語(yǔ)法檢查會(huì)給出"warn"
来破。不要擔(dān)心,這個(gè)可以忽略忘古。 -
build時(shí)的上下文目錄:
缺省為.devcontainer
目錄徘禁。
可以通過devcontainer.json的
"context"`屬性指定。
3. 創(chuàng)建并啟動(dòng)容器
-
目錄映射
缺省情況下髓堪,vscode會(huì)將<本地工作區(qū)的目錄>
映射到容器的"/workspace"
目錄送朱。
這里需要強(qiáng)調(diào)一點(diǎn),由于docker run
實(shí)際上是在服務(wù)器端執(zhí)行的干旁,所以<本地工作區(qū)的目錄>
指的是服務(wù)器端的路徑驶沼。
而docker-machine
命令創(chuàng)建的虛擬機(jī)會(huì)自動(dòng)將本地的"/Users"
目錄共享到服務(wù)器的"/Users"
(MacOS上述"/Users"
,其他系統(tǒng)可能有所不同)。所以<本地工作區(qū)的目錄>
在本地和服務(wù)器上同樣有效疤孕。如果服務(wù)器不是由
docker-machine
創(chuàng)建的商乎,那么可以在devcontainer.json
中指定"workspaceMount"
屬性。
例如:
先創(chuàng)建一個(gè)卷docker volume create v-sample-python
然后設(shè)置"workspaceMount": "type=volume,source=v-sample-python,destination=/workspace"
這樣容器就掛載了卷祭阀,從而避免的本地目錄的映射鹉戚。
這種操作的問題是,在容器中對(duì)文件的修改专控,不會(huì)直接和本地文件同步抹凳。我們需要使用git
或其他SCM
工具來管理代碼。 -
端口映射
在Sample中"appPort"
屬性伦腐,指定了映射到服務(wù)器Host
的端口赢底。我們查看一下:$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8588365e7f73 sample-python "/bin/sh -c 'echo Co…" 8 minutes ago Up 7 minutes 127.0.0.1:9000->9000/tcp sample-python
9000
端口雖然打開了,但綁定的是127.0.0.1
地址柏蘑,這根本沒啥用嘛(安裝Docker Desktop版除外)幸冻。
將屬性值改為"appPort": ["0.0.0.0:9000:9000"]
即可。 啟動(dòng)后執(zhí)行命令
vscode有一個(gè)標(biāo)準(zhǔn)的啟動(dòng)后執(zhí)行命令/bin/sh -c "while sleep 1000; do :; done"
咳焚。這行命令讓容器的主進(jìn)程始終循環(huán)洽损。這樣可以保證容器不會(huì)自動(dòng)停止。關(guān)于容器如何不停止的問題請(qǐng)看 Docker初學(xué)者問題 - 如何讓容器啟動(dòng)后不會(huì)自動(dòng)停止
可以通過設(shè)置屬性"overrideCommand"=false
來禁止vscode使用這一命令革半。同時(shí)在"runArgs"
屬性中定制自己的啟動(dòng)命令碑定。-
容器中的用戶
在Dockerfile
中創(chuàng)建了一個(gè)用戶vscode
流码,在容器啟動(dòng)時(shí)通過"runArgs"
屬性的"-u", "vscode"
指定連接到容器的缺省用戶。為什么要?jiǎng)?chuàng)建非root
用戶?可以閱讀說明 Adding a non-root user to your dev container延刘。
這里我簡(jiǎn)要的說明一下漫试,很多基礎(chǔ)鏡像缺省用戶是root
,當(dāng)容器中使用root
用戶創(chuàng)建文件時(shí)碘赖,文件的owner也是root
這有可能導(dǎo)致本地的用戶無法訪問這些文件驾荣。具體根據(jù)目錄映射的形式不同我們分為3種情況:-
vscode連接Docker Desktop安裝的Docker Engine。
這種情況下崖疤,缺省docker run
會(huì)將本地的工作區(qū)目錄mount
到容器中秘车,如果容器使用的是root
用戶典勇,那么容器中創(chuàng)建的文件也相當(dāng)于本機(jī)root
創(chuàng)建的文件劫哼。而本機(jī)的操作用戶(一般來說是非root
用戶)無法訪問。
這時(shí)割笙,就需要根據(jù)本機(jī)的操作用戶的id
和groupid
在Dockerfile
中創(chuàng)建對(duì)應(yīng)的用戶权烧,來解決這一問題褐桌。
本地用戶的id
和groupid
可以通過"id -u"
,"id -g"
命令查看骗随。 -
vscode連接Docker Machine創(chuàng)建的虛擬機(jī)
這種情況下,容器映射的目錄是虛擬機(jī)中的目錄被丧,而虛擬機(jī)的目錄時(shí)通過VirtualBox
來共享的本機(jī)目錄乱顾,由于VirtualBox
的共享會(huì)使用本機(jī)的當(dāng)前操作用戶來作為訪問共享目錄的用戶板祝。所以無論容器中使用什么用戶,都不會(huì)產(chǎn)生問題走净。 -
使用卷或遠(yuǎn)程服務(wù)的目錄做
mount
這種情況與本機(jī)的目錄沒有任何關(guān)系券时,所以不會(huì)產(chǎn)生問題。
-
vscode連接Docker Desktop安裝的Docker Engine。
4. 在容器中安裝vscode擴(kuò)展插件
vscode在連接到容器的環(huán)境后伏伯,會(huì)根據(jù)不同的容器加載不同的插件橘洞。這些插件是安裝在容器中的,不會(huì)污染本機(jī)的插件環(huán)境说搅。
安裝哪些插件由devcontianer.json
中的"extensions"
屬性指定炸枣。
插件會(huì)安裝到容器中的${HOME}/.vscode-server/extensions
目錄。
5. 安裝 "VS Code Server"
"VS Code Server"是做什么用的弄唧?官網(wǎng)有張圖可以說明适肠。
按照我的理解,"VS Code Server"是用來管理容器中的插件并使其可以在本地的vscode中使用候引。
開發(fā)過程
重新構(gòu)建鏡像
由于樣例中使用的是python
的debian
鏡像侯养。個(gè)人感覺鏡像比較大,安裝慢背伴。我比較喜歡Alpine
鏡像沸毁。python
本身有3.7.5-alpine3.10
鏡像峰髓,但我更喜歡直接使用alpine:3.10
,因?yàn)檠b完python
環(huán)境后比官方的Python
或小那么一點(diǎn)點(diǎn)息尺。
添加alpine.Dockerfile
內(nèi)容如下
FROM alpine:3.10
ENV DEBIAN_FRONTEND=noninteractive
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN sed -i -e 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories\
&& apk --update add --no-cache \
libuuid \
gcc \
libc-dev \
linux-headers \
make \
automake \
g++ \
python3-dev \
sudo \
bash \
git \
curl \
python3 \
&& curl https://bootstrap.pypa.io/get-pip.py| python3 - \
&& pip --disable-pip-version-check --no-cache-dir install pylint -i https://mirrors.aliyun.com/pypi/simple/ \
&& addgroup -g $USER_GID $USERNAME \
&& adduser -s /bin/bash -u $USER_UID -G $USERNAME -D $USERNAME \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
VOLUME [ "/workspace" ]
ENV DEBIAN_FRONTEND=
### 修改`devcontainer.json`
```json
{
"dockerFile": "alpine.Dockerfile",
"settings": {
"python.pythonPath": "/usr/bin/python3",
"python.linting.pylintPath": "/usr/bin/pylint",
}
啟動(dòng)Sample項(xiàng)目
啟動(dòng)容器后進(jìn)入flask
項(xiàng)目目錄携兵。然后啟動(dòng)開發(fā)進(jìn)程。
$ FLASK_ENV=development flask run --host 0.0.0.0 --port 9000
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:9000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 320-680-031
切換到本地筆記本搂誉,查看一下Docker主機(jī)的IP徐紧,由于我們使用Docker Machine建立的主機(jī),可以通過下面命令查看炭懊。
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
default * virtualbox Running tcp://192.168.99.122:2376 v19.03.5
192.168.99.122
就是Docker主機(jī)IP了并级。在瀏覽器訪問http://192.168.99.122:9000
由于之前在
devcontainer.json
文件中配置了"appPort": ["0.0.0.0:9000:9000"]
,所以容器在主機(jī)上映射了9000
端口侮腹。
但這種配置在多人共享一臺(tái)Docker主機(jī)嘲碧,或者同時(shí)調(diào)試多個(gè)環(huán)境并產(chǎn)生端口沖突時(shí)會(huì)比較麻煩。
那么下面我介紹一下Forward端口
Forward端口
延續(xù)上一小節(jié)的環(huán)境父阻,我們?cè)谌萜髦袉?dòng)了開發(fā)進(jìn)程愈涩,開放的9000
端口。現(xiàn)在我們做如下操作
- 在
devcontainer.json
中刪除"appPort"
屬性 - 在命令行中使用
docker rm -f sample-python
刪除容器 - 重新在容器中啟動(dòng)項(xiàng)目
- 點(diǎn)擊左下角狀態(tài)欄綠色的部分
- 在出現(xiàn)命令菜單中選擇
Remote-Containers: Forward Port from Container...
- 在出現(xiàn)的下一步的菜單中選擇
Forwarding 9000
- 在瀏覽器打開
http://localhost:9000
地址就可以看到頁(yè)面了加矛。
停止Forward
- 點(diǎn)擊左下角狀態(tài)欄綠色的部分
- 在出現(xiàn)命令菜單中選擇
Remote-Containers: Forward Port from Container...
- 在出現(xiàn)的下一步的菜單中選擇
Stop Forwarding 9000->9000
- 就可以取消端口轉(zhuǎn)發(fā)
Forward端口的好處是不會(huì)占用Docker主機(jī)的端口資源
如果兩個(gè)容器環(huán)境同時(shí)需要Forward同樣的端口怎么辦么履婉?
vscode在Forward的時(shí)候,如果發(fā)現(xiàn)本機(jī)端口被占用斟览,則會(huì)隨機(jī)找一個(gè)可用端口Fowrard到容器中
程序調(diào)試
在sample項(xiàng)目中有一個(gè)文件.vscode/launch.josn
這個(gè)就是調(diào)試配置文件毁腿。sample中已經(jīng)有了Flask
的配置內(nèi)容。我們將其中"FLASK_APP"
項(xiàng)修改成準(zhǔn)確的路徑指向app.py
苛茂。然后啟動(dòng)調(diào)試進(jìn)程已烤。
啟動(dòng)進(jìn)程后我們?cè)?code>app.py的hello()
方法中加入斷點(diǎn)。然后在瀏覽器訪問http://127.0.0.1:9000
(別忘了Forward端口)味悄。
這是你應(yīng)該可以看到草戈,vscode停在了斷點(diǎn)處。
到此為止VSCode使用
Remote-Containers
連接Docker容器的過程基本介紹完畢了侍瑟。