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

更新日期: 2022-08-27阅读: 638标签: 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


如何通过 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

npm私有仓库 配置verdaccio在docker环境

前端开发过程中,少不了自己封装一些通用的包,但又不想放在公共的平台,所以搭建一个npm私有的仓库是很有必要的。在这里简单介绍如何使用 verdoccio 在docker环境下的配置。verdoccio,轻量级私有npm代理注册表。

ASP.NET Core 如何在运行Docker容器时指定容器外部端口(docker compose)

所以我们可以通过修改docker compose的配置文件来完成我们的需求。熟悉Docker的都应该知道容器运行时其内部会有一个端口以映射到我们外部的端口,我们需要固定的就是这个外部端口。

DOCKER上运行DOTNET CORE

下载microsoft/dotnet镜像、创建.NET Core MVC项目、上面dotnet restore这一步可能会卡很久遇到超时的状况,因为Nuget在国外的原因,博客园有提供加速镜像,参照设定好之后,速度会快很多

Docker---大型项目容器化改造

虚拟化和容器化是项目云化不可避免的两个问题。虚拟化由于是纯平台操作,一个运行于linux操作系统的项目几乎不需要做任何改造就可以支持虚拟化。而项目如果要支持容器化则需要做许多细致的改造工作。

开发人员爱Docker的10个理由

Stack Overflow开发人员调查中,开发人员将Docker评为:最受欢迎的平台,最喜欢的平台,最常用的平台。来自世界各地的近90,000名开发人员对调查做出了回应。

Docker部署网站之后映射域名

Docker中部署tomcat相信大家也都知道,不知道的可以google 或者bing 一下。这里主要是为了记录在我们启动容器之后,tomcat需要直接定位到网站信息,而不是打开域名之后,还得加个blog后缀才能访问到我们的网站首页。

微服务架构之「 容器技术 」

现在一聊到容器技术,大家就默认是指 Docker 了。但事实上,在 Docker 出现之前,PaaS社区早就有容器技术了,以 Cloud Foundry、OpenShift 为代表的就是当时的主流。那为啥最终还是 Docker 火起来了呢?

Docker部署ngnix静态网站

首先获取ngnix镜像(默认的是最新版),先来编写一个最简单的Dockerfile,一个Dockerfile修改该Nginx镜像的首页.Dockerfile是一个文本文件,其中包含了若干条指令

如何从单独的容器调试运行中的Docker容器?

容器非常适合封装软件,但是有时一味地改造容器镜像以使其尽可能小时,您可能走得太远。我们需要在“简洁”的镜像和无法调试的镜像之间找到很好的平衡。看到人们调试正在运行的容器的正常方法

内部集群的 DNS server 搭建

当我们使用 traefik 反向代理和自动服务发现后,我们对集群内部的服务分为两类:公有服务。如我的博客,网站,以及为它们提供服务的 API。我们可以通过公有的域名去映射服务使得外网能够访问

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!