使用JavaScript / Node在码头上访问文件

时间:2019-02-06 11:36:02

标签: node.js docker

有没有一种方法可以在执行过程中以编程方式访问容器(docker)上的文件。我尝试使用node-docker-api只是为了在第一个实例中进行设置,并建立连接:

const docker = new Docker({
    "host": "tcp://docker:port"
});

// List
docker.container.list()
// Inspect
    .then(containers => containers[0].status())
    .then(container => container.top())
    .then(processes => console.log(processes))
    .catch(error => console.log(error));

其中“端口”是4位数字的端口号。但我收到此错误消息:

{ Error: connect ECONNREFUSED 127.0.0.1:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1081:14)
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 80 }

更新: 我已经使用https://github.com/docker-java/docker-java/issues/253和httphijack-https://gist.github.com/missedone/76517e618486db746056

在dockerjava中用Java完成了类似的操作
ExecCreateCmdResponse execCreateResp = dck.execCreateCmd(cid).withCmd("bash")
        .withAttachStderr().withAttachStdout().withAttachStdin().withTty(false).exec();

HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");

HttpHijack ws = new HttpHijack(new URI("http://127.0.0.1:2376/v1.19/exec/" + execCreateResp.getId() + "/start"));
String payload = "{\"Detach\": false,\"Tty\": false}";
ws.post(headers, payload);

,然后使用以下命令从容器中复制文件:

try (TarArchiveInputStream tarStream = new TarArchiveInputStream(
    docker.copyArchiveFromContainerCmd(containerId, "/home/seluser/Downloads/" + fileName).exec())) {
    unTar(tarStream, new File(filePath));
    return;
}catch(NotFoundException e){
    e.printStackTrace();
}

但是我似乎找不到使用javascript / node实现上述目标的方法

2 个答案:

答案 0 :(得分:0)

鉴于容器中的文件是临时文件,因此如果您的代码某种程度上依赖于该文件,则应格外小心。

最佳做法是使用docker volumes存储数据。 就您而言,如果您可以将文件存储在Docker卷中,则可以从另一个容器运行代码并从中查看该文件。因此,容器将共享相同的存储,这不是临时的,并且将在容器重启后继续存在。

如果不是您所需要的Docker卷,那么我想到的唯一想法就是使用Docker REST API,尤其是使用Exec方法。

使用此方法,您可以在容器中执行Linux命令。


更新1: 如果您的程序在主机上运行,​​并且您需要访问docker volume生成的数据,则还可以将主机目录绑定到docker容器内的目录。

示例:docker run -v /host/folder:/container/folder <your_image>

这样,docker文件夹中的任何更改都将反映在主机的文件夹中-因此您可以访问它们。

Read more


更新2: 您可以通过以下方式使用Docker REST API在docker容器内执行命令:

  1. 启用对REST API的TCP访问: 编辑/lib/systemd/system/docker.service并更改下一行: ExecStart=/usr/bin/dockerd -g /data/docker -H fd://ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 并保存文件。 然后systemctl daemon-reloadservice docker restart。现在您应该可以访问http://127.0.0.1:2375上的API了-您应该获得{ "message": "page not found" }作为响应。

  2. 使用REST API创建Exec对象,例如:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"AttachStdout": true,"AttachStderr": true,"Cmd": ["date"]}' \
http://127.0.0.1:2375/v{dockerVersion}/containers/{containerId}/exec 

这里:

  • dockerVersion-可以使用docker version命令检索docker引擎的版本(请参阅服务器的版本,在我的情况下为1.38-因此在URL中将类似于v1.38 < strong>不要忘记v
  • containerId-可通过以下命令检索您在docker中的容器ID:curl http://127.0.0.1:2375/v{dockerVersion}/containers/json

作为对/containers/{containerId}/exec的回应,您应该得到类似:{"Id": "{objectId}"}

  1. 执行先前创建的命令:
curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"Detach": false,"Tty": false}' \
http://127.0.0.1:2375/v{dockerVersion}/exec/{objectId}/start

这里:

  • objectId-上一步中从docker API返回的ID(步骤2)

作为响应,您应该获得纯文本-命令的输出。

注意::JSON正文中的Cmd是一个数组,因此您可以指定多个命令。

答案 1 :(得分:0)

您可以使用Docker API / getAchive方法从容器中提取文件,然后将其解压缩 在服务器端dockerode

上使用了docker API的NodeJS实现。
 npm i dockerode

然后将其导入并运行文件所在的容器

var Docker = require('dockerode');
var docker = new Docker({socketPath: '/var/run/docker.sock'}); //or whatever path to your socket
let file="abs/path/in/container/somefile.file"
let tag="docekerImageTag"  //"repo/image" //"johndoe/docker_image"

runContainer(tag,"foo").then(container=>{
  getFile(container,file,ws)
})


function runContainer(containerName,param){
 return docker.run(
    containerName,
    ['Rscript', 'random.rscript','--test',`${param}`,],
    [process.stdout, process.stderr], {Tty:false}, //send only stdout if you don't want the split no tty needed
  ).then(function(data){
      var output=data[0]
      var container=data[1]
      return container
    },rej=>{
      console.log({rej})
      return rej
    }
  )
}
function getFile(container,file,ws){
  container.getArchive({path:file}).then(file=>{
    if(ws) ws.sendMsg(file) //send it somewhere I'm using a websocket. This will give you a stream with the tar file. 
//With the websocket you might have to parse the BufferList and iteratively send the buffers and assemble it on the other end
//fs.write(file,path,"UTF8") is another option. Though I think you still have to iterate the bufferList for "fs" 
  })
}

如果您想立即使用它,请不要忘记解压缩文件。

还有一个客户端JavaScript程序包可解压缩流调用js-untar,一旦您通过websocket / other将其调用到客户端,该程序就很好用。