在远程Docker主机上进行开发

有时你可能想使用Dev Containers扩展在位于远程服务器上的容器内进行开发。Docker支持将本地文件系统挂载(绑定)到远程开发容器中,因此Visual Studio Code默认的devcontainer.json行为(使用本地源代码)将无法工作。虽然这是默认行为,但在本节中,我们将介绍如何连接到远程主机,以便你可以使用Remote - SSH扩展在容器中打开远程主机上的文件夹,附加到任何正在运行的容器,或者使用本地devcontainer.json文件作为配置、创建和通过套接字连接到远程开发容器的方式。

使用 Remote - SSH 扩展进行连接

如果您使用的是Linux或macOS SSH主机,您可以同时使用Remote - SSH和Dev Containers扩展。您甚至不需要在本地安装Docker客户端。要做到这一点:

  1. 按照Remote - SSH扩展的安装和SSH 主机设置步骤进行操作。
  2. 可选: 设置SSH 基于密钥的认证到服务器,这样你就不需要多次输入密码。
  3. 安装 Docker 在你的 SSH 主机上。你不需要在本地安装 Docker。
  4. 按照快速开始的步骤,使用Remote - SSH扩展连接到主机并在那里打开一个文件夹。
  5. 使用Dev Containers: Reopen in Container命令从命令面板(F1, ⇧⌘P (Windows, Linux Ctrl+Shift+P))。

Dev Containers 快速入门的其余部分同样适用。您可以了解更多关于Remote - SSH 扩展在其文档中的信息。

使用 Remote - Tunnels 扩展进行连接

你可以同时使用Remote - Tunnels和Dev Containers扩展来在容器内打开远程主机上的文件夹。你甚至不需要在本地安装Docker客户端。这与上面的SSH主机场景类似,但使用的是Remote - Tunnels。要做到这一点:

  1. 按照入门指南的说明操作Remote - Tunnels扩展。
  2. 安装 Docker 在你的隧道主机上。你不需要在本地安装 Docker。
  3. 按照步骤为Remote - Tunnels扩展连接到隧道主机并在那里打开一个文件夹。
  4. 使用Dev Containers: Reopen in Container命令从命令面板(F1, ⇧⌘P (Windows, Linux Ctrl+Shift+P))。

Dev Containers 快速入门的其余部分同样适用。您可以了解更多关于Remote - Tunnels 扩展在其文档中的信息。

使用 Docker CLI 连接

此模型仅要求在远程主机上运行一个Docker引擎,并且您的本地Docker CLI可以连接到该主机。虽然使用Remote - SSH和Remote - Tunnels扩展更容易,甚至不需要在本地安装Docker CLI,但此模型对于您已经通过命令行连接的主机的情况非常有用。如果您希望附加到此远程服务器上已经运行的容器,这种方法也很有用。

一个基本的远程示例

设置VS Code以附加到远程Docker主机上的容器可以像在settings.json中设置Docker扩展docker.environment属性并重新启动VS Code(或重新加载窗口)一样简单。

例如:

"docker.environment": {
    "DOCKER_HOST": "ssh://your-remote-user@your-remote-machine-fqdn-or-ip-here"
}

使用SSH需要一个支持的SSH客户端,你已经为远程主机配置了基于密钥的认证,并且密钥已导入到本地SSH代理。有关配置代理和添加密钥的详细信息,请参阅使用SSH密钥与Git的文章。

此时,您可以附加到远程主机上的容器。我们将在本节后面详细介绍如何使用设置和环境变量Docker上下文进行连接。

对于devcontainer.json,还有一个额外的步骤:您需要更新任何配置的(或自动配置的)绑定挂载,使它们不再指向本地文件系统。

此设置有两种变体。第一种是首先创建您的远程开发容器,然后将您的源代码克隆到一个命名的卷中,因为这不需要您直接访问远程主机上的文件系统。

这是一个基本的devcontainer.json设置示例:

{
  "image": "node", // Or "dockerFile"
  "workspaceFolder": "/workspace",
  "workspaceMount": "source=remote-workspace,target=/workspace,type=volume"
}

事实上,命令面板(F1)中的Dev Containers: Clone Repository in Container Volume...命令使用了相同的技术。如果你在GitHub仓库中已经有一个devcontainer.json文件,该文件引用了一个镜像或Dockerfile,该命令将自动使用一个命名卷而不是绑定挂载——这也适用于远程主机。

第二种方法是将远程机器上的文件夹绑定挂载到你的容器中。这要求你能够访问远程文件系统,但也允许你使用远程机器上的现有源代码

更新上面示例中的workspaceMount属性以使用此模型代替:

"workspaceMount": "source=/absolute/path/on/remote/machine,target=/workspace,type=bind,consistency=cached"

无论哪种情况,要尝试它,请运行Dev Containers: Open Folder in Container...,并选择包含.devcontainer.json文件的本地文件夹。

请参阅转换现有或预定义的devcontainer.json以获取有关Docker Compose等其他场景的信息。

使用VS Code设置或本地环境变量连接

如果您已经有一个远程Docker主机在运行,您可以在您的工作区或用户settings.json中使用以下属性来指定主机。

SSH协议

Docker 的最新版本(18.06+)已经增加了对 SSH 协议的支持,以便连接到远程 Docker 主机。这很容易配置,因为你只需要在 settings.json 中设置一个属性即可使用它。

首先,安装一个支持的SSH客户端,配置基于密钥的认证,然后将您的密钥导入到本地SSH代理(在Windows和Linux上通常默认不运行)。有关配置代理和添加密钥的详细信息,请参阅使用SSH密钥与Git的文章。

然后,将以下Docker扩展docker.environment属性添加到settings.json中(根据需要替换值):

"docker.environment": {
    "DOCKER_HOST": "ssh://your-remote-user@your-remote-machine-fqdn-or-ip-here"
}

重新启动VS Code(或重新加载窗口)后,您现在可以附加到远程主机上任何正在运行的容器。您还可以使用专门的本地devcontainer.json文件来创建/连接到远程开发容器

提示: 如果这对您不起作用,但您能够从命令行使用SSH连接到主机,请确保您已经运行了带有认证密钥的SSH代理。如果所有方法都失败了,您可以改用SSH隧道作为备用方案

使用TCP协议

虽然SSH协议有其内置的授权机制,但使用TCP协议通常需要在您的settings.json中设置其他Docker扩展属性。这些属性包括:

"docker.environment": {
    "DOCKER_HOST": "tcp://your-remote-machine-fqdn-or-ip-here:port",
    "DOCKER_CERT_PATH": "/optional/path/to/folder/with/certificate/files",
    "DOCKER_TLS_VERIFY": "1" // or "0"
}

与SSH一样,重新启动VS Code(或重新加载窗口)以使设置生效。

使用环境变量代替settings.json

如果您不想使用settings.json,您可以在终端中设置环境变量。具体步骤如下:

  1. 关闭所有实例的VS Code。
  2. 确保 VS Code 在您的操作系统 PATH 中。
  3. 在终端/命令提示符中设置环境变量(例如 DOCKER_HOST)。
  4. 在同一终端/命令提示符中输入code以启动VS Code并设置变量。

使用Docker上下文连接

Docker Contexts 允许您与不同的主机进行交互 - 您可以为每个主机设置上下文并在它们之间切换。

您可以使用docker context create创建新的上下文。可以使用docker context use 更改当前上下文。

Docker 扩展 提供了 docker.environment 设置,可以设置像 DOCKER_HOSTDOCKER_CONTEXT 这样的环境变量,这些变量也会被 Dev Containers 扩展所使用。

注意: 上述设置仅在安装了 Docker 扩展时可见。如果没有 Docker 扩展,Dev Containers 将使用当前上下文。

转换现有或预定义的 devcontainer.json

要将现有的或预定义的本地devcontainer.json转换为远程的,请按照以下步骤操作:

  1. 在 VS Code 中打开一个本地文件夹(不是远程的),您希望在其中转换文件。

  2. 如果您没有选择包含devcontainer.json的文件夹,您可以通过从命令面板(F1)运行Dev Containers: 添加容器配置文件...来选择一个预定义的配置文件。

  3. 根据你的.devcontainer/devcontainer.json.devcontainer.json引用的内容,按照以下步骤修改源代码挂载:

    Dockerfile 或镜像:

    如果您没有远程主机的登录权限,请为您的源代码使用Docker“卷”。按如下方式更新.devcontainer/devcontainer.json(如果需要,可以用唯一的卷名称替换remote-workspace):

    "workspaceMount": "source=remote-workspace,target=/workspace,type=volume"
    "workspaceFolder": "/workspace",
    

    如果您确实有登录权限,您可以使用远程文件系统绑定挂载来代替:

    "workspaceMount": "source=/absolute/path/on/remote/machine,target=/workspace,type=bind,consistency=cached"
    "workspaceFolder": "/workspace",
    

    workspaceMount 属性支持与 Docker CLI --mount 标志 相同的值,如果您有其他的使用场景。

    Docker Compose:

    如果您没有远程主机的登录权限,请更新(或扩展)您的docker-compose.yml。将your-service-name-here替换为devcontainer.json中为"service"属性指定的值,并将remote-workspace替换为唯一的卷名称:

    version: '3'
    services:
      your-service-name-here:
        volumes:
            - remote-workspace:/workspace
        # ...
    
    volumes:
      remote-workspace:
    

    如果您确实有登录权限,您可以使用远程文件系统绑定挂载来代替:

    version: '3'
    services:
      your-service-name-here:
        volumes:
          - /absolute/path/on/remote/machine:/workspace:cached
        # ...
    

    如果需要支持不同的场景,请参阅Docker Compose 文档中的 volumes

  4. 从命令面板(F1)运行Dev Containers: Reopen in Container命令或Dev Containers: Rebuild Container

  5. 如果你使用了卷而不是绑定挂载,请使用 ⌃⇧` (Windows, Linux Ctrl+Shift+`) 在容器内打开终端。你可以从这里运行 git clone 来拉取你的源代码,并使用 文件 > 打开... / 打开文件夹... 来打开克隆的仓库。

下次你想连接到同一个容器时,运行Dev Containers: Open Folder in Container...并在VS Code窗口中选择相同的本地文件夹。

可选:使远程源代码在本地可用

如果您将源代码存储在远程主机的文件系统上,而不是Docker卷内,有几种方法可以在本地访问这些文件:

  1. 使用SSHFS挂载远程文件系统.
  2. 使用rsync从远程主机同步文件到本地机器
  3. 如果您正在使用Docker Machine,请使用mount命令

使用SSHFS或Docker Machine的挂载命令是更方便的选择,并且不需要任何文件同步。然而,性能将比通过VS Code工作显著慢,因此它们最适合用于单个文件编辑和上传/下载内容。如果您需要使用一个应用程序来批量读取/写入许多文件(如本地源代码控制工具),rsync是更好的选择。