Есть ли способ программно получить доступ к файлу в контейнере (докере) во время выполнения. Я пытался использовать 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.info(processes))
.catch(error => console.info(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 }
ОБНОВИТЬ: Я сделал что-то подобное на Java с dockerjava, используя https://github.com/docker-java/docker-java/issues/253 и httphijack — https://gist.github.com/missedone/76517e618486db746056
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





Учитывая, что файлы внутри контейнера эфемерны, вы должны быть осторожны, если ваш код каким-то образом зависит от этих файлов.
Лучше всего использовать тома докера для хранения данных. В вашем случае, если вы можете хранить файлы в томе докера, вы можете запустить свой код из другого контейнера и увидеть эти файлы из него. Таким образом, контейнеры будут использовать одно и то же хранилище, которое не является эфемерным и переживет перезапуск контейнера.
Если объемы докеров не ваш случай, то единственная идея, на мой взгляд, — поиграть с Докер REST API и особенно с методом Исполнитель.
Используя этот метод, вы можете выполнять команды Linux в контейнере.
ОБНОВЛЕНИЕ 1: Если ваша программа работает на хост-компьютере и вам нужен доступ к данным, сгенерированным томом докера, вы также можете привязать каталог хост-компьютера к каталогу внутри контейнера докера.
Пример: docker run -v /host/folder:/container/folder <your_image>
Таким образом, любое изменение в папке докера будет отражено в папке на вашем хост-компьютере, чтобы вы могли получить к ним доступ.
ОБНОВЛЕНИЕ 2: Вы можете использовать Docker REST API для выполнения команд внутри контейнера Docker следующим образом:
Включите TCP-доступ к REST API:
Отредактируйте /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. Теперь вы должны получить доступ к API на http://127.0.0.1:2375 — вы должны получить { "message": "page not found" } в качестве ответа.
Создайте объект Exec с помощью REST API, например:
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 (см. версию для сервера, в моем случае это 1.38 — поэтому в URL это будет как v1.38 не забудьте v)containerId — идентификатор вашего контейнера в докере, который можно получить с помощью следующей команды: 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 на предыдущем шаге (ШАГ 2)В ответ вы должны получить обычный текст — вывод вашей команды.
ЗАМЕТКА:Cmd в теле JSON представляет собой массив, поэтому вы можете указать несколько команд.
Разве вы не можете хранить сгенерированные файлы в томе докера?
в основном я запускаю некоторые тесты пользовательского интерфейса селена, используя докер селена. Во время этих тестов файлы загружаются, и я пытаюсь получить к ним доступ после загрузки. Тесты будут выполняться как часть процесса CI на Jenkins.
Пожалуйста, смотрите мой обновленный ответ. Вы можете привязать папку селена в докере к вашему хост-каталогу и получить доступ к файлам в нем. Но, наверное, должно быть какое-то элегантное решение. Я не знаком с селеном.
это было бы хорошим решением, если бы я был единственным, кто использовал контейнер, но это не так. Вместо того, чтобы запускать docker с хост-папкой, к которой может получить доступ каждый, было бы неплохо иметь возможность доступа к контейнеру во время выполнения и копирования файлов в рабочий каталог. Я добился этого с помощью Java, используя dockerjava, но не могу найти никакого решения, используя javascript/node
имел в виду «вместо того, чтобы пытаться найти общую папку хоста», к которой каждый может получить доступ
пожалуйста, посмотрите мое обновление, просто чтобы предоставить больше информации о том, как оно было реализовано в java
@ Ларри, проверь раздел UPDATE 2 моего ответа. Я провел небольшое исследование и добавил инструкции о том, как выполнять команды Linux внутри контейнера докеров с использованием REST API.
Привет @Larry, если этот или любой другой ответ решил ваш вопрос, рассмотрите возможность его принятия, нажав на галочку. Это показывает более широкому сообществу, что вы нашли решение, и повышает репутацию как отвечающего, так и вас самих. Нет никаких обязательств делать это.
Вы можете использовать метод Docker API /getAchive для извлечения файлов из контейнера, а затем распаковать их. Существует реализация 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.info({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-разархивировать, который хорошо работает, когда вы получаете его на стороне клиента через websocket/other.
спасибо за ссылки. Файлы, к которым мне нужен доступ, генерируются во время выполнения, и к ним нужно получить доступ через несколько секунд, т.е. их необходимо скопировать в рабочий каталог, из которого выполняется код, и обрабатываться. Есть ли у вас пример того, как взаимодействовать с контейнером, используя предложенный вами подход. Я не могу найти примеры по ссылке, которую вы предоставили. Спасибо