diff --git a/src/components/Setup.react.js b/src/components/Setup.react.js
index eb44736a5b..741322e174 100644
--- a/src/components/Setup.react.js
+++ b/src/components/Setup.react.js
@@ -3,6 +3,7 @@ import Router from 'react-router';
import Radial from './Radial.react.js';
import RetinaImage from 'react-retina-image';
import Header from './Header.react';
+import Util from '../utils/Util';
import metrics from '../utils/MetricsUtil';
import setupStore from '../stores/SetupStore';
import setupActions from '../actions/SetupActions';
@@ -43,6 +44,13 @@ var Setup = React.createClass({
shell.openExternal('https://www.docker.com/docker-toolbox');
},
+ handleLinuxDockerInstall: function () {
+ metrics.track('Opening Linux Docker installation instructions', {
+ from: 'setup'
+ });
+ shell.openExternal('http://docs.docker.com/linux/started/');
+ },
+
renderContents: function () {
return (
@@ -74,6 +82,25 @@ var Setup = React.createClass({
},
renderError: function () {
+ let deleteVmAndRetry;
+
+ if (Util.isLinux()) {
+ if (!this.state.started) {
+ deleteVmAndRetry = (
+
+ );
+ }
+ } else {
+ if (this.state.started) {
+ deleteVmAndRetry = (
+
+ );
+ } else {
+ deleteVmAndRetry = (
+
+ );
+ }
+ }
return (
@@ -93,7 +120,7 @@ var Setup = React.createClass({
{this.state.error.message || this.state.error}
- {this.state.started ? : }
+ {{deleteVmAndRetry}}
diff --git a/src/utils/DockerMachineUtil.js b/src/utils/DockerMachineUtil.js
index 283b4cee85..fa22e37eab 100644
--- a/src/utils/DockerMachineUtil.js
+++ b/src/utils/DockerMachineUtil.js
@@ -151,6 +151,11 @@ var DockerMachine = {
}
});
});
+ } else if (util.isLinux()) {
+ cmd = cmd || process.env.SHELL;
+ var terminal = util.linuxTerminal();
+ if (terminal)
+ util.exec(terminal.concat([cmd])).then(() => {});
} else {
cmd = cmd || process.env.SHELL;
this.url(machineName).then(machineUrl => {
diff --git a/src/utils/DockerUtil.js b/src/utils/DockerUtil.js
index 7091482feb..1eede0525e 100644
--- a/src/utils/DockerUtil.js
+++ b/src/utils/DockerUtil.js
@@ -3,6 +3,7 @@ import fs from 'fs';
import path from 'path';
import dockerode from 'dockerode';
import _ from 'underscore';
+import child_process from 'child_process';
import util from './Util';
import hubUtil from './HubUtil';
import metrics from '../utils/MetricsUtil';
@@ -20,20 +21,25 @@ export default {
throw new Error('Falsy ip or name passed to docker client setup');
}
- let certDir = path.join(util.home(), '.docker/machine/machines/', name);
- if (!fs.existsSync(certDir)) {
- throw new Error('Certificate directory does not exist');
- }
+ if (util.isLinux()) {
+ this.host = 'localhost';
+ this.client = new dockerode({socketPath: '/var/run/docker.sock'});
+ } else {
+ let certDir = path.join(util.home(), '.docker/machine/machines/', name);
+ if (!fs.existsSync(certDir)) {
+ throw new Error('Certificate directory does not exist');
+ }
- this.host = ip;
- this.client = new dockerode({
- protocol: 'https',
- host: ip,
- port: 2376,
- ca: fs.readFileSync(path.join(certDir, 'ca.pem')),
- cert: fs.readFileSync(path.join(certDir, 'cert.pem')),
- key: fs.readFileSync(path.join(certDir, 'key.pem'))
- });
+ this.host = ip;
+ this.client = new dockerode({
+ protocol: 'https',
+ host: ip,
+ port: 2376,
+ ca: fs.readFileSync(path.join(certDir, 'ca.pem')),
+ cert: fs.readFileSync(path.join(certDir, 'cert.pem')),
+ key: fs.readFileSync(path.join(certDir, 'key.pem'))
+ });
+ }
},
init () {
@@ -66,6 +72,14 @@ export default {
});
},
+ isDockerRunning () {
+ try {
+ child_process.execSync('ps ax | grep "docker daemon" | grep -v grep');
+ } catch (error) {
+ throw new Error('Cannot connect to the Docker daemon. The daemon is not running.');
+ }
+ },
+
startContainer (name, containerData) {
let startopts = {
Binds: containerData.Binds || []
diff --git a/src/utils/SetupUtil.js b/src/utils/SetupUtil.js
index b0cf1ba0d6..cf9b6ac43f 100644
--- a/src/utils/SetupUtil.js
+++ b/src/utils/SetupUtil.js
@@ -2,8 +2,8 @@ import _ from 'underscore';
import fs from 'fs';
import path from 'path';
import Promise from 'bluebird';
-import util from './Util';
import bugsnag from 'bugsnag-js';
+import util from './Util';
import virtualBox from './VirtualBoxUtil';
import setupServerActions from '../actions/SetupServerActions';
import metrics from './MetricsUtil';
@@ -51,7 +51,31 @@ export default {
return _retryPromise.promise;
},
- async setup () {
+ async nativeSetup () {
+ while (true) {
+ try {
+ docker.setup('localhost', machine.name());
+ docker.isDockerRunning();
+
+ break;
+ } catch (error) {
+ router.get().transitionTo('setup');
+ metrics.track('Native Setup Failed');
+ setupServerActions.error({error});
+
+ let message = error.message.split('\n');
+ let lastLine = message.length > 1 ? message[message.length - 2] : 'Docker Machine encountered an error.';
+ bugsnag.notify('Native Setup Failed', lastLine, {
+ 'Docker Machine Logs': error.message
+ }, 'info');
+
+ this.clearTimers();
+ await this.pause();
+ }
+ }
+ },
+
+ async nonNativeSetup () {
let virtualBoxVersion = null;
let machineVersion = null;
while (true) {
diff --git a/src/utils/Util.js b/src/utils/Util.js
index 9950ca6ec1..a0671a57ad 100644
--- a/src/utils/Util.js
+++ b/src/utils/Util.js
@@ -5,6 +5,7 @@ import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
import remote from 'remote';
+var dialog = remote.require('dialog');
var app = remote.require('app');
module.exports = {
@@ -34,6 +35,9 @@ module.exports = {
isWindows: function () {
return process.platform === 'win32';
},
+ isLinux: function () {
+ return process.platform === 'linux';
+ },
binsPath: function () {
return this.isWindows() ? path.join(this.home(), 'Kitematic-bins') : path.join('/usr/local/bin');
},
@@ -156,5 +160,17 @@ module.exports = {
linuxToWindowsPath: function (linuxAbsPath) {
return linuxAbsPath.replace('/c', 'C:').split('/').join('\\');
},
+ linuxTerminal: function () {
+ if (fs.existsSync('/usr/bin/x-terminal-emulator')) {
+ return ['/usr/bin/x-terminal-emulator', '-e'];
+ } else {
+ dialog.showMessageBox({
+ type: 'warning',
+ buttons: ['OK'],
+ message: 'The terminal emulator symbolic link doesn\'t exists. Please read the Wiki at https://github.com/kitematic/kitematic/wiki/Common-Issues-and-Fixes#early-linux-support-from-zedtux.'
+ });
+ return;
+ }
+ },
webPorts: ['80', '8000', '8080', '8888', '3000', '5000', '2368', '9200', '8983']
};
diff --git a/styles/variables.less b/styles/variables.less
index a98c2fe98d..9e873d583d 100644
--- a/styles/variables.less
+++ b/styles/variables.less
@@ -23,8 +23,8 @@
@color-box-button: lighten(@gray-lightest, 5%);
@color-background: lighten(@gray-lightest, 4.5%);
-@font-regular: "Helvetica Neue", Segoe UI, Arial, "Lucida Grande", sans-serif;
-@font-code: Menlo, Consolas;
+@font-regular: "Helvetica Neue", Segoe UI, "Ubuntu", Arial, "Lucida Grande", sans-serif;
+@font-code: Menlo, Consolas, "DejaVu Sans Mono";
@border-radius: 0.2rem;