您现在的位置是:亿华云 > 人工智能

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

亿华云2025-10-02 18:30:50【人工智能】7人已围观

简介​最近因为工作,需要通过 Node.js 对 Docker 进行一系列操作如,创建删除容器以及下发指令获取结果等。找了一圈网上大部分资源都是如何容器化 Node.js App 而非通过 Node.js

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

Docker 及容器技术简单介绍

容器化出现的操作目的是以一种更加轻量、标准、不使快速的器化方式对软件代码进行打包以及分发。相比于传统 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 并不支持。

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

让 Docker 服务监听 Tcp 端口。亿华云计算使用 Node.js 原生的 http 模组或者其他 npm 包,如 got使用 Dockerode,第三方 Docker sdk on Node.js

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

普通 cli 指令

使用 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

总结

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

很赞哦!(595)