Make the docker proxy work

This commit is contained in:
Johannes Zellner
2018-08-13 22:14:56 +02:00
parent 3cf3c36e86
commit 4da91ec90d
2 changed files with 78 additions and 8 deletions
+36 -8
View File
@@ -6,48 +6,76 @@ exports = module.exports = {
};
var assert = require('assert'),
bodyParser = require('body-parser'),
config = require('./config.js'),
debug = require('debug')('box:dockerproxy'),
http = require('http');
http = require('http'),
net = require('net');
var gServer = null;
function start(callback) {
assert.strictEqual(typeof callback, 'function');
var parser = bodyParser.json();
function interceptor(req, res) {
debug(`request: ${req.method} ${req.url}`);
console.log(`request: ${req.method} ${req.url}`, req.body);
if (req.method === 'POST' && req.url.match(/\/containers\/create/)) {
debug('patching container creation');
}
return false;
}
debug(`startDockerProxy: starting proxy on port ${config.get('dockerProxyPort')}`);
gServer = http.createServer(function (req, res) {
if (interceptor(req, res)) return;
// rejectUnauthorized should not be required but it doesn't work without it
var options = {
socketPath: '/var/run/docker.sock',
method: req.method,
path: req.url,
headers: req.headers,
rejectUnauthorized: false
headers: req.headers
};
var dockerRequest = http.request(options, function (dockerResponse) {
res.writeHead(dockerResponse.statusCode, dockerResponse.headers);
dockerResponse.on('error', console.error);
// Force node to send out the headers, this is required for the /container/wait api to make the docker cli proceed
res.write(' ');
dockerResponse.on('error', function (error) { console.error('dockerResponse error:', error); });
dockerResponse.pipe(res, { end: true });
});
req.on('error', console.error);
req.on('error', function (error) { console.error('req error:', error); });
if (!req.readable) {
dockerRequest.end();
} else {
req.pipe(dockerRequest, { end: true });
}
}).listen(config.get('dockerProxyPort'), callback);
gServer.on('upgrade', function (req, client, head) {
// Create a new tcp connection to the TCP server
var remote = net.connect('/var/run/docker.sock', function () {
// two-way pipes between client and docker daemon
client.pipe(remote).pipe(client);
// resend the upgrade event to the docker daemon, so it responds with the proper message through the pipes
remote.write(req.method + ' ' + req.url + ' HTTP/1.1\r\n' +
`Host: ${req.headers.host}\r\n` +
'Connection: Upgrade\r\n' +
'Upgrade: tcp\r\n' +
'\r\n'
);
});
});
}
function stop(callback) {
+42
View File
@@ -0,0 +1,42 @@
/* jslint node:true */
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict';
var dockerProxy = require('../dockerproxy.js'),
config = require('../config.js'),
exec = require('child_process').exec,
expect = require('expect.js');
const DOCKER = `docker -H tcp://localhost:${config.get('dockerProxyPort')} `;
describe('Cloudron', function () {
this.timeout(1000000);
before(dockerProxy.start);
after(dockerProxy.stop);
it('can get info', function (done) {
exec(DOCKER + ' info', function (error, stdout, stderr) {
expect(error).to.be(null);
expect(stdout).to.contain('Containers:');
expect(stderr).to.be.empty();
done();
});
});
it('can create container', function (done) {
var cmd = DOCKER + ` run ubuntu "/bin/bash" "-c" "echo 'hello'"`;
console.log(cmd)
exec(cmd, function (error, stdout, stderr) {
console.log(error, stdout, stderr)
expect(error).to.be(null);
expect(stdout).to.contain('hello');
expect(stderr).to.be.empty();
done();
});
});
});