Add a whole bunch of magic for docker.exec to work
This commit is contained in:
19
src/apps.js
19
src/apps.js
@@ -748,10 +748,14 @@ function exec(appId, options, callback) {
|
|||||||
|
|
||||||
var container = docker.connection.getContainer(app.containerId);
|
var container = docker.connection.getContainer(app.containerId);
|
||||||
|
|
||||||
var execOptions = {
|
var execOptions = {
|
||||||
AttachStdin: true,
|
AttachStdin: true,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
|
// A pseudo tty is a terminal which processes can detect (for example, disable colored output)
|
||||||
|
// Creating a pseudo terminal also assigns a terminal driver which detects control sequences
|
||||||
|
// When passing binary data, tty must be disabled. In addition, the stdout/stderr becomes a single
|
||||||
|
// unified stream because of the nature of a tty (see https://github.com/docker/docker/issues/19696)
|
||||||
Tty: options.tty,
|
Tty: options.tty,
|
||||||
Cmd: cmd
|
Cmd: cmd
|
||||||
};
|
};
|
||||||
@@ -761,9 +765,18 @@ function exec(appId, options, callback) {
|
|||||||
var startOptions = {
|
var startOptions = {
|
||||||
Detach: false,
|
Detach: false,
|
||||||
Tty: options.tty,
|
Tty: options.tty,
|
||||||
stdin: true // this is a dockerode option that enabled openStdin in the modem
|
// hijacking upgrades the docker connection from http to tcp. because of this upgrade,
|
||||||
|
// we can work with half-close connections (not defined in http). this way, the client
|
||||||
|
// can properly signal that stdin is EOF by closing it's side of the socket. In http,
|
||||||
|
// the whole connection will be dropped when stdin get EOF.
|
||||||
|
// https://github.com/apocas/dockerode/commit/b4ae8a03707fad5de893f302e4972c1e758592fe
|
||||||
|
hijack: true,
|
||||||
|
stream: true,
|
||||||
|
stdin: true,
|
||||||
|
stdout: true,
|
||||||
|
stderr: true
|
||||||
};
|
};
|
||||||
exec.start(startOptions, function(error, stream) {
|
exec.start(startOptions, function(error, stream /* in hijacked mode, this is a net.socket */) {
|
||||||
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error));
|
||||||
|
|
||||||
if (options.rows && options.columns) {
|
if (options.rows && options.columns) {
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ function exec(req, res, next) {
|
|||||||
|
|
||||||
var tty = req.query.tty === 'true' ? true : false;
|
var tty = req.query.tty === 'true' ? true : false;
|
||||||
|
|
||||||
apps.exec(req.params.id, { cmd: cmd, rows: rows, columns: columns, tty: tty }, function (error, duplexStream) {
|
apps.exec(req.params.id, { cmd: cmd, rows: rows, columns: columns, tty: tty }, function (error, execStream) {
|
||||||
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
|
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
|
||||||
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
|
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
|
||||||
if (error) return next(new HttpError(500, error));
|
if (error) return next(new HttpError(500, error));
|
||||||
@@ -367,8 +367,14 @@ function exec(req, res, next) {
|
|||||||
req.clearTimeout();
|
req.clearTimeout();
|
||||||
res.sendUpgradeHandshake();
|
res.sendUpgradeHandshake();
|
||||||
|
|
||||||
duplexStream.pipe(res.socket);
|
// allowHalfOpen allows the client to close it's connection (end()) to signal a stdin EOF. If allowHalfOpen
|
||||||
res.socket.pipe(duplexStream);
|
// is not set, our socket will call end() automatically. Setting this to true, leaves our socket open
|
||||||
|
// and allows us to send the result of the command (made possible by docker hijacking feature).
|
||||||
|
res.socket.allowHalfOpen = true;
|
||||||
|
|
||||||
|
// When tty is disabled, the execStream is a duplex stream. When enabled, it has stdout/stderr merged.
|
||||||
|
execStream.pipe(res.socket);
|
||||||
|
res.socket.pipe(execStream);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user