游戏开发工具

vscode 支持Docker

上一节:vscde 支持Emmet下一节:

今天我们要介绍的内容是,如何在 VS Code 中配置、部署和调试 Docker。

在阅读本文之前,首先你需要对 Docker 容器化的知识有所了解。其次,Docker 的操作,都可以通过命令行来实现。所以今天我要着重介绍的就是:VS Code里如何使用 UI 和命令来简化命令行操作,以及如何对 Docker 容器里的代码进行调试,这里我会借助两个简单的例子来讲解。

安装Docker插件

VS Code 的 Docker 支持,是由插件来完成的,这个插件是 VS Code 官方团队维护的,所以它的发布者是 Microsoft。你可以在市场上点击下载,也可以直接在 VS Code 插件视图里搜索 Docker 进行安装。

当然了,这个插件的正确运行,离不开一个正确安装的 Docker 环境。关于 Docker 的安装,还请参考官方文档

1.jpg


安装完Docker插件后,在活动栏上,我们就能够看到一个集装箱的图标,点击它,我们就能够看到 Docker 相关的信息了。

2.jpg

在这个视图中,我们能够看到以下信息:

  • 当前环境中所有的 image;

  • 当前环境中存在的 container;

  • 以及 Docker 的仓库列表。

当我们在 image 上右击时,能够看到一系列的操作,比如查看 image 的信息、发布这个 image、运行 image 等。当然,这些操作同样也可以在命令面板中找到。

3.jpg

我们在 containers 上右击调出的上下文菜单就要简单一些,有三个命令:删除 container、重启 container以及查看这个 container 运行的日志。

4.jpg

Dockerfile

除了提供了一个视图,Docker 插件还能够对 Dockerfile 文件进行语法高亮。

5.jpg

而且也支持自动补全,这样我们就可以通过建议列表来输入 Dockerfile 中的命令了。

1.gif

构建和运行

在书写了正确的 Dockerfile 之后,我们就可以通过这个 Dockerfile 来构建 image 了。为了方便理解,下面我们创建一个新的文件夹,在其中创建一个 Dockerfile。内容如下:

FROM alpine:latest

RUN apk --no-cache add \
    htop

CMD [ "htop" ]

这段 Dockerfile 的意思是,我们希望基于 alpine 系统,安装 htop 这个包,最后运行一个命令 htop,查看当前运行的各种进程。

docker build

接下来,我们就可以打开命令面板,执行 “Docker: Build image” 命令。这个命令会打开集成终端,然后执行 docker build 命令。

1.gif

docker run

生成了 image 之后,我们就可以通过这个 image 来创建 container 了。此时,我们可以通过 Docker 视图的上下文菜单来生成“运行 container”,也可以从命令面板中,运行 “Docker: Run” 命令。然后 VS Code 就会询问我们想要使用哪个 image。

2.gif

docker run interactive

除了 Run 这个命令外,另一个非常有用的命令就是 Run Interactive。通过这个命令,我们可以创建并运行 container,然后进入到这个 container 的 shell 环境汇总。

3.gif

在上面的例子里,我们在 container 里运行的命令是 htop,也就是实时监控系统运行的情况;当我们执行了 “Run interactive” 命令,运行了 contaienr 并且进入到它的 shell 环境中后,我们就立刻看到了 htop 的运行界面。

看到这里你可能已经发现了:对于命令面板里执行每个命令,VS Code 都会打开集成终端,然后运行相对应 Docker 脚本。在你还在学习 Docker 的过程中,你可以先依赖于 VS Code 提供的命令,然后试着去理解 VS Code 每个命令背后的脚本的含义。

而下面这些就需要我们具备一定的 docker 命令行的知识。

输出 log

首先,我们对 Dockerfile 按如下稍作修改。

FROM alpine:latest
RUN apk --no-cache add \
    htop
CMD [ "pwd" ]

我们将Dockerfile中,最后一个配置 CMD 进行了修改。那么,从这个 image 生成的 container 运行起来后,会执行 pwd 命令,而非 htop 命令。

修改完 Dockerfile 之后,第一件要做的事情,就是重新构建 image。在构建这个 image 时,我们可以覆盖之前的那个 image,也可以重新起个名字来创建一个新的 image。比如我就给新的 image 取名为”vscode-docker-sample2:latest”。

有了新的 image 后,接下来就是从 “vscode-docker-sample2:latest” 创建一个新的 container。

1.gif

在运行 docker run 的时候,如果你有留意左侧视图里 “containers” 这个列表的话,你会发现,一个名叫 vscode-docker-sample2 的 container 出现了一下然后又消失了。这是为什么呢?

我们来看一下集成终端,此时集成终端里运行的脚本是:

docker run --rm -d vscode-docker-sample2:latest

这行脚本中有一个参数 ‘–rm’,它的意思是:如果 container 里的命令执行结束的话,那就将这个 container 删除。由于这个 container 中运行的命令是 pwd,这个命令很快就结束了,所以我们来不及在视图中看到并且操作它。如果我们不希望这个 container 被删除该怎么办呢?

我们可以选择手动地运行如下的脚本:

docker run -d vscode-docker-sample2:latest

这一次,我们创建的 container 运行结束后就不会被删除了。也就是此时我们能够在左侧 Containers 列表里,看到 vscode-docker-sample2:latest (dreamy_…) 这个 container 了。它前面的图标里有一个红色的点,这说明这个 container 已经结束工作了。

我们可以在这个 container 上右击调出上下文菜单,选择 Show logs 命令。接着,我们就能够看到这个 container 中 pwd 命令执行的结果了,就是 ‘/’。

1.gif

Docker Compose

除了 Dockerfile 的支持,Docker 插件还支持 Docker Compose。Docker Compose 是用于配置多个 container 并且将其同时运行的。和 Dockerfile 一样,我们一样也可以在 Docker compose file 里获得自动补全和错误检查。

这里,让我们用一个 Node.js 的代码示例,来展示 Docker Compose 以及接下来调试相关的内容。

首先,让我们将上文中创建的 Dockerfile 删除。然后在文件夹下创建一个 JavaScript 文件 index.js,内容如下:

function foo() {
    bar("Hello World");
}

function bar(str) {
    console.log(str);
}

foo();

JavaScript

(上面这段 JavaScript 代码,我们在专栏前面的内容里也经常使用,非常简单。)

接着,我们就需要为这个 JavaScript 代码准备 Docker 相关的配置了。不过值得庆幸的是,Docker 插件已经为我们提供了 Docker 配置的快捷生成方式了。

自动创建 Dockerfile 和 compose 配置

我们只需调出命令面板,然后搜索执行命令 “Docker: Add docker files to workspace”。

1.gif

接着 VS Code 会问我们想要创建什么环境的 Docker image。这里我们选择 Node.js,这样就可以运行上面创建的 index.js 文件了。

命令执行后,工作区内多出了三个文件。第一个文件是Dockerfile。

FROM node:8.9-alpine
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"]
RUN npm install --production --silent && mv node_modules ../
COPY . .
EXPOSE 3000

Shell

这个文件里,指定了 Node.js 8.9 作为基础 image,然后将当前工作目录下的 package.json 、package-lock.json 等都拷贝到 container 中去。接着运行 npm install 命令来安装代码运行所需的 dependencies。不过,由于我们只有一个简单的 JavaScript 文件,我们并不需要 npm,所以我们不妨把这个文件修改为:

FROM node:8.9-alpine
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY . .
EXPOSE 3000

Shell

第二个文件是docker-compose.yml 。这个文件里指定了当前只有一个 container 需要被创建并运行,而且这个 container 需要使用端口 3000。

version: '2.1'

services:
  vscode-sample:
    image: vscode-sample
    build: .
    environment:
      NODE_ENV: production
    ports:
      - 3000:3000

第三个文件是docker-compose.debug.yml。顾名思义,它是用于调试时的 compose 文件,跟上面的 docker-compose.yml 文件相比,它只多了两行代码,也就是:

  • 9229:9229,使用 9229 端口;

  • command: node –inspect index.js ,在 container 运行起来后,运行 node 程序,并且调试 index.js 文件。

version: '2.1'

services:
  vscode-sample:
    image: vscode-sample
    build: .
    environment:
      NODE_ENV: development
    ports:
      - 3000:3000
      - 9229:9229
    ## set your startup file here
    command: node --inspect index.js

Compose Up

在有了这三个配置文件后,要想构建并且运行 container 就简单了。我们不再需要先执行 “Docker: build image ” 再运行 “Docker: run” 了,而是直接运行单个命令——“Docker: compose up” 即可。

1.gif

运行 “Docker: compose up” 后,我们需要选择使用哪个 compose 配置文件。只要准备好了 compose 配置文件,那么在 VS Code 中操作就非常简单了,一共只有三个命令:

  • Docker compose up

  • Docker compose down

  • Docker compose start

如果你想看看 VS Code 是不是真的成功运行了 container,你可以从 Docker 的视图里,找到这个新创建出来的 container,查看它的 log。你能够看到以下结果:

1.jpg

index.js 在 container 里被成功地运行了,而且输出了 Hello World。

调试

我们在前面的文章里,做了这么多的准备工作,既创建了 JavaScript 文件,又使用了 Docker compose。不过这些操作,都是为调试内容做的准备。

这个 JSON 文件里的 configurations 的值就是当前文件夹下所有的配置了。现在我们只有一个调试配置,它有四个属性:第一个是 type,代表着调试器的类型。它决定了 VS Code 会使用哪个调试插件来调试代码。第二个是 request,代表着该如何启动调试器。如果我们的代码已经运行起来了,则可以将它的值设为 attach,那么我们则是使用调试器来调试这个已有的代码进程;而如果它的值是 launch,则意味着我们会使用调试器直接启动代码并且调试。……

当 request 的值被设置为 attach 后,我们就可以将调试器附着到已经处于调试状态的代码进程上了,接着我们就能够调试代码了。而调试 Docker 中的代码,就是使用的 attach 这个方法。我们可以在 Docker container 里以命令行的方式调试代码,并且开放调试端口,接着我们让 VS Code 里的调试插件附着到这个端口上即可。这就是在 VS Code 中调试非本地环境运行的代码的理论知识了。下面,我们一起看看怎么做。首先,我们对 docker-compose.debug.yml 做一点修改,将 command 改成如下的值:

command: node --inspect-brk=0.0.0.0:9229 index.js

这个命令是说,将调试 index.js 文件,然后在第一行停下来,并且使用 9229 这个端口进行调试。接着,让我们运行 “Docker: compose up” 将 container 运行起来。

下一步就是调试代码了。这里,我们使用的 .vscode/launch.json 文件内容如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Docker: Attach to Node",
            "port": 9229,
            "address": "localhost",
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "/usr/src/app",
            "protocol": "inspector"
        }
    ]
}

JSON

这个调试配置有几个属性值得注意:

  • request 是 attach,也就是附着到已经运行的代码上;

  • port 就是调试的端口;

  • localRoot 是本地代码的根目录;

  • remoteRoot 是指在远程运行的代码的根目录。在我们的例子里,我们已经在Dockerfile里指明了工作目录是 /usr/src/app (不记得的话还请翻上去看一看),所以此处我们输入 /usr/src/app。

有了这个调试配置后,F5 我们就能够调试 Docker container 中的代码了,并且停到了第一行代码上。到这里,我们就成功地将一段 JavaScript 代码运行在 Docker 中,并且从 VS Code 里调试起来了。


上一节:vscde 支持Emmet下一节: