mirror of https://github.com/portainer/portainer
Merge branch 'dev'
commit
b77fb1ad03
21
README.md
21
README.md
|
@ -5,19 +5,40 @@ DockerUI is a web interface to interact with the Remote API. The goal is to pro
|
|||
|
||||

|
||||
|
||||
|
||||
###Goals
|
||||
* Little to no dependencies - I really want to keep this project a pure html/js app. You can drop the docker binary on your server run so I want to be able to drop these html files on your server and go.
|
||||
|
||||
###Installation
|
||||
Open js/app.js and change the DOCKER_ENDPOINT constant to your docker ip and port. Then host the site like any other html/js application.
|
||||
|
||||
|
||||
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243');
|
||||
|
||||
###Remote API Version
|
||||
DockerUI currently supports the v1.1 Remote API
|
||||
|
||||
###Stack
|
||||
* Angular.js
|
||||
* Flatstrap ( Flat Twitter Bootstrap )
|
||||
|
||||
|
||||
###Todo:
|
||||
I work fast so it will not be long before these changes are impelmented.
|
||||
|
||||
* Multiple endpoints
|
||||
* Full repository support
|
||||
* Search
|
||||
* Create images via Dockerfile
|
||||
* Push files to a container
|
||||
* Unit tests
|
||||
|
||||
|
||||
###License - MIT
|
||||
The DockerUI code is licensed under the MIT license. Flatstrap(bootstrap) is licensed under the Apache License v2.0 and Angular.js is licensed under MIT.
|
||||
|
||||
|
||||
**DockerUI:**
|
||||
Copyright (c) 2013 Michael Crosby. crosbymichael.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
|
|
|
@ -70,6 +70,11 @@
|
|||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.center {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.btn-remove {
|
||||
margin: 0 auto;
|
||||
max-width: 70%;
|
||||
|
@ -78,3 +83,7 @@
|
|||
.actions {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.container-bottom {
|
||||
height: 50px;
|
||||
}
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
|
||||
<div class="container">
|
||||
|
||||
<div ng-include="template" ng-controller="MastheadController" ></div>
|
||||
<div id="view" ng-view>
|
||||
<div ng-include="template" ng-controller="MastheadController" ></div>
|
||||
<div id="view" ng-view>
|
||||
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>Created by:<a href="http://crosbymichael.com">Michael Crosby</a></p>
|
||||
<div class="container-bottom"></div>
|
||||
<div class="footer center well">
|
||||
<p>Created by: <a href="http://crosbymichael.com">crosbymichael</a></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
angular.module('dockerui', ['dockerui.services', 'dockerui.filters'])
|
||||
.config(['$routeProvider', function ($routeProvider) {
|
||||
$routeProvider.when('/', {templateUrl: 'partials/home.html', controller: 'HomeController'});
|
||||
$routeProvider.when('/', {templateUrl: 'partials/dashboard.html', controller: 'DashboardController'});
|
||||
$routeProvider.when('/containers/', {templateUrl: 'partials/containers.html', controller: 'ContainersController'});
|
||||
$routeProvider.when('/containers/:id/', {templateUrl: 'partials/container.html', controller: 'ContainerController'});
|
||||
$routeProvider.when('/images/', {templateUrl: 'partials/images.html', controller: 'ImagesController'});
|
||||
|
@ -10,4 +10,6 @@ angular.module('dockerui', ['dockerui.services', 'dockerui.filters'])
|
|||
$routeProvider.when('/settings', {templateUrl: 'partials/settings.html', controller: 'SettingsController'});
|
||||
$routeProvider.otherwise({redirectTo: '/'});
|
||||
}])
|
||||
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243');
|
||||
// This is your docker url that the api will use to make requests
|
||||
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243')
|
||||
.constant('DOCKER_API_VERSION', '/v1.1');
|
||||
|
|
|
@ -33,42 +33,42 @@ function MastheadController($scope) {
|
|||
};
|
||||
}
|
||||
|
||||
function HomeController() {
|
||||
function DashboardController($scope, Container) {
|
||||
|
||||
}
|
||||
|
||||
function SideBarController($scope, Container, Settings) {
|
||||
$scope.template = 'partials/sidebar.html';
|
||||
$scope.containers = [];
|
||||
$scope.endpoint = Settings.endpoint;
|
||||
|
||||
Container.query({all: 0}, function(d) {
|
||||
$scope.containers = d;
|
||||
});
|
||||
}
|
||||
|
||||
function SettingsController($scope, Auth, System, Docker, Settings) {
|
||||
$scope.auth = {};
|
||||
$scope.info = {};
|
||||
$scope.docker = {};
|
||||
$scope.endpoint = Settings.endpoint;
|
||||
$scope.apiVersion = Settings.version;
|
||||
|
||||
$('#response').hide();
|
||||
$scope.alertClass = 'block';
|
||||
|
||||
var showAndHide = function(hide) {
|
||||
$('#response').show();
|
||||
if (hide) {
|
||||
setTimeout(function() { $('#response').hide();}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.updateAuthInfo = function() {
|
||||
if ($scope.auth.password != $scope.auth.cpassword) {
|
||||
$scope.response = 'Your passwords do not match.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Your passwords do not match.', '#response');
|
||||
return;
|
||||
}
|
||||
Auth.update(
|
||||
{username: $scope.auth.username, email: $scope.auth.email, password: $scope.auth.password}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Auth information updated.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Auto information updated.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -89,52 +89,33 @@ function ContainerController($scope, $routeParams, $location, Container) {
|
|||
$('#response').hide();
|
||||
$scope.alertClass = 'block';
|
||||
|
||||
var showAndHide = function(hide) {
|
||||
$('#response').show();
|
||||
if (hide) {
|
||||
setTimeout(function() { $('#response').hide();}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.start = function(){
|
||||
Container.start({id: $routeParams.id}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Container started.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Container started.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.stop = function() {
|
||||
Container.stop({id: $routeParams.id}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Container stopped.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Container stopped.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.kill = function() {
|
||||
Container.kill({id: $routeParams.id}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Container killed.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Container killed.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -142,14 +123,10 @@ function ContainerController($scope, $routeParams, $location, Container) {
|
|||
if (confirm("Are you sure you want to remove the container?")) {
|
||||
Container.remove({id: $routeParams.id}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Container removed.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Container removed.', '#response');
|
||||
}, function(e){
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -210,26 +187,15 @@ function ImageController($scope, $routeParams, $location, Image) {
|
|||
|
||||
$('#response').hide();
|
||||
$scope.alertClass = 'block';
|
||||
|
||||
var showAndHide = function(hide) {
|
||||
$('#response').show();
|
||||
if (hide) {
|
||||
setTimeout(function() { $('#response').hide();}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.remove = function() {
|
||||
if (confirm("Are you sure you want to delete this image?")) {
|
||||
Image.remove({id: $routeParams.id}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Image removed.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Image removed.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -244,14 +210,10 @@ function ImageController($scope, $routeParams, $location, Image) {
|
|||
var tag = $scope.tag;
|
||||
Image.tag({id: $routeParams.id, repo: tag.repo, force: tag.force ? 1 : 0}, function(d) {
|
||||
console.log(d);
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = 'Tag added.';
|
||||
showAndHide(true);
|
||||
setSuccessfulResponse($scope, 'Tag added.', '#response');
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = e.data;
|
||||
showAndHide(false);
|
||||
setFailedResponse($scope, e.data, '#response');
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -307,3 +269,16 @@ function StartContainerController($scope, $routeParams, $location, Container) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
function setSuccessfulResponse($scope, msg, msgId) {
|
||||
$scope.alertClass = 'success';
|
||||
$scope.response = msg;
|
||||
$(msgId).show();
|
||||
setTimeout(function() { $(msgId).hide();}, 5000);
|
||||
}
|
||||
|
||||
function setFailedResponse($scope, msg, msgId) {
|
||||
$scope.alertClass = 'error';
|
||||
$scope.response = msg;
|
||||
$(msgId).show();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('dockerui.services', ['ngResource'])
|
||||
.factory('Container', function($resource, DOCKER_ENDPOINT) {
|
||||
.factory('Container', function($resource, Settings) {
|
||||
// Resource for interacting with the docker containers
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
|
||||
return $resource(DOCKER_ENDPOINT + '/containers/:id/:action', {}, {
|
||||
return $resource(Settings.url + '/containers/:id/:action', {}, {
|
||||
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
|
||||
get :{method: 'GET', params: { action:'json'}},
|
||||
start: {method: 'POST', params: {id: '@id', action: 'start'}},
|
||||
|
@ -16,10 +16,10 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
remove :{method: 'DELETE', params: {id: '@id', v:0}}
|
||||
});
|
||||
})
|
||||
.factory('Image', function($resource, DOCKER_ENDPOINT) {
|
||||
.factory('Image', function($resource, Settings) {
|
||||
// Resource for docker images
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
|
||||
return $resource(DOCKER_ENDPOINT + '/images/:id/:action', {}, {
|
||||
return $resource(Settings.url + '/images/:id/:action', {}, {
|
||||
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
|
||||
get :{method: 'GET', params: { action:'json'}},
|
||||
search :{method: 'GET', params: { action:'search'}},
|
||||
|
@ -31,30 +31,33 @@ angular.module('dockerui.services', ['ngResource'])
|
|||
delete :{id: '@id', method: 'DELETE'}
|
||||
});
|
||||
})
|
||||
.factory('Docker', function($resource, DOCKER_ENDPOINT) {
|
||||
.factory('Docker', function($resource, Settings) {
|
||||
// Information for docker
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
||||
return $resource(DOCKER_ENDPOINT + '/version', {}, {
|
||||
return $resource(Settings.url + '/version', {}, {
|
||||
get: {method: 'GET'}
|
||||
});
|
||||
})
|
||||
.factory('Auth', function($resource, DOCKER_ENDPOINT) {
|
||||
.factory('Auth', function($resource, Settings) {
|
||||
// Auto Information for docker
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
|
||||
return $resource(DOCKER_ENDPOINT + '/auth', {}, {
|
||||
return $resource(Settings.url + '/auth', {}, {
|
||||
get: {method: 'GET'},
|
||||
update: {method: 'POST'}
|
||||
});
|
||||
})
|
||||
.factory('System', function($resource, DOCKER_ENDPOINT) {
|
||||
.factory('System', function($resource, Settings) {
|
||||
// System for docker
|
||||
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
|
||||
return $resource(DOCKER_ENDPOINT + '/info', {}, {
|
||||
return $resource(Settings.url + '/info', {}, {
|
||||
get: {method: 'GET'}
|
||||
});
|
||||
})
|
||||
.factory('Settings', function() {
|
||||
.factory('Settings', function(DOCKER_ENDPOINT, DOCKER_API_VERSION) {
|
||||
return {
|
||||
displayAll: false
|
||||
displayAll: false,
|
||||
endpoint: DOCKER_ENDPOINT,
|
||||
version: DOCKER_API_VERSION,
|
||||
url: DOCKER_ENDPOINT + DOCKER_API_VERSION
|
||||
};
|
||||
});
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
<div class="row-fluid">
|
||||
<!--<div class="sidebar span4">
|
||||
<div ng-include="template" ng-controller="SideBarController"></div>
|
||||
</div>-->
|
||||
<div class="span12">
|
||||
<div class="jumbotron">
|
||||
<h1>DockerUI</h1>
|
||||
<p class="lead">The Linux container engine</p>
|
||||
<a class="btn btn-large btn-success" href="http://docker.io">Learn more.</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +0,0 @@
|
|||
<div class="jumbotron">
|
||||
<h1>DockerUI</h1>
|
||||
<p class="lead">The Linux container engine</p>
|
||||
<a class="btn btn-large btn-success" href="http://docker.io">Learn more.</a>
|
||||
</div>
|
||||
|
||||
<hr>
|
|
@ -4,7 +4,7 @@
|
|||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<ul class="nav">
|
||||
<li class="{{ hclass }}" ng-click="linkChange('home')"><a href="#">Home</a></li>
|
||||
<li class="{{ hclass }}" ng-click="linkChange('home')"><a href="#">Dashboard</a></li>
|
||||
<li class="{{ cclass }}" ng-click="linkChange('containers')"><a href="/#/containers/">Containers</a></li>
|
||||
<li class="{{ iclass }}" ng-click="linkChange('images')"><a href="/#/images/">Images</a></li>
|
||||
<li class="{{ sclass }}" ng-click="linkChange('settings')"><a href="/#/settings/">Settings</a></li>
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
<h3>Docker Information</h3>
|
||||
<div>
|
||||
<p class="lead">
|
||||
<strong>Version</strong>{{ docker.Version }}<br />
|
||||
<strong>GitCommit</strong>{{ docker.GitCommit }}<br />
|
||||
<strong>GoVersion</strong>{{ docker.GoVersion }}<br />
|
||||
<strong>Endpoint: </strong>{{ endpoint }}<br />
|
||||
<strong>Api Version: </strong>{{ apiVersion }}<br />
|
||||
<strong>Version: </strong>{{ docker.Version }}<br />
|
||||
<strong>Git Commit: </strong>{{ docker.GitCommit }}<br />
|
||||
<strong>Go Version: </strong>{{ docker.GoVersion }}<br />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<div class="well">
|
||||
<strong>Running containers:</strong>
|
||||
<br />
|
||||
<strong>Endpoint: </strong>{{ endpoint }}
|
||||
<ul>
|
||||
<li ng-repeat="container in containers">
|
||||
<a href="/#/containers/{{ container.Id }}/">{{ container.Id|truncate:20 }}</a>
|
||||
<span class="pull-right label label-{{ container.Status|statusbadge }}">{{ container.Status }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
Loading…
Reference in New Issue