容器化技术为软件开发带来了革命性的变化,它通过隔离开发环境,确保应用程序在不同机器上运行的一致性。容器包含了所有必需的依赖,并且确保了它们的正确版本,无需任何更改,容器就可以在本地、云计算节点、Kubernetes Pod中部署。然而,这些优势并非没有代价。直到最近,开发容器化应用程序时,开发者无法直接使用他们喜欢的IDE工具(例如,VS Code、PyCharm、CLion、Eclipse)来编辑文件或调试运行在容器中的应用程序。开发者不得不寻找捷径和变通方法。
如果开发是在本地运行的容器中进行的,可以将本地文件系统挂载到容器内部,并使用IDE在本地编辑文件,同时看到容器中的更改。对于调试,有些人尝试在容器内安装远程调试服务器(例如,对于C++的gdbserver,对于Python的ptvsd)。其他开发者会安装窗口系统、VNC服务器和IDE在容器内,并使用VNC客户端连接并在容器内工作。然而,大多数开发者会完全放弃IDE工具,转而使用传统的(但功能强大的)终端编辑器(例如,vi或emacs)和命令行调试器(例如,gdb)。
2019年5月发布的Visual Studio Code(版本1.35)带来了全新的远程开发和远程容器扩展。这些扩展允许使用Docker容器(本地、远程、Kubernetes Pod)作为全功能的开发电机环境,来编辑和调试VS Code或其插件支持的任何语言。唯一的要求是能够通过SSH访问容器。
本文将展示如何轻松地使用VS Code在运行中的容器中编辑文件和调试C++或Python服务。
在本文的编写过程中,使用了一台Windows 10 Enterprise笔记本电脑(以下简称本地系统)和一台Google Cloud Compute Engine VM(以下简称远程系统)。然而,描述的工作流程将适用于其他云提供商。本地系统需要安装以下软件:
需要在本地系统上生成并安装SSH私钥(参见)。
远程系统需要安装以下软件:
确保已经配置了首选的容器注册表的访问权限(例如,参见)。
要验证设置是否正确,请确保可以使用其IP地址通过SSH连接到远程系统:
PS C:\> ssh drepin@10.128.0.79
Last login: Thu Aug 1 14:17:46 2019 from openvpn.internal
drepin@drepin-dev ~
在远程系统上,拉取将要使用的工作容器:
drepin@drepin-dev$ docker pull gcr.io/your-project/server-dev
启动第一个PowerShell并发出以下命令,将本地Docker客户端连接到远程主机上的Docker Engine:
PS C:\> ssh -NL localhost:23750:/var/run/docker.sock drepin@10.128.0.79
创建一个空文件夹,并将一个${FOLDER}/.devcontainer.json
文件放入其中。该文件的格式在有描述。下面是一个用于C++远程开发的容器的示例文件:
{
"name": "brick-client-dev",
"image": "gcr.io/your-project/server-dev",
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"appPort": [8050],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"extensions": [
"ms-vscode.cpptools"
]
}
启动第二个PowerShell并发出以下命令,设置DOCKER_HOST
环境变量,并在刚刚创建的文件夹中启动VS Code:
PS C:\> $env:DOCKER_HOST="localhost:23750"
PS C:\> cd ${FOLDER}; code .
在VS Code中,运行命令Remote-Containers: Reopen Folder in Container
,要么通过点击Reopen in Container
按钮...要么通过输入
"Remote-Containers: Reopen Folder in Container"。
VS Code将开始在容器内安装VS Code Server和插件:
一两分钟后,将能够在容器内编辑、构建和调试代码。
VS Code目前还不支持非root容器,例如,从这样的Dockerfile创建的容器:
FROM ubuntu:18.04
USER 1000
为了解决这个限制,建议以用户0启动容器,并使用VS Code连接到它:
docker run -it --rm --user 0 --entrypoint /bin/sh gcr.io/your-project/server-dev