Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用 Node.js 操作 Docker,不是使用 Dcoker 容器化 Node.js 服务哦!

使用 Node.js 操作 Docker,不是使用 Dcoker 容器化 Node.js 服务哦!

作者头像
coder_koala
发布于 2022-11-28 01:51:21
发布于 2022-11-28 01:51:21
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

最近因为工作,需要通过 Node.js 对 Docker 进行一系列操作如,创建删除容器以及下发指令获取结果等。找了一圈网上大部分资源都是如何容器化 Node.js App 而非通过 Node.js 操作 Docker,Docker 官方也并未提供针对 Node.js 的 sdk,所以这篇文章就简单带大家了解一下如何通过 Node.js 相对高效的向 Docker daemon 直接下发指令。

Docker 及容器技术简单介绍

  • 因为本公众号之前已经介绍过 Docker 的基本用法,所以在这里只做简单回顾。有需要的读者可以去翻一下之前的文章或者直接上官网查看。https://docs.docker.com/reference/
  • 容器化出现的目的是以一种更加轻量、标准、快速的方式对软件代码进行打包以及分发。相比于传统 VM,容器化技术使用更少的系统资源占用率且拥有更快的应用启动速度。
  • Docker Engine 类似 Client-sever 模式。用户通过 Docker CLI 如 run、ps、rm 等将指令下发给 Docker daemon 再由 daemon 去执行对应操作Docker 官方同时也提供了一系列 http 协议的接口也可以对 daemon 直接下发指令。 参考:https://docs.docker.com/engine/api/v1.41/#section/Versioning

注意: Docker daemon 在本机上使用 Unix-socket,常用的 Axios 并不支持。

在这提供几种解决方式有兴趣的同学可以动手操作看看:

  1. 让 Docker 服务监听 Tcp 端口。 参考: https://blog.k4nz.com/adb7b5a9eeef48def89317ea9b808f7d/
  2. 使用 Node.js 原生的 http 模组或者其他 npm 包,如 got
  3. 使用 Dockerode,第三方 Docker sdk on Node.js

如何通过 Node.js 向 Docker daemon 下发指令

普通 cli 指令

使用 child_process 模组中的 exec、spawn 函数,通过子进程执行 Docker 提供的 cli 指令。

如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const { exec } = require('child_process')
// list containers info
exec('docker ps -a', (err, stdout, stderr) => {
  if (err) {
    console.error(`exec error: ${err}`);
    return;
  }
console.log(`stdout: ${stdout}`); // print all existing containers
  console.error(`stderr: ${stderr}`);
});
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const { spawn } = require('child_process')
const { Readable} = require('stream')
// 使用terminal传入指令
const container = spawn('docker', ['run', '-it', 'bash']);
process.stdin.pipe(container.stdin); // connect parent stdin to child stdin

// -it flag: i是开启容器stdin,t是attach一个pseudo-tty,具体参考docker官方reference

// 通过stream的的方式传入指令
// const container = spawn('docker', ['run', '-i', 'bash']);
// const buffer = new Readable();
// buffer.pipe(container.stdin);
// buffer.push('ls');
// buffer.push(null);
container.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
container.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
container.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});

通过上面两种方式可以实现向 Docker daemon 下发指令,但是对于每次操作都需要创建并维护一个新的子进程,因此开销会很大,而且也不是 Node.js 的优势所在,因此接下来会结合第三方 docker-node sdk Dockerode 和 Docker http Api,通过 http 请求的方式实现上面的目标。

Dockerode = Docker + Node.js (https://www.npmjs.com/package/dockerode)

Dockerode 是基于 Docker-modem 在已经解决了所有网络问题(端口、协议)的基础上将 Docker Api 封装而成的 sdk。 Dockerode 中所有函数都提供了两种写法,callback 和 promise 的写法。官网提供的大多是 callback 的写法,在这里我们主要会使用 promise 结合 async/await 的写法。下面将简单介绍基本使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const Docker = require('dockerode')const docker = new Docker();

async function wrapper() {
const opts = {
Image: 'bash',
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
Tty: true, // tty is set false if not using process stdin
    OpenStdin: true,
StdinOnce: true,
// AutoRemove: true,
  };

const container_opts = {
stream: true,
stdin: true,
stdout: true,
stderr: true,
// hijack: true, !! must be set true here if not using process stdin
  };

const container = await docker.createContainer(opts);
const stream = await container.attach(container_opts);

// 通过terminal传入指令
  process.stdin.pipe(stream);
  stream.pipe(process.stdout);

// 通过buffer传入指令
// const d = new Duplex();
// d._write = () => {}; // avoid trivial error
// d.pipe(stream);
// stream.pipe(d);
// stream.on('data', (data) => {
//   // do some work on result here
// });
// d.push('ls');
// d.push(null);

  container.start();
}

wrapper();

以上介绍两种使用 Dockerode 替代 cli 命令的写法。

请注意作为区别于 cli 方式,使用 stream 将指令传入的方式,务必将 tty 设定成 false,在 container_opts 中添加 hijack:true

参考:https://github.com/apocas/dockerode/issues/455#issuecomment-489436370

总结

Dockerode 使用 Node.js 最擅长的方式通过 http 请求对 Docker daemon 下发指令,干净且高效。调用Dockerode 中函数的参数配置同 Docker 的官方文案。只是网上关于 Dockerode 文章不多,且使用时,有些配置有坑需要注意。

以上

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员成长指北 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Node.js 多进程(上)
我们都知道 Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能。
陈不成i
2021/07/13
7070
[译]关于Node.js streams你需要知道的一切
Node.js的stream模块是有名的应用困难,更别说理解了。那现在可以告诉你,这些都不是问题了。
frontoldman
2019/09/02
1.1K0
[译]关于Node.js streams你需要知道的一切
深入了解 Node 的多进程服务
我们现在已经知道了Node是单线程运行的,这表示潜在的错误有可能导致线程崩溃,然后进程也会随着退出,无法做到企业追求的稳定性;另一方面,单进程也无法充分多核CPU,这是对硬件本身的浪费。Node社区本身也意识到了这一问题,于是从0.1版本就提供了child_process模块,用来提供多进程的支持。
用户8921923
2022/10/24
7910
Node.js 多进程(下)
child_process.spawn 使用指定的命令行参数创建新进程,语法格式如下:
陈不成i
2021/07/13
5100
[译] 你所需要知道的关于 Node.js Streams 的一切
https://medium.freecodecamp.org/node-js-streams-everything-you-need-to-know-c9141306be93
五月君
2020/02/11
7900
[译] 你所需要知道的关于 Node.js Streams 的一切
Nodejs进程间通信
一.场景 Node运行在单线程下,但这并不意味着无法利用多核/多机下多进程的优势 事实上,Node最初从设计上就考虑了分布式网络场景: Node is a single-threaded, single-process system which enforces shared-nothing design with OS process boundaries. It has rather good libraries for networking. I believe this to be a basis
ayqy贾杰
2019/06/12
3.2K0
【英文】Node.js Streams: Everything you need to know //转载
Node.js streams have a reputation for being hard to work with, and even harder to understand. Well I’ve got good news for you — that’s no longer the case.
Jean
2019/12/06
8740
【英文】Node.js Streams: Everything you need to know //转载
node.js 中的进程和线程工作原理
进程是对正在运行中的程序的一个抽象,是系统进行资源分配和调度的基本单位,操作系统的其他所有内容都是围绕着进程展开的
ACK
2024/09/18
1160
node.js 中的进程和线程工作原理
一篇文章构建你的 Node.js 知识体系
最近读《重学前端》,开篇就是让你拥有自己的知识体系图谱,后续学的东西补充到相应的模块,既可以加深对原有知识的理解,又可以强化记忆,很不错的学习方案。
五月君
2020/08/28
1.9K0
一篇文章构建你的 Node.js 知识体系
Vue + Node.js 从 0 到 1 实现自动化部署工具
最近写了一个自动化部署的 npm 包 zuo-deploy[1],只需点击一个按钮,就可以执行服务器部署脚本,完成功能更新迭代。客户端使用 Vue + ElementUI,服务 koa + socket + koa-session 等。基础功能代码 300 行不到,已开源在 github。zuoxiaobai/zuo-deploy 欢迎 Star、Fork。这里介绍下具体实现细节、思路。
@超人
2022/04/14
1.7K0
Vue + Node.js 从 0 到 1 实现自动化部署工具
Node.js 进阶 - 多文件 Stream 合并,串行和并发两种模式实现
将多个文件合并为一个文件,常见的场景是类似于大文件分片上传,事先根据一定的文件大小拆分为多个小文件上传到服务端,最后服务端在合并起来。
五月君
2022/05/19
2.3K1
Node.js进阶之进程与线程
进程与线程在服务端研发中是一个非常重要的概念,如果您在学习的时候对这一块感到混乱或者不是太理解,可以阅读下本篇内容,本篇在介绍进程和线程的概念之外,列举了很多 Demo 希望能从实战角度帮助您更好的去理解。
五月君
2019/07/12
1.2K0
Node.js进阶之进程与线程
系列3|走进Node.js之多进程模型
文:正龙(沪江网校Web前端工程师) 本文原创,转载请注明作者及出处 之前的文章“走进Node.js之HTTP实现分析”中,大家已经了解 Node.js 是如何处理 HTTP 请求的,在整个处理过程,它仅仅用到单进程模型。那么如何让 Web 应用扩展到多进程模型,以便充分利用CPU资源呢?答案就是 Cluster。本篇文章将带着大家一起分析Node.js的多进程模型。 首先,来一段经典的 Node.js 主从服务模型代码: const cluster = require('cluster'); cons
iKcamp
2018/03/30
1.4K0
系列3|走进Node.js之多进程模型
node中创建服务进程
背景 在node工程部署中,常常涉及到三方:本地客户端、跳板机和服务器(集群)。在通过git触发gitlab hook脚本后,需要在跳板机中执行相应的ssh命令执行shell文件启动node服务器,这需要使用一个常用的命令setsid,这样当ssh命令执行完毕shell退出后,node服务器仍正常运行,此时node服务进程就是一个最典型的daemon进程(后台服务进程)。 那么,在node项目中,如何创建一个daemon进程呢?最简单的方式,其实就是采用类似上文中介绍的方式: require('child_
欲休
2018/03/15
1.7K0
Node.js 中 child_procss 模块
Node.js 的单线程模型给了它无数的赞美,也带给它无数的诟病。单线程模型,让开发者远离了线程调度的复杂性,使用事件驱动也能开发出一个高并发的服务器;同样也是因为单线程,让CPU密集型计算应用完全不适用。
李振
2021/11/26
7290
简单分析下 Node.js 关于集群的那些事
nodejs 原有版本中没有实现多线程,为了充分利用多核 cpu,可以使用子进程实现内核的负载均衡。
coder_koala
2020/11/19
6590
Node.js多进程
使用子进程的执行命令,缓存子进程的输出。并将子进程的输出以回调函数参数的形式进行返回
mySoul
2018/07/30
6580
理解NodeJS多进程
一次面试中,我提到自己用过pm2,面试接着问:「那你知道pm2父子进程通信方式吗」。我大概听说pm2有cluster模式,但不清楚父子进程如何通信。面试结束后把NodeJS的多进程重新整理了一下。
coder2028
2022/10/10
1.2K0
如何让Node服务实现自动重启
Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~ ​当我们在做Node服务端开发的时候通常都会监听一个启动的端口来进行通信,当服务的内容发生改变的时候总是需要重新启动服务来保证服务内容可以被页面或接口正确获取,当重启的次数变的多了以后往往就会考虑到自动重启来解决这种重复的劳动,如:nodemon。那么我们就来探索一下要实现一个类似nodemon的功能。 前提概要: 1. 涉及知识点: fs.watch,fs.watchFile,chokidar;
前端小鑫同学
2022/12/26
1.5K0
Node.js 的 EventEmitter 事件处理详解
在本教程中我们学习 Node.js 的原生 EvenEmitter 类。学完后你将了解事件、怎样使用 EvenEmitter 以及如何在程序中利用事件。另外还会学习 EventEmitter 类从其他本地模块扩展的内容,并通过一些例子了解背后的原理。
疯狂的技术宅
2020/11/03
1.7K0
相关推荐
Node.js 多进程(上)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档