新知识点!一文告诉你如何调试运行在Docker容器中的远程Node.js应用程序

作者 | Terence Shin

翻译 | 天道酬勤,责编 | Carol

出品 | CSDN云计算(ID:CSDNcloud)

你知道吗?

如果你想要调试已运行在远程计算机上Docker容器内的Node.js应用程序,并且希望无需修改命令参数(启用调试模式),其实并不需要向全世界开放远程Node.js调试器代理端口来实现。

 

或许你原本不知道这真的可以实现,也不知道该如何实现。不过当你看完本文,就会Get 到一些新奇的知识点,话不多说,往下看吧!

 

TdodoMVC演示应用程序

作者将使用TodoMVC Node.js应用程序的一个Github分支(由Gleb Bahmutov创建)作为本文的演示应用程序,可以随意克隆并使用此代码库:https://github.com/alexei-led/todomvc-express。

 

下面是添加的用于TodoMVC应用程序的Dockerfile,它允许在Docker容器中运行TodoMVC应用程序。

 

FROM alpine:3.5
# install node
RUN apk add --no-cache nodejs-current tini
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Build time argument to set NODE_ENV (‘production’’ bydefault)
ARG NODE_ENV
ENV NODE_ENV ${NODE_ENV:-production}
# install npm packages: clean obsolete files
COPY package.json /usr/src/app/
RUN npm config set depth 0 && \
    npm install && \
    npm cache clean && \
    rm -rf /tmp/*
# copy source files
COPY . /usr/src/app
EXPOSE 3000
# Set tini as entrypoint
ENTRYPOINT [“/sbin/tini”, “--“]
CMD [ “npm”, “start” ]
# add VCS labels for code sync and nice reports
ARG VCS_REF=”local”
LABEL org.label-schema.vcs-ref=$VCS_REF \
     org.label-schema.vcs-url="https://github.com/alexei-led/todomvc-express.git"

在Docker容器中构建和运行TodoMVC

要为TodoMVC应用程序构建新的Docker映像,请运行docker build命令。

 

$ # build Docker image; set VCS_REF tocurrent HEAD commit (short)
$ docker build -t local/todomvc --build-argVCS_REF=`git rev-parse ---short HEAD` .
$ # run TodoMVC in a Docker container
$ docker run -d -p 3000:3000 --name todomvclocal/todomvc node src/start.js

 

计划

最终目标:作者希望能够将Node.js调试器添加到AWS云中的远程主机上Docker容器中已经启动并运行的Node.js应用程序上,而无需修改应用程序、容器、容器配置或使用其他调试标志重新启动它。

想象一下,该应用程序正在运行,但是现在发生了一些问题。作者想使用调试器连接到该应用程序并开始查看问题。

 

因此,作者需要一个计划一个逐步的流程,这将有助于实现最终目标。下面让我们来探索操作流程。

 

在服务器(AWS EC2 VM)机器上,有一个运行在Docker容器中的Node.js应用程序。在客户端(笔记本电脑)上,使用一个IDE(Visual Studio Code),Node.js应用程序代码(git pull /clone)和一个Node.js调试器。下面是计划清单:

  • 将已经运行的应用程序设置为调试模式

  • 公开一个新的Node.js调试器代理端口,以安全的方式启用远程调试

  • 同步客户端-服务器代码:两者都应在git树中的相同的提交上

  • 将本地Node.js调试器添加到远程服务器上的Node.js调试器代理端口,并以安全的方式进行

  • 如果一切正常,应该能够执行常规的调试任务,例如设置断点、检查变量和暂停执行等。

步骤1:将已经运行的Node.js应用程序设置为调试模式

通过使用debug命令行标志启动Node或使用SIGUSR1通知现有的Node进程,可以启用和访问V8调试器。(Node API文档)

 

因此,为了打开Node调试器代理,只需要将SIGUSR1信号发送到TodoMVC应用程序的Node.js进程。注意它运行在Docker容器中。我们可以使用什么命令将过程信号发送到在Docker容器中运行的应用程序呢?

 

作者选择docker killcommand,该命令实际上并没有杀死在Docker容器中运行的PID 1进程,而是向其发送Unix信号(默认情况下,它会发送SIGKILL)。

 

1)将TodoMVC设置为调试模式

下面要做的就是将SIGUSR1发送到在todomvcDocker容器中运行的TodoMVC应用程序。有两种方法可以做到这一点:

  • 使用docker kill --signal命令将SIGUSR1发送到在Docker容器中运行的PID 1进程,如果它是正确的(正确完成信号转发)初始化应用程序(如tini),那么它将起作用;

  • 或者在已经运行的Docker容器中执行kill -s SIGUSR1,将SIGUSR1信号发送到主Node.js进程。

 

$ # send SIGUSR1 with docker kill (if usingproper init process)
$ docker kill --signal SIGUSR1 todomvc
$ # OR run kill command for node processinside todomvc container
$ docker exec -it todomvc sh -c ‘kill -sSIGUSR1 $(pidof -s node)’

让我们确认Node应用程序已设置为调试模式。

 

$ docker logs todomvcTodoMVC server listening athttp://:::3000


emitting 2 todos server has new 2 todos


GET / 200 31.439 ms — 3241


GET /app.css 304 4.907 ms


— —


Starting debugger agent.


Debugger listening on 127.0.0.1:5858

 

如上所示,Node.js调试器代理已启动,但它只能接受来自本地主机的连接,请参见最后输出行:Debugger listening 127.0.0.1:5858

 

步骤2:公开节点调试端口

为了将远程Node.js调试器添加到以调试模式运行的Node应用程序中,需要以下操作:

  • 允许从任何(或特定)IP(或IP范围)连接到调试器代理

  • 公开Docker容器外部的Node.js调试器代理的端口

 

当应用程序已经在Docker容器中运行并且Node.js调试器代理准备与运行在同一台机器上的Node.js调试器进行通信而无法从Node.js调试器代理端口访问时,该如何在Docker容器之外访问呢?

 

可以使用暴露的调试器端口启动每个Node.js Docker容器并允许来自任何IP的连接(使用特殊的--debug-port和--debug Node.js标志),但是我们并不是在寻找很简单的方法。

 

从安全的角度来看,这不是一个好主意(允许不受保护地访问Node.js调试器)。另外,如果我们使用调试标志重新启动一个已经在运行的应用程序,那么我们将失去当前的执行上下文,并且可能无法重现要调试的问题。那么我们需要一个更好的解决方案。

 

很不幸,Docker不允许为已经运行的Docker容器公开其他端口。因此,我们需要以某种方式连接到正在运行的容器网络,并为Node.js调试器代理公开一个新端口。

 

同样,当Node.js进程已经启动时,也无法告诉Node.js调试器代理接受来自不同IP地址的连接。

 

借助名为socat(SOcketCAT)的小型Linux实用程序,可以解决上述两个问题。就像netcat一样,但考虑到安全性(例如它支持chrooting),并且可以在各种协议并通过文件、管道、设备、TCP套接字、Unix套接字、OCKS4的客户端、代理CONNECT或SSL等工作。

 

socat手册页上描述如下:

socat是基于命令行的实用程序,可建立两个双向字节流并在它们之间传输数据。因为可以从大量不同类型的数据接收器和源(请参阅地址类型)中构造流,并且由于可以将大量地址选项应用于流,所以socat可以用于许多不同的目的。

 

这个socat正是我需要的。因此,计划如下:我将在板载socat实用程序的情况下运行一个新的Docker容器,并为TodoMVC容器配置Node.js调试器端口映射。

 

socat.Dockerfile如下:

 

FROM alpine:3.5
RUN apk add --no-cache socat
CMD socat -h

1)构建socat Docker容器

 

$ docker build -t local/socat — <socat.Dockerfile

2)允许从任何IP连接到Node debugger代理

需要在与todomvc容器相同的网络名称空间中运行“ sidecar” socat容器,并定义端口映射。

 

$ # define local port forwarding
$ docker run -d --name socat-nip--network=container:todomvc \
local/socat socat TCP-LISTEN:4848,forkTCP:127.0.0.1:5858

现在,到达4848端口的所有流量都将被路由到监听127.0.0.1:5858的Node.js调试器代理。  4848端口可以接受来自任何IP的流量。还可以使用IP范围来限制到socat侦听端口的连接,添加range = <ANY IP RANGE>选项。

 

3)公开Docker容器的Node.js调试器端口

 

在大多数情况下,我们都想调试在远程计算机(例如,AWS EC2实例)上运行的应用程序。我们也不想将不受保护的Node.js调试器代理端口公开给全世界。一种可行且可行的解决方案是使用SSH隧道访问此端口。

 

$ # Open SSH Tunnel to gain access to serversport 5858.
$ # Set `SSH_KEY_FILE` to ssh key location oradd it to ssh-agent
$ #
$ # open an ssh tunnel, send it to the bg, andwait 20 seconds
$ # for connections, once all connections areclosed
$ # after 20 seconds then close the tunnel
$ ssh -i ${SSH_KEY_FILE} -f -oExitOnForwardFailure=yes \
-L 5858:127.0.0.1:5858ec2_user@some.ec2.host.com sleep 20

 

现在,所有到localhost:5858的流量都将通过SSH隧道传输到远程Docker主机,并经过一些socat转发到运行在todomvc容器中的Node.js调试器代理上。

步骤3:同步相同的代码提交

 

为了能够调试远程应用程序,你需要确保在IDE中使用的代码与在远程服务器上运行的代码相同。作者也将尝试使这一步骤自动化,还记得在TodoMVC Dockerfile中使用过的LABEL命令吗?这些标签可帮助我们识别git存储库并提交应用程序Docker映像:

  • org.label-schema.vcs-ref——包含用于HEAD提交的短SHA

  • org.label-schema.vcs-url——包含一个应用程序git存储库URL(可在git clone/pull中使用)

作者使用的是(标签架构约定)[http://label-schema.org/rc1/],因为它很有用,你也可以选择其他任何约定。

这种方法可以为每个正确标记的Docker映像标识应用程序代码存储库以及创建该存储库的提交。

$ # get git repository url form Docker image
$ GIT_URL=$(docker inspect local/todomvc
| jq -r‘.[].ContainerConfig.Labels.”org.label-schema.vcs-url”’)
$ # get git commit from Docker image
$ GIT_COMMIT=$(docker inspect local/todomvc
| jq -r ‘.[].ContainerConfig.Labels.”org.label-schema.vcs-ref”’)
$
$ # clone git repository, if needed
$ git clone $GIT_URL
$ # set HEAD to same commit as server
$ git checkout $GIT_COMMIT

现在,本地开发环境和远程应用程序都在同一个git commit上了,我们可以开始调试代码了。

 

步骤4:将本地Node.js调试器添加到调试器代理端口

 

需要配置IDE才能开始调试,作者使用的是Visual Studio Code,这里需要添加一个新的Launch配置。

 

此启动配置指定远程调试器服务器和要添加的端口以及应用程序源文件的远程位置,这些位置应与本地文件同步(请参见上一步)。

 

{ // For more information about Node.js debugattributes, visit: https://go.microsoft.com/fwlink/?linkid=830387
“version”: “0.2.0”,
“configurations”: [ {
“type”: “node”,
“request”: “attach”,
“name”: “Debug Remote Docker”,
“address”: “127.0.0.1”,
“port”: 5858, “localRoot”:
“${workspaceRoot}/”,
“remoteRoot”: “/usr/src/app/” }
] }

 

总结

通过以上步骤可以实现计划的目标:可以将Node.js调试器添加到已经在远程计算机上的Docker容器中运行的Node.js应用程序。找到合适的解决方案需要很长时间,但是在找到合适的解决方案之后,该过程看起来并不复杂。

 

弄清楚之后,一旦在环境中遇到新问题,就可以轻松地将Node.js调试器添加到正在运行的应用程序,并开始研究该问题,这样非常方便。

 

作者录制了一部短片,只是为了证明所演示的步骤与本文中所描述的所有步骤一样都很顺利。

                            

希望这篇文章对你有用,欢迎评论区和我们讨论!

 

在中国企业与「远程办公」正面相遇满月之际,2月29日,CSDN 联合广大「远程办公」工具服务企业共同举办【抗击疫情,科技公司在行动】系列之【远程办公】专题线上峰会活动:中国「远程办公」大考。

扫下方二维码或点击阅读原文免费报名直播+抽取奖品+与大牛交流。想提前了解峰会详情,可加小助手微信csdnai,回复远程办公,进直播群。

推荐阅读:从Kubernetes安全地访问AWS服务,告诉你多云场景下如何管理云凭据!
解析云原生与云计算本质区别,别再傻傻分不清楚了!
Go 大败!Google 宣布 Fuchsia 终端开发只支持 C/C++/Dart
干货!从0到1教你打造一个令人上瘾的聊天机器人?
游戏之道
真实版“删库跑路”?程序员蓄意破坏线上生产环境!
真香,朕在看了!点击“阅读原文”,参与报名
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽量详细地介绍DockerNode.js应用程序的全过程操作,包括环境搭建、镜像创建以及容器运行等。请您按照以下步骤进行操作。 1. 环境搭建 首先,您需要在您的Linux系统上安装Docker。可以通过以下命令来安装: ``` sudo apt-get update sudo apt-get install docker.io ``` 安装完成后,可以通过以下命令来检查Docker的版本: ``` docker --version ``` 接下来,您需要在Linux系统上安装Node.js。可以通过以下命令来安装: ``` sudo apt-get install nodejs sudo apt-get install npm ``` 安装完成后,可以通过以下命令来检查Node.js的版本: ``` node -v ``` 2. 创建应用程序的镜像 接下来,您需要创建一个Dockerfile来构建您的应用程序的镜像。在您的项目根目录下创建一个名为Dockerfile的文件,并将以下代码复制粘贴到该文件: ``` FROM node:12 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD [ "npm", "start" ] ``` 以上Dockerfile文件内容的含义是: - 从Docker Hub上拉取Node.js的12版本作为基础镜像 - 在/app目录下创建一个工作目录 - 复制package.json和package-lock.json到工作目录下 - 运行npm install安装项目依赖 - 复制项目所有文件到工作目录下 - 暴露3000端口 - 运行npm start命令启动应用程序 接下来,通过以下命令来构建应用程序的镜像: ``` sudo docker build -t <image-name> . ``` 其,<image-name>是您想要给镜像取的名字,可以自定义。运行以上命令后,Docker会根据Dockerfile文件的配置来构建应用程序的镜像。 3. 基于应用程序的镜像运行容器 镜像构建完成后,您可以使用以下命令来基于该镜像运行容器: ``` sudo docker run -p 3000:3000 -d <image-name> ``` 其,-p参数用于将Docker容器内部的3000端口映射到主机的3000端口,-d参数用于在后台运行容器,<image-name>是您在构建镜像时指定的镜像名字。 运行以上命令后,您的应用程序就会在Docker容器运行,并且可以通过浏览器访问http://localhost:3000来访问您的应用程序。 以上就是完整的DockerNode.js应用程序的全过程操作,希望可以对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值