diff --git a/README.md b/README.md index ce20e8267..b97fd6193 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Cloudinovasi UI for Docker +This UI is dedicated to CloudInovasi internal usage. + A fork of the amazing UI for Docker by Michael Crosby and Kevan Ahlquist (https://github.com/kevana/ui-for-docker) using the rdash-angular theme (https://github.com/rdash/rdash-angular). ![Dashboard](/dashboard.png) @@ -56,7 +58,7 @@ $ docker run -d -p 10.20.30.1:80:9000 --privileged -v /var/run/docker.sock:/var/ ### Hide containers with specific labels -You can hide specific containers in the containers view by using the `-hide-label` or `-l` options and specifying a label. +You can hide specific containers in the containers view by using the `--hide-label` or `-l` options and specifying a label. For example, take a container started with the label `owner=acme`: @@ -70,6 +72,16 @@ You can hide it in the view by starting the ui with: $ docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui -l owner=acme ``` +### Custom Docker registries support + +You can specify the support of others registries than DockerHub by using the `--registries` or `-r` options and specifying a registry using the format *REGISTRY_NAME=REGISTRY_ADDRESS*. + +For example, if I want the registry 'myCustomRegistry' pointing to *myregistry.domain.com:5000* available in the UI: + +``` +$ docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui -r myCustomRegistry=myregistry.domain.com:5000 +``` + ### Available options The following options are available for the `ui-for-docker` binary: @@ -79,4 +91,5 @@ The following options are available for the `ui-for-docker` binary: * `--data`, `-d`: Path to the data folder (default: *"."*) * `--assets`, `-a`: Path to the assets (default: *"."*) * `--swarm`, `-s`: Swarm cluster support (default: *false*) -* `--hide-label`, `-l`: Hide containers with a specific label in the UI +* `--hide-label`, `-l`: Hide containers with a specific label in the UI (format *LABEL_NAME=LABEL_VALUE*) +* `--registries`, `-r`: Available registries in the UI (format *REGISTRY_NAME=REGISTRY_ADDRESS*) diff --git a/app/components/createContainer/createContainerController.js b/app/components/createContainer/createContainerController.js index 4360729dc..c61fc2495 100644 --- a/app/components/createContainer/createContainerController.js +++ b/app/components/createContainer/createContainerController.js @@ -8,9 +8,12 @@ function ($scope, $state, Config, Container, Image, Volume, Network, Messages, e $scope.formValues = { Console: 'none', - Volumes: [] + Volumes: [], + AvailableRegistries: [], + Registry: '', }; + $scope.imageConfig = {}; $scope.config = { Env: [], HostConfig: { @@ -51,6 +54,8 @@ function ($scope, $state, Config, Container, Image, Volume, Network, Messages, e Config.$promise.then(function (c) { var swarm = c.swarm; + $scope.formValues.AvailableRegistries = c.registries; + Volume.query({}, function (d) { var persistedVolumes = d.Volumes.filter(function (volume) { if (volume.Driver === 'local-persist') { @@ -105,22 +110,9 @@ function ($scope, $state, Config, Container, Image, Volume, Network, Messages, e }); } - function createImageConfig(imageName) { - var imageNameAndTag = imageName.split(':'); - var imageConfig = { - fromImage: imageNameAndTag[0], - tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest' - }; - return imageConfig; - } - function pullImageAndCreateContainer(config) { $('#createContainerSpinner').show(); - - var image = _.toLower(config.Image); - var imageConfig = createImageConfig(image); - - Image.create(imageConfig, function (data) { + Image.create($scope.imageConfig, function (data) { var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error'); if (err) { var detail = data[data.length - 1]; @@ -135,6 +127,28 @@ function ($scope, $state, Config, Container, Image, Volume, Network, Messages, e }); } + function createImageConfig(imageName, registry) { + var imageNameAndTag = imageName.split(':'); + var image = imageNameAndTag[0]; + if (registry) { + image = registry + '/' + imageNameAndTag[0]; + } + var imageConfig = { + fromImage: image, + tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest' + }; + return imageConfig; + } + + function prepareImageConfig(config) { + var image = _.toLower(config.Image); + var registry = $scope.formValues.Registry; + var imageConfig = createImageConfig(image, registry); + console.log(JSON.stringify(imageConfig, null, 4)); + config.Image = imageConfig.fromImage + ':' + imageConfig.tag; + $scope.imageConfig = imageConfig; + } + function preparePortBindings(config) { var bindings = {}; config.HostConfig.PortBindings.forEach(function (portBinding) { @@ -194,6 +208,7 @@ function ($scope, $state, Config, Container, Image, Volume, Network, Messages, e function prepareConfiguration() { var config = angular.copy($scope.config); + prepareImageConfig(config); preparePortBindings(config); prepareConsole(config); prepareEnvironmentVariables(config); diff --git a/app/components/createContainer/createcontainer.html b/app/components/createContainer/createcontainer.html index e82f1ea76..819812097 100644 --- a/app/components/createContainer/createcontainer.html +++ b/app/components/createContainer/createcontainer.html @@ -18,11 +18,18 @@ - +
-
- +
+ +
+ +
+
@@ -32,7 +39,7 @@
- +
diff --git a/app/components/images/images.html b/app/components/images/images.html index 5ed569661..09420abda 100644 --- a/app/components/images/images.html +++ b/app/components/images/images.html @@ -15,14 +15,21 @@
- +
-
+
+ +
+ +
- +
diff --git a/app/components/images/imagesController.js b/app/components/images/imagesController.js index 02c4b3a64..8ae37b746 100644 --- a/app/components/images/imagesController.js +++ b/app/components/images/imagesController.js @@ -1,6 +1,6 @@ angular.module('images', []) -.controller('ImagesController', ['$scope', '$state', 'Image', 'Messages', -function ($scope, $state, Image, Messages) { +.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'Messages', +function ($scope, $state, Config, Image, Messages) { $scope.state = {}; $scope.sortType = 'RepoTags'; $scope.sortReverse = true; @@ -8,7 +8,8 @@ function ($scope, $state, Image, Messages) { $scope.state.selectedItemCount = 0; $scope.config = { - Image: '' + Image: '', + Registry: '', }; $scope.order = function(sortType) { @@ -35,10 +36,14 @@ function ($scope, $state, Image, Messages) { } }; - function createImageConfig(imageName) { + function createImageConfig(imageName, registry) { var imageNameAndTag = imageName.split(':'); + var image = imageNameAndTag[0]; + if (registry) { + image = registry + '/' + imageNameAndTag[0]; + } var imageConfig = { - fromImage: imageNameAndTag[0], + fromImage: image, tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest' }; return imageConfig; @@ -47,7 +52,8 @@ function ($scope, $state, Image, Messages) { $scope.pullImage = function() { $('#pullImageSpinner').show(); var image = _.toLower($scope.config.Image); - var imageConfig = createImageConfig(image); + var registry = $scope.config.Registry; + var imageConfig = createImageConfig(image, registry); Image.create(imageConfig, function (data) { var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error'); if (err) { @@ -104,5 +110,9 @@ function ($scope, $state, Image, Messages) { }); } - fetchImages(); + Config.$promise.then(function (c) { + $scope.availableRegistries = c.registries; + fetchImages(); + }); + }]); diff --git a/dockerui.go b/dockerui.go index 7e29a73b9..439608dbd 100644 --- a/dockerui.go +++ b/dockerui.go @@ -18,12 +18,13 @@ import ( ) var ( - endpoint = kingpin.Flag("endpoint", "Dockerd endpoint").Default("/var/run/docker.sock").Short('e').String() - addr = kingpin.Flag("bind", "Address and port to serve UI For Docker").Default(":9000").Short('p').String() - assets = kingpin.Flag("assets", "Path to the assets").Default(".").Short('a').String() - data = kingpin.Flag("data", "Path to the data").Default(".").Short('d').String() - swarm = kingpin.Flag("swarm", "Swarm cluster support").Default("false").Short('s').Bool() - labels = LabelParser(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')) + endpoint = kingpin.Flag("endpoint", "Dockerd endpoint").Default("/var/run/docker.sock").Short('e').String() + addr = kingpin.Flag("bind", "Address and port to serve UI For Docker").Default(":9000").Short('p').String() + assets = kingpin.Flag("assets", "Path to the assets").Default(".").Short('a').String() + data = kingpin.Flag("data", "Path to the data").Default(".").Short('d').String() + swarm = kingpin.Flag("swarm", "Swarm cluster support").Default("false").Short('s').Bool() + labels = LabelParser(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')) + registries = LabelParser(kingpin.Flag("registries", "Supported Docker registries").Short('r')) authKey []byte authKeyFile = "authKey.dat" ) @@ -35,6 +36,7 @@ type UnixHandler struct { type Config struct { Swarm bool `json:"swarm"` HiddenLabels Labels `json:"hiddenLabels"` + Registries Labels `json:"registries"` } type Label struct { @@ -47,7 +49,7 @@ type Labels []Label func (l *Labels) Set(value string) error { parts := strings.SplitN(value, "=", 2) if len(parts) != 2 { - return fmt.Errorf("expected HEADER=VALUE got '%s'", value) + return fmt.Errorf("expected NAME=VALUE got '%s'", value) } label := new(Label) label.Name = parts[0] @@ -179,6 +181,7 @@ func main() { configuration := Config{ Swarm: *swarm, HiddenLabels: *labels, + Registries: *registries, } handler := createHandler(*assets, *data, *endpoint, configuration) diff --git a/gruntFile.js b/gruntFile.js index f2cbfd90a..160068fcc 100644 --- a/gruntFile.js +++ b/gruntFile.js @@ -267,7 +267,7 @@ module.exports = function (grunt) { command: [ 'docker stop ui-for-docker', 'docker rm ui-for-docker', - 'docker run --privileged -d -p 9000:9000 -v /tmp/docker-ui:/data --name ui-for-docker ui-for-docker -e http://10.0.7.11:4000 --swarm -d /data' + 'docker run --privileged -d -p 9000:9000 -v /tmp/docker-ui:/data --name ui-for-docker ui-for-docker -e http://10.0.7.10:4000 --swarm -d /data -r local=192.168.2.193:5000' ].join(';') }, cleanImages: {