6

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

 2 years ago
source link: https://www.fly63.com/article/detial/12052
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

更新日期: 2022-08-27阅读: 10标签: Docker分享

扫一扫分享

最近因为工作,需要通过 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 直接下发指令。

    参考:h ttps://docs.docker.com/engine/api/v1.41/#section/Versioning

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

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

  1. 让 Docker 服务监听 Tcp 端口。参考:https://blog.k4nz.com/adb7b5a9eeef48def89317ea9b808f7d/

  2. 使用 Node.js 原生的 http 模组或者其他 npm 包,如 got

  3. 使用 Dockerode,第三方 Docker sdk on Node.js

630c1b4e4f8ac.jpg

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

普通 c li 指令

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

如下所示:

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}`);

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 的写法。下面将简单介绍基本使用:

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

总结

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

- END -

敬请关注「Nodejs技术栈」微信公众号, 期望与志同道合的你一起打造优质 “Nodejs技术栈” 交流群,一起互相学习进步! 可长按下方二维码 添加【五月君】个人微信备注 “Node” 邀请入群。

原文 https://mp.weixin.qq.com/s/odE6Lymh0nDar_URQb1O4Q

链接: https://www.fly63.com/article/detial/12052


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK