新知识点!一文告诉你如何调试运行在Docker容器中的远程Node.js应用程序
云栖号:https://yqh.aliyun.com
第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策!
你知道吗?
如果你想要调试已运行在远程计算机上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 = 选项。
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调试器添加到正在运行的应用程序,并开始研究该问题,这样非常方便。
作者录制了一部短片,只是为了证明所演示的步骤与本文中所描述的所有步骤一样都很顺利。
希望这篇文章对你有用,欢迎评论区和我们讨论!
云栖号:https://yqh.aliyun.com
第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策!
原文发布时间:2020-02-26
本文作者:Alexei Ledenev
本文来自:“CSDN云计算公众号”,了解相关信息可以关注“CSDN云计算”
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Kubernetes - 4.7 Workload - Job
什么是Job? Job一般用于数据处理、迁移等一次性任务处理场景,Job会创建Pod进行作业并确保完成。 Job作业模式 非并行作业: 作业完成后Pod自动终止。 具有完成次数计数的并行作业:指定所需完成作业的次数,作业完成后Pod自动终止。 具有工作队列的并行作业:指定Pod之间或外部服务的协调确定作业,Pod全部终止后作业完成。 通过Yaml资源定义清单创建Job apiVersion: batch/v1 kind: Job metadata: name: pi spec: template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never backoffLimit: 4 参数 .spec.completions #需要Pod的执行成功次数 .spec.parallelism #Job同时可执行的Pod数量 .spec.backoffLimit #Job的容错次数 .spec.activ...
- 下一篇
搭建浅层神经网络"Hello world"
作为图像识别与机器视觉界的 "hello world!" ,MNIST ("Modified National Institute of Standards and Technology") 数据集有着举足轻重的地位。基本上每本人工智能、机器学习相关的书上都以它作为开始。 下面我们会用 TensorFlow 搭建一个浅层的神经网络来运行 "hello world!" 模型。 以下内容和模块的运算,均在矩池云平台进行。 本次教程分五步: 第一步:数据预处理,包括提取数据标签、查看图片数据、数据可视化、查看数据是否平衡等 第二步:数据加载,打乱数据集 第三步:构建模型,简单介绍网络卷积模型和激活函数,定义训练函数和学习率 第四步:模型训练,查看训练过程和结果,使用图表查看模型精确度和学习率变化 第五步:尝试提升精准度,不断探索和优化 在搭建开始前,我们需要加载以下对应的模块: 第一步:数据预处理 1.1查看数据标签 在任何模型建立之前,应当优先查看数据的情况。例如数据集的大小、训练集和测试集的数据数量、标签的数据数量分布等。下方为训练集和测试集的数据查看代码: train = pd.rea...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群