有没有一种方法可以在执行过程中以编程方式访问容器(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实现上述目标的方法
答案 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文件夹中的任何更改都将反映在主机的文件夹中-因此您可以访问它们。
更新2: 您可以通过以下方式使用Docker REST API在docker容器内执行命令:
启用对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-reload
和service docker restart
。现在您应该可以访问http://127.0.0.1:2375
上的API了-您应该获得{ "message": "page not found" }
作为响应。
使用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}"}
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将其调用到客户端,该程序就很好用。