作者 | 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://:::3000emitting 2 todos server has new 2 todosGET / 200 31.439 ms — 3241GET /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教你打造一个令人上瘾的聊天机器人?
游戏之道
真实版“删库跑路”?程序员蓄意破坏线上生产环境!
真香,朕在看了!点击“阅读原文”,参与报名

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

  1. 如何调试Node.js应用程序?

    如何调试Node.js服务器应用程序? 现在,我主要使用带有以下打印语句的警报调试 : sys.puts(sys.inspect(someVariable)); 必须有更好的调试方法. 我知道Goog ...

  2. 如何输入已经以新的TTY运行的Docker容器

    本文翻译自:How to enter in a Docker container already running with a new TTY I have a container that is r ...

  3. 一文告诉你,如何在 Kubernetes 的容器引擎中运行 KVM 和 VMware VM!

    作者 | Gilson Melo 译者 | 天道酬勤 责编 | 徐威龙 封图| CSDN下载于视觉中国 随着微服务的出现,人们通常会问:"是否有可能通过Kubernetes上的微服务在基于内 ...

  4. docker容器的标准使用过程_phpStorm中使用xdebug工具调试docker容器中的程序

    最近使用了docker容器来构建项目,这种方式虽然极大的加快了构建的项目速度,但是也会对之前的本地开发带来一些挑战,比如今天讲到的调试程序,大家对于xdebug一定不会陌生,但是如果php-fpm放到 ...

  5. keras训练完以后怎么预测_一文告诉你如何将Keras模型保存到文件中,并再次加载它们来进行预测。...

    Keras是一个用于深度学习的简单而强大的Python库. 鉴于深度学习模式可能需要数小时.数天甚至数周的时间来培训,了解如何保存并将其从磁盘中加载是很重要的. 在本文中,您将发现如何将Keras模型 ...

  6. Idea SpringBoot 基于 Docker容器环境进行远程调试

    远程服务环境要求 对启动的jar服务命令进行修改,改成远程调试模式启动 eg: java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspen ...

  7. AOSP6.0.1 系统中增加新的category类型与app绑定,并在hotseat容器中加载app

    在launcher3(桌面程序)的hotseat中,可以通过修改dw_phone_hotseat.xml在指定位置加载指定app(仅限于已经指定category类型为APP_xxxx的app或者是系统 ...

  8. IRIS 2021 技术文档 First Look 24 技术概要:容器中的 InterSystems 产品

    技术概要:LDAP 和 InterSystems 产品 目录 技术概要: LDAP 和 InterSystems 产品 1 设置 LDAP 身份验证 1 选择 InterSystems IRIS 实例 ...

  9. linux安装无法添加挂载,linux-无法在已挂载/ etc / passwd和/ etc / shadow的docker容器中添加新用户...

    问题示例: docker run -ti -v my_passwd:/etc/passwd -v my_shadow:/etc/shadow --rm centos [root@681a5489f3b ...

  10. 动力节点Docker学习教程,一文带你快速了解docker容器

    什么是Docker? 下面是Docker容器的Logo,大家可以从这个logo也能道出容器的大致概念了. 其实Docker的概念来自于集装箱,集装箱解决的问题就是把所有不规整的货物都用标准化大小的箱子 ...

最新文章

  1. 教你如何保养iphone电池
  2. mysql 查询日志介绍
  3. Oracle分析函数——函数列表
  4. BZOJ 4407 于神之怒加强版
  5. Spring MVC注释
  6. 《Python Cookbook 3rd》笔记(2.8):多行匹配模式
  7. 浅谈Opencl四大模型之Programming Model
  8. linux内核通俗理解,简洁明了!高手带你理解ARM-Linux的启动过程
  9. 整个电脑键盘被锁住了_轻巧便携:罗技Pebble鹅卵石轻薄鼠标+K380蓝牙键盘上手体验...
  10. dota2自定义地图服务器,RPG DOTA2 自定义地图制作指南——构建模型
  11. Android Studio Design界面不显示控件的解决方法
  12. CAJ格式文件怎么转换为PDF格式
  13. 渐进式Express源码学习2-道士下山
  14. js 实现批量下载页面中的图片
  15. 仿猫眼电影在线选座组件
  16. java多线程概念、实现、状态和生命周期、同步、通信
  17. Centos7安装教程2022.2
  18. HTML5期末大作业:音乐网站设计——html5在线音乐新闻发布会网站模板(滚动页) HTML+CSS+JavaScript
  19. 小程序如何把一个页面当作组件来引用,就是既可以当作一个组件也能当一个页面使用
  20. 《红楼梦》金陵十二钗判词及赏析

热门文章

  1. 【福利贴】迅雷会员账号共享,每天更新
  2. 设置 无线网 连接到服务器未响应,设置无线路由器显示服务器未响应
  3. Ubuntu18/Linux 安装 Halcon21.05
  4. android httpclient post 参数,Android HttpClient GET或者POST请求基本使用方法
  5. 联想计算机无法启动怎么办,联想电脑打不开机怎么办
  6. 位图字体的制作与使用
  7. 【linux】linux下修改鼠标指针
  8. 科密考勤机对比和参考价
  9. python抛出异常 后如何接住_如何在try中捕获异常后继续循环。。。例外
  10. 怎样黑网吧的万象系统_5636小编教你如何进入万象网管系统