From 0c563fb3fb63acfbfec18a71d4d728941cf68cb1 Mon Sep 17 00:00:00 2001 From: Eugene Kazakov Date: Mon, 1 May 2017 00:42:03 +0700 Subject: [PATCH 1/8] Delete tags with API v2 --- app/image/image-controller.js | 9 ++----- app/services/registry-services.js | 17 +++++++----- app/tag/delete-tags-controller.js | 43 ++++++++++--------------------- app/tag/tag-controller.js | 21 ++++++++++----- app/tag/tag-detail.html | 14 +++------- app/tag/tag-list-directive.html | 19 +++++++++----- develop/docker-compose.yml | 9 +++++-- start-apache.sh | 2 -- 8 files changed, 64 insertions(+), 70 deletions(-) diff --git a/app/image/image-controller.js b/app/image/image-controller.js index 65da230..c94a7e5 100644 --- a/app/image/image-controller.js +++ b/app/image/image-controller.js @@ -14,8 +14,7 @@ angular.module('image-controller', ['registry-services', 'app-mode-services']) $scope.appMode = AppMode.query(); $scope.totalImageSize = 0; - $scope.imageDetails = Manifest.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, tagName: $scope.tagName}); - + $scope.imageDetails = Manifest.query({repository: $scope.repository, tagName: $scope.tagName}); @@ -30,11 +29,7 @@ angular.module('image-controller', ['registry-services', 'app-mode-services']) $scope.totalImageSize = 0; var size; angular.forEach($scope.imageDetails.fsLayers, function (id, key) { - - Blob.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, digest: id.blobSum}).$promise.then( function(data, headers){ - size = data; - console.log(data) - console.log(size) + Blob.query({repository: $scope.repository, digest: id.blobSum}).$promise.then(function(data){ if(!isNaN(data.contentLength-0)){ $scope.totalImageSize += data.contentLength; } diff --git a/app/services/registry-services.js b/app/services/registry-services.js index ed4f843..6d2ec28 100644 --- a/app/services/registry-services.js +++ b/app/services/registry-services.js @@ -121,10 +121,6 @@ angular.module('registry-services', ['ngResource']) return res; }, }, - 'delete': { - url: '/v1/repositories/:repoUser/:repoName/tags/:tagName', - method: 'DELETE', - }, 'exists': { url: '/v1/repositories/:repoUser/:repoName/tags/:tagName', method: 'GET', @@ -143,7 +139,7 @@ angular.module('registry-services', ['ngResource']) }]) .factory('Manifest', ['$resource', function($resource){ - return $resource('/v2/:repoUser/:repoName/manifests/:tagName', {}, { + return $resource('/v2/:repository/manifests/:tagName', {}, { // Response example: // { // "schemaVersion": 1, @@ -169,6 +165,9 @@ angular.module('registry-services', ['ngResource']) // } 'query': { method:'GET', + headers: { + accept: 'application/vnd.docker.distribution.manifest.v2+json', + }, isArray: false, transformResponse: function(data, headers){ var res = {}; @@ -207,13 +206,17 @@ angular.module('registry-services', ['ngResource']) res.architecture = resp.architecture; return res; }, - } + }, + 'delete': { + url: '/v2/:repository/manifests/:digest', + method: 'DELETE', + }, }); }]) // This is not totally working right now (problem with big layers) /* .factory('Blob', ['$resource', function($resource){ - return $resource('/v2/:repoUser/:repoName/blobs/:digest', {}, { + return $resource('/v2/:repository/blobs/:digest', {}, { 'query': { method:'HEAD', diff --git a/app/tag/delete-tags-controller.js b/app/tag/delete-tags-controller.js index c3f7c54..6376aa8 100644 --- a/app/tag/delete-tags-controller.js +++ b/app/tag/delete-tags-controller.js @@ -8,46 +8,31 @@ * Controller of the docker-registry-frontend */ angular.module('delete-tags-controller', ['registry-services']) - .controller('DeleteTagsController', ['$scope', '$route', '$modalInstance', '$window', 'Tag', 'items', 'information', - function($scope, $route, $modalInstance, $window, Tag, items, information) + .controller('DeleteTagsController', ['$scope', '$route', '$modalInstance', '$window', 'Manifest', 'items', 'information', + function($scope, $route, $modalInstance, $window, Manifest, items, information) { $scope.items = items; $scope.information = information; // Callback that triggers deletion of tags and reloading of page $scope.ok = function () { - angular.forEach($scope.items, function(value, key) { - var tagStr = value; + angular.forEach($scope.items, function(value) { + var repository = value.split(":")[0]; var tagName = value.split(":")[1]; - var repoUser = value.split("/")[0]; - var repoName = value.split("/")[1].split(":")[0]; - var tag = { - repoUser: repoUser, - repoName: repoName, + Manifest.query({ + repository: repository, tagName: tagName - }; - - if (!Tag.exists(tag)) { - toastr.warning('Tag does no longer exist: ' + tagStr); - return; - } - - Tag.delete(tag, - // success - function(value, responseHeaders) { - toastr.success('Deleted tag: ' + tagStr); - }, - // error - function(httpResponse) { - toastr.error('Failed to delete tag: ' + tagStr + ' Response: ' + httpResponse.statusText); - } - ); + }).$promise.then(function (data) { + Manifest.delete({ + repository: repository, + digest: data.digest + }).$promise.then(function () { + $window.location.href = '/repository/' + repository; + }); + }); }); $modalInstance.close(); - - // Go to the repositories page - $window.location.href = 'repositories'; }; $scope.cancel = function () { diff --git a/app/tag/tag-controller.js b/app/tag/tag-controller.js index 23c89f0..da7ccc6 100644 --- a/app/tag/tag-controller.js +++ b/app/tag/tag-controller.js @@ -63,18 +63,12 @@ angular.module('tag-controller', ['registry-services']) if(!isNaN(idx)){ tmpIdx = parseInt(idx) + idxShift; if ( result[tmpIdx].hasOwnProperty('name') ) { - result[tmpIdx].details = Manifest.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, tagName: result[tmpIdx].name}); + result[tmpIdx].details = Manifest.query({repository: $scope.repository, tagName: result[tmpIdx].name}); } } } }); - - - // Copy collection for rendering in a smart-table - $scope.displayedTags = [].concat($scope.tags); - - // selected tags $scope.selection = []; @@ -83,6 +77,19 @@ angular.module('tag-controller', ['registry-services']) return filterFilter($scope.displayedTags, { selected: true }); }; + // Watch tags for changes + // To watch for changes on a property inside the object "tags" + // we first have to make sure the promise is ready. + $scope.tags.$promise.then(function(data) { + // Copy collection for rendering in a smart-table + $scope.displayedTags = [].concat(data); + $scope.$watch('displayedTags|filter:{selected:true}', function(nv) { + $scope.selection = nv.map(function (tag) { + return $scope.repository + ':' + tag.name; + }); + }, true); + }); + $scope.openConfirmTagDeletionDialog = function(size) { var modalInstance = $modal.open({ animation: true, diff --git a/app/tag/tag-detail.html b/app/tag/tag-detail.html index 085756b..16d62ef 100644 --- a/app/tag/tag-detail.html +++ b/app/tag/tag-detail.html @@ -3,27 +3,21 @@
  • Repositories
  • {{repositoryUser}}
  • {{repositoryName}}
  • -
  • {{tagName}}
  • +
  • {{tagName}}
  • Details for tag {{repositoryUser}} / - {{repositoryName}} : - {{tagName}} + {{repositoryName}} : + {{tagName}}
    -
    - -

    diff --git a/app/tag/tag-list-directive.html b/app/tag/tag-list-directive.html index c9fc235..8edfc3a 100644 --- a/app/tag/tag-list-directive.html +++ b/app/tag/tag-list-directive.html @@ -10,7 +10,8 @@ - + + @@ -19,13 +20,19 @@ - - + + + - - + + diff --git a/develop/docker-compose.yml b/develop/docker-compose.yml index 3ac4b0a..711d30d 100644 --- a/develop/docker-compose.yml +++ b/develop/docker-compose.yml @@ -1,7 +1,10 @@ frontend: build: . links: - - registry:path-to-your-registry-v2 + - registry:registry + environment: + - DOCKER_REGISTRY_HOST=registry + - DOCKER_REGISTRY_PORT=5000 ports: # Serves the page via grunt - "9000:9000" @@ -11,6 +14,8 @@ frontend: - ../:/source:rw - ./start-develop.sh:/root/start-develop.sh:ro registry: - image: registry:2.1.1 + image: registry ports: - "5000:5000" + environment: + - REGISTRY_STORAGE_DELETE_ENABLED=true diff --git a/start-apache.sh b/start-apache.sh index a5c5b9b..b957fca 100644 --- a/start-apache.sh +++ b/start-apache.sh @@ -37,8 +37,6 @@ echo "{\"host\": \"$ENV_REGISTRY_PROXY_FQDN\", \"port\": $ENV_REGISTRY_PROXY_POR # information about browse mode. [[ x$ENV_MODE_BROWSE_ONLY =~ ^x(true|false)$ ]] || ENV_MODE_BROWSE_ONLY=false -# Overwrite browse-only option for now since only browse-only is working right now -ENV_MODE_BROWSE_ONLY=true [[ -z "$ENV_DEFAULT_REPOSITORIES_PER_PAGE" ]] && ENV_DEFAULT_REPOSITORIES_PER_PAGE=20 [[ -z "$ENV_DEFAULT_TAGS_PER_PAGE" ]] && ENV_DEFAULT_TAGS_PER_PAGE=10 echo "{\"browseOnly\":$ENV_MODE_BROWSE_ONLY, \"defaultRepositoriesPerPage\":$ENV_DEFAULT_REPOSITORIES_PER_PAGE , \"defaultTagsPerPage\":$ENV_DEFAULT_TAGS_PER_PAGE }" > /var/www/html/app-mode.json From d2dc506da1616f7118b290a35d7c884aa85580b3 Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Sat, 2 Jun 2018 23:27:45 -0400 Subject: [PATCH 2/8] Update Dockerfile to offical Node 8 image The existing Dockerfile was a Ubuntu image which installed Node and NPM via apt-get. This change set updates the Dockerfile to use the offical Node image which has the chosin version of Node and NPM pre-installed. It also switches to an Alpine image to lower the file size. --- develop/Dockerfile | 47 +++++++++++++--------------------------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/develop/Dockerfile b/develop/Dockerfile index 4a151b6..c5a7ba4 100644 --- a/develop/Dockerfile +++ b/develop/Dockerfile @@ -1,8 +1,20 @@ -FROM ubuntu:14.04 +FROM node:8-alpine MAINTAINER "Konrad Kleine" USER root +# The node image removes these packages as they are only needed to build node not to run it +# Since we update npm package at start up will need these in the image +RUN apk add --no-cache \ + bash \ + curl \ + gcc \ + g++ \ + git \ + make \ + nano \ + python + ############################################################ # Setup environment variables ############################################################ @@ -10,39 +22,6 @@ USER root ENV SOURCE_DIR /source ENV START_SCRIPT /root/start-develop.sh -############################################################ -# Speedup DPKG and don't use cache for packages -############################################################ - -# Taken from here: https://gist.github.com/kwk/55bb5b6a4b7457bef38d -# -# this forces dpkg not to call sync() after package extraction and speeds up -# install -RUN echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/02apt-speedup -# we don't need and apt cache in a container -RUN echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache - -RUN apt-get -y update && \ - export DEBIAN_FRONTEND=noninteractive - -############################################################ -# Install development requirements -############################################################ - -RUN apt-get -y install \ - git \ - nodejs \ - nodejs-legacy \ - npm \ - --no-install-recommends -RUN git config --global url."https://".insteadOf git:// -# Avoid this: "Problem with the SSL CA cert (path? access rights?)" -RUN git config --global http.sslVerify false - -############################################################ -# Create start script -############################################################ - # Let people know how this was built ADD Dockerfile /root/Dockerfile From 5e7bbf77b55eedd6a861d83b0a9a62901e3f4226 Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Sat, 2 Jun 2018 23:44:07 -0400 Subject: [PATCH 3/8] Update to docker-compose v3 This change set updates the docker-compose file in the develop folder to use the v3 syntax. This allows us to add a user layer network so that the two containers can communicate without having to go up the network stack. This allows us to not have to expose the registery's port (5000) to the host. This reduces the chance of a port conflict --- develop/docker-compose.yml | 44 ++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/develop/docker-compose.yml b/develop/docker-compose.yml index 3ac4b0a..c825636 100644 --- a/develop/docker-compose.yml +++ b/develop/docker-compose.yml @@ -1,16 +1,28 @@ -frontend: - build: . - links: - - registry:path-to-your-registry-v2 - ports: - # Serves the page via grunt - - "9000:9000" - # For live reload with grunt - - "35729:35729" - volumes: - - ../:/source:rw - - ./start-develop.sh:/root/start-develop.sh:ro -registry: - image: registry:2.1.1 - ports: - - "5000:5000" +version: '3.2' +services: + frontend: + build: . + ports: + # Serves the page via grunt + - "9000:9000" + # For live reload with grunt + - "35729:35729" + depends_on: + - registry + volumes: + - ../:/source:rw + - ./start-develop.sh:/root/start-develop.sh:ro + environment: + - DOCKER_REGISTRY_HOST=registry + - DOCKER_REGISTRY_PORT=5000 + registry: + image: registry:2.1.1 + expose: + - "5000" + networks: + dev_net: + aliases: + - path-to-your-registry-v2 + +networks: + dev_net: From b67985a1fd63f55cc14c2aad9b803327141bb7e1 Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Sun, 3 Jun 2018 19:49:37 -0400 Subject: [PATCH 4/8] :art:Re-orginize package.json I just perfer to see the dependancies at the bottom as they can tend to grow and it makes it easier to view the more important stuff like meta info about the package and the scripts in a terminal editor if they are at the top --- package.json | 60 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 305a7a1..cec10cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,36 @@ { "name": "docker-registry-frontend", + "description": "A pure web-based frontend to a docker-registry", "version": "0.0.2", + "author": "Konrad Kleine", + "license": "MIT", + "keywords": [ + "docker", + "registry", + "frontend", + "ui" + ], + "main": "Gruntfile.js", + "directories": { + "test": "test" + }, + "engines": { + "node": ">=0.10.0" + }, + "repository": { + "type": "git", + "url": "git@github.com:kwk/docker-registry-frontend.git" + }, + "bugs": { + "url": "https://github.com/kwk/docker-registry-frontend/issues" + }, + "scripts": { + "server": "grunt serve", + "postinstall": "bower install", + "pretest": "npm install", + "test": "karma start test/karma.conf.js", + "test-single-run": "karma start test/karma.conf.js --single-run" + }, "dependencies": {}, "devDependencies": { "bower": "^1.7.2", @@ -37,35 +67,5 @@ "karma-spec-reporter": "0.0.26", "load-grunt-tasks": "^3.4.0", "time-grunt": "^1.3.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "server": "grunt serve", - "postinstall": "bower install", - "pretest": "npm install", - "test": "karma start test/karma.conf.js", - "test-single-run": "karma start test/karma.conf.js --single-run" - }, - "description": "A pure web-based frontend to a docker-registry", - "main": "Gruntfile.js", - "directories": { - "test": "test" - }, - "repository": { - "type": "git", - "url": "git@github.com:kwk/docker-registry-frontend.git" - }, - "keywords": [ - "docker", - "registry", - "frontend", - "ui" - ], - "author": "Konrad Kleine", - "license": "MIT", - "bugs": { - "url": "https://github.com/kwk/docker-registry-frontend/issues" } } From e7aed6b1e779be165d5f6a874c8b078edc1686c5 Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Sun, 3 Jun 2018 21:33:49 -0400 Subject: [PATCH 5/8] Move from Bower to NPM This change set removes :fire: Bower as the dependancy package manager and switches over to NPM. Bower requiers all packages to be in git and pulls them out of a public git repo. NPM on the other hand is a registry of packages and it has become the go to for JS package dependancy for both Node and Browser applications. The Bower website even suggests moving off Bower in favor of NPM/Yarn. --- .bowerrc | 3 --- .dockerignore | 1 - .gitignore | 1 - Dockerfile | 5 +--- Gruntfile.js | 34 +++++-------------------- app/about.html | 8 +++--- app/images/tool-bower.png | Bin 4739 -> 0 bytes app/images/tool-npm.png | Bin 0 -> 1617 bytes app/index.html | 52 +++++++++++++++++++------------------- bower.json | 31 ----------------------- develop/start-develop.sh | 1 - package.json | 27 +++++++++++++++++--- test/karma.conf.js | 28 ++++++++++---------- 13 files changed, 74 insertions(+), 117 deletions(-) delete mode 100644 .bowerrc delete mode 100644 app/images/tool-bower.png create mode 100644 app/images/tool-npm.png delete mode 100644 bower.json diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 69fad35..0000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/.dockerignore b/.dockerignore index 6b93a3b..071fae3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,7 +2,6 @@ node_modules dist .tmp .saas-cache -bower_components screenshots *~ *.swp diff --git a/.gitignore b/.gitignore index fdc8139..503e460 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ node_modules dist .tmp .sass-cache -bower_components *~ *.swp diff --git a/Dockerfile b/Dockerfile index 1a78f0e..542c0f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,7 @@ RUN echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache RUN mkdir -p $SOURCE_DIR/dist \ $SOURCE_DIR/app \ $SOURCE_DIR/test \ - $SOURCE_DIR/.git + $SOURCE_DIR/.git # Add dirs ADD app $SOURCE_DIR/app @@ -40,12 +40,10 @@ ADD test $SOURCE_DIR/test # Dot files ADD .jshintrc $SOURCE_DIR/ -ADD .bowerrc $SOURCE_DIR/ ADD .editorconfig $SOURCE_DIR/ ADD .travis.yml $SOURCE_DIR/ # Other files -ADD bower.json $SOURCE_DIR/ ADD Gruntfile.js $SOURCE_DIR/ ADD LICENSE $SOURCE_DIR/ ADD package.json $SOURCE_DIR/ @@ -82,7 +80,6 @@ RUN apt-get -y update && \ git config --global url."https://".insteadOf git:// && \ cd $SOURCE_DIR && \ npm install && \ - node_modules/bower/bin/bower install --allow-root && \ node_modules/grunt-cli/bin/grunt build --allow-root && \ cp -rf $SOURCE_DIR/dist/* $WWW_DIR && \ rm -rf $SOURCE_DIR && \ diff --git a/Gruntfile.js b/Gruntfile.js index 5f5bdad..617fec1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -22,7 +22,7 @@ module.exports = function (grunt) { // Configurable paths for the application var appConfig = { - app: require('./bower.json').appPath || 'app', + app: 'app', dist: 'dist' }; @@ -34,10 +34,6 @@ module.exports = function (grunt) { // Watches files for changes and runs tasks based on the changed files watch: { - bower: { - files: ['bower.json'], - tasks: ['wiredep'] - }, js: { files: ['<%= yeoman.app %>/{,*/}*.js'], tasks: ['newer:jshint:all'], @@ -105,8 +101,8 @@ module.exports = function (grunt) { middlewares.push( connect.static('.tmp'), connect().use( - '/bower_components', - connect.static('./bower_components') + '/node_modules', + connect.static('./node_modules') ), connect.static(appConfig.app) ); @@ -123,8 +119,8 @@ module.exports = function (grunt) { connect.static('.tmp'), connect.static('test'), connect().use( - '/bower_components', - connect.static('./bower_components') + '/node_modules', + connect.static('./node_modules') ), connect.static(appConfig.app) ]; @@ -189,14 +185,6 @@ module.exports = function (grunt) { } }, - // Automatically inject Bower components into the app - wiredep: { - app: { - src: ['<%= yeoman.app %>/index.html'], - ignorePath: /\.\.\// - } - }, - // Renames files for browser caching purposes filerev: { dist: { @@ -316,13 +304,6 @@ module.exports = function (grunt) { } }, - // Replace Google CDN references - cdnify: { - dist: { - html: ['<%= yeoman.dist %>/*.html'] - } - }, - // Copies remaining files to places other tasks can use copy: { dist: { @@ -346,7 +327,7 @@ module.exports = function (grunt) { src: ['generated/*'] }, { expand: true, - cwd: 'bower_components/bootstrap/dist', + cwd: 'node_modules/bootstrap/dist', src: 'fonts/*', dest: '<%= yeoman.dist %>' }] @@ -391,7 +372,6 @@ module.exports = function (grunt) { grunt.task.run([ 'clean:server', - 'wiredep', 'concurrent:server', 'autoprefixer', 'configureProxies:server', @@ -415,14 +395,12 @@ module.exports = function (grunt) { grunt.registerTask('build', [ 'clean:dist', - 'wiredep', 'useminPrepare', 'concurrent:dist', 'autoprefixer', 'concat', 'ngAnnotate', 'copy:dist', - 'cdnify', 'cssmin', 'uglify', 'filerev', diff --git a/app/about.html b/app/about.html index 3b5c469..8270a70 100644 --- a/app/about.html +++ b/app/about.html @@ -49,11 +49,11 @@

    Grunt

    - Bower + NPM
    -

    Bower

    -

    The Bower package manager is used to manage all the dependencies of the code.

    -

    Checkout Bower

    +

    NPM

    +

    The NPM package manager is used to manage all the dependencies of the code.

    +

    Checkout NPM

    diff --git a/app/images/tool-bower.png b/app/images/tool-bower.png deleted file mode 100644 index 62c40bec4a9a89804a5bfa261fcb20293b144c56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4739 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 - - - - - + + + + + @@ -47,31 +47,31 @@

    Docker Registry Frontend

    - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/bower.json b/bower.json deleted file mode 100644 index d85d631..0000000 --- a/bower.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "docker-registry-frontend", - "version": "0.0.0", - "dependencies": { - "angular": "~1.3.0", - "json3": "~3.3.1", - "es5-shim": "~3.1.0", - "bootstrap": "3.3.4", - "angular-resource": "~1.3.0", - "angular-cookies": "~1.3.0", - "angular-sanitize": "~1.3.0", - "angular-animate": "~1.3.0", - "angular-touch": "~1.3.0", - "angular-route": "~1.3.0", - "toastr": "~2.0.3", - "angular-bootstrap": "~0.13.0", - "angular-loading-bar": "~0.6.0", - "angular-moment": "~0.8.2", - "angular-smart-table": "~1.3.0", - "angular-filter": "~0.5.2", - "angular-bootstrap-checkbox": "~0.3.1" - }, - "devDependencies": { - "angular-mocks": "~1.3.0", - "angular-scenario": "~1.3.0" - }, - "resolutions": { - "angular": "~1.3.0" - }, - "appPath": "app" -} diff --git a/develop/start-develop.sh b/develop/start-develop.sh index 72c3cf5..142b5a7 100755 --- a/develop/start-develop.sh +++ b/develop/start-develop.sh @@ -3,5 +3,4 @@ set -x set -e cd $SOURCE_DIR npm install -node_modules/bower/bin/bower install --allow-root node_modules/grunt-cli/bin/grunt serve --allow-root diff --git a/package.json b/package.json index cec10cd..5a4a5b3 100644 --- a/package.json +++ b/package.json @@ -25,15 +25,34 @@ "url": "https://github.com/kwk/docker-registry-frontend/issues" }, "scripts": { - "server": "grunt serve", - "postinstall": "bower install", + "start": "grunt serve", "pretest": "npm install", "test": "karma start test/karma.conf.js", "test-single-run": "karma start test/karma.conf.js --single-run" }, - "dependencies": {}, + "dependencies": { + "angular": "~1.3.0", + "angular-animate": "~1.3.0", + "angular-bootstrap-checkbox": "~0.5.0", + "angular-cookies": "~1.3.0", + "angular-filter": "~0.5.2", + "angular-loading-bar": "~0.6.0", + "angular-moment": "~0.8.2", + "angular-resource": "~1.3.0", + "angular-route": "~1.3.0", + "angular-sanitize": "~1.3.0", + "angular-smart-table": "~1.4.12", + "angular-touch": "~1.3.0", + "angular-ui-bootstrap": "~0.13.0", + "bootstrap": "3.3.4", + "es5-shim": "~3.2.0", + "jquery": "^2.1.4", + "json3": "~3.3.1", + "toastr": "~2.0.3" + }, "devDependencies": { - "bower": "^1.7.2", + "angular-mocks": "~1.3.0", + "angular-scenario": "~1.3.0", "connect-modrewrite": "^0.8.2", "grunt": "^0.4.1", "grunt-autoprefixer": "^3.0.3", diff --git a/test/karma.conf.js b/test/karma.conf.js index da47709..d1d1168 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -20,20 +20,20 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - 'bower_components/angular/angular.js', - 'bower_components/angular-animate/angular-animate.js', - 'bower_components/angular-bootstrap/ui-bootstrap.js', - 'bower_components/angular-bootstrap-checkbox/angular-bootstrap-checkbox.js', - 'bower_components/angular-cookies/angular-cookies.js', - 'bower_components/angular-filter/dist/angular-filter.js', - 'bower_components/angular-loading-bar/src/loading-bar.js', - 'bower_components/angular-mocks/angular-mocks.js', - 'bower_components/angular-moment/angular-moment.js', - 'bower_components/angular-resource/angular-resource.js', - 'bower_components/angular-route/angular-route.js', - 'bower_components/angular-sanitize/angular-sanitize.js', - 'bower_components/angular-smart-table/src/smart-table.module.js', - 'bower_components/angular-touch/angular-touch.js', + 'node_modules/angular/angular.js', + 'node_modules/angular-animate/angular-animate.js', + 'node_modules/angular-ui-bootstrap/ui-bootstrap.js', + 'node_modules/angular-bootstrap-checkbox/angular-bootstrap-checkbox.js', + 'node_modules/angular-cookies/angular-cookies.js', + 'node_modules/angular-filter/dist/angular-filter.js', + 'node_modules/angular-loading-bar/src/loading-bar.js', + 'node_modules/angular-mocks/angular-mocks.js', + 'node_modules/angular-moment/angular-moment.js', + 'node_modules/angular-resource/angular-resource.js', + 'node_modules/angular-route/angular-route.js', + 'node_modules/angular-sanitize/angular-sanitize.js', + 'node_modules/angular-smart-table/src/smart-table.module.js', + 'node_modules/angular-touch/angular-touch.js', 'app/**/*.js', 'test/spec/**/*.js' ], From df7da0a15db28c7f225d180959186f589fc1d70c Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Fri, 8 Jun 2018 10:05:52 -0400 Subject: [PATCH 6/8] :art:Refactor Dockerfile to use multi-stage featcher Docker files can now be setup to use multiple images to generate a build pipe line. This allows you to use different images (i.e. official images) vs. a single image with all tools installed. With this change we can remove NPM and Node from the run time image which just needs Apache. We can also seperate the hosting commands from the compilation commands. The current Dockerfile installed apache, node, and npm as well as packages required to install the NPM packages used to _build_ the angular app. Once built all the files are served staticlly via apache. Node and NPM are _not_ needed to host the application. This results in dependencies and commands being mixed up. This change set splits the Dockerfile into two stages: Build and Host The Build stage uses an offical Node image and installs the OS packages needed to run the Grunt tasks. It then copies in the source files and runs Grunt build. The artifacts of this image are located in the dist directory. The Host stage uses a debian:jessie image and installs apache (maybe later we can move to an offical Apache image), it then copies the artifacts from the Build stage into its /var/www/html folder, then configers and starts Apache. Now the steps and dependencies are nicely seperated --- Dockerfile | 97 +++++++++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1a78f0e..6eea346 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,52 @@ -FROM debian:jessie -MAINTAINER "Konrad Kleine" +################################################################################ +# Stage 1: Build the Angluar application +################################################################################ +FROM node:8-alpine as build_app +LABEL maintainer="Konrad Kleine" + +ENV WORKDIR=/usr/src +RUN mkdir -p $WORKDIR \ + $WORKDIR/.git + +WORKDIR $WORKDIR + +# The node image removes these packages as they are only needed to build node not to run it +# Since we are installing/building npm packages will need these in the image +RUN apk add --no-cache --virtual .build-deps \ + automake \ + autoconf \ + gcc \ + g++ \ + make \ + nasm \ + python \ + zlib-dev + +COPY . $WORKDIR + +RUN npm install \ + && apk del .build-deps + +# Add some git files for versioning +ADD .git/HEAD $WORKDIR/.git/HEAD +ADD .git/refs $WORKDIR/.git/refs + +# Create version file +RUN export GITREF=$(cat .git/HEAD | cut -d" " -f2) && \ + export GITSHA1=$(cat .git/$GITREF) && \ + echo "{\"git\": {\"sha1\": \"$GITSHA1\", \"ref\": \"$GITREF\"}}" > app-version.json + +## Build App +RUN node_modules/grunt-cli/bin/grunt build --allow-root +################################################################################ +# Stage 2: Run the Angular application +################################################################################ + +FROM debian:jessie +LABEL maintainer="Konrad Kleine" + USER root ############################################################ @@ -9,7 +54,6 @@ USER root ############################################################ ENV WWW_DIR /var/www/html -ENV SOURCE_DIR /tmp/source ENV START_SCRIPT /root/start-apache.sh RUN mkdir -pv $WWW_DIR @@ -28,32 +72,8 @@ RUN echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache ############################################################ -# Create dirs -RUN mkdir -p $SOURCE_DIR/dist \ - $SOURCE_DIR/app \ - $SOURCE_DIR/test \ - $SOURCE_DIR/.git - -# Add dirs -ADD app $SOURCE_DIR/app -ADD test $SOURCE_DIR/test - -# Dot files -ADD .jshintrc $SOURCE_DIR/ -ADD .bowerrc $SOURCE_DIR/ -ADD .editorconfig $SOURCE_DIR/ -ADD .travis.yml $SOURCE_DIR/ - -# Other files -ADD bower.json $SOURCE_DIR/ -ADD Gruntfile.js $SOURCE_DIR/ -ADD LICENSE $SOURCE_DIR/ -ADD package.json $SOURCE_DIR/ -ADD README.md $SOURCE_DIR/ - -# Add some git files for versioning -ADD .git/HEAD $SOURCE_DIR/.git/HEAD -ADD .git/refs $SOURCE_DIR/.git/refs +COPY --from=build_app /usr/src/dist/ $WWW_DIR/ +COPY --from=build_app /usr/src/app-version.json $WWW_DIR/app-version.json ############################################################ # Install and configure webserver software @@ -63,30 +83,11 @@ RUN apt-get -y update && \ export DEBIAN_FRONTEND=noninteractive && \ apt-get -y install \ apache2 \ - bzip2 \ libapache2-mod-auth-kerb \ libapache2-mod-proxy-html \ - git \ - nodejs \ - nodejs-legacy \ - npm \ --no-install-recommends && \ a2enmod proxy && \ a2enmod proxy_http && \ - cd $SOURCE_DIR && \ - export GITREF=$(cat .git/HEAD | cut -d" " -f2) && \ - export GITSHA1=$(cat .git/$GITREF) && \ - echo "{\"git\": {\"sha1\": \"$GITSHA1\", \"ref\": \"$GITREF\"}}" > $WWW_DIR/app-version.json && \ - cd $SOURCE_DIR && \ - rm -rf $SOURCE_DIR/.git && \ - git config --global url."https://".insteadOf git:// && \ - cd $SOURCE_DIR && \ - npm install && \ - node_modules/bower/bin/bower install --allow-root && \ - node_modules/grunt-cli/bin/grunt build --allow-root && \ - cp -rf $SOURCE_DIR/dist/* $WWW_DIR && \ - rm -rf $SOURCE_DIR && \ - apt-get -y --auto-remove purge git nodejs nodejs-legacy npm bzip2 && \ apt-get -y autoremove && \ apt-get -y clean && \ rm -rf /var/lib/apt/lists/* From 77725ee13ce525d27ce5b3fe7b71de491b1cddf3 Mon Sep 17 00:00:00 2001 From: Brad van der Laan Date: Sat, 9 Jun 2018 00:04:27 -0400 Subject: [PATCH 7/8] :green_heart:Fix Karam Tests With the change to move off bower I had to update angular-smart-table because NPM did not have the very old version we were using. The oldest 1.x version it had was 1.4.12. In angular-smart-table 1.4.2 however they refactored their smart-table.module.js file to no longer pass in the angular global but instead refernce the ng variable directly. This caused an issue with the Karma config as ng is unknown. Looking at https://github.com/lorenzofox3/Smart-Table/commit/13da8c9d81ba115c5d58cac3a17253f3e41d1f01#diff-40dfb1c53004f1488cbe6eb300b286dd I see what they did for their Karma test config so this change set is just copying that to ensure that the angular-smart-table module is imported propertly in the tests. This does not seem to be an issue in prod. --- test/init-smart-table.js | 1 + test/karma.conf.js | 1 + 2 files changed, 2 insertions(+) create mode 100644 test/init-smart-table.js diff --git a/test/init-smart-table.js b/test/init-smart-table.js new file mode 100644 index 0000000..07af0f6 --- /dev/null +++ b/test/init-smart-table.js @@ -0,0 +1 @@ +ng = angular; diff --git a/test/karma.conf.js b/test/karma.conf.js index d1d1168..a28090e 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -32,6 +32,7 @@ module.exports = function(config) { 'node_modules/angular-resource/angular-resource.js', 'node_modules/angular-route/angular-route.js', 'node_modules/angular-sanitize/angular-sanitize.js', + 'test/init-smart-table.js', 'node_modules/angular-smart-table/src/smart-table.module.js', 'node_modules/angular-touch/angular-touch.js', 'app/**/*.js', From 207b4d5f9efe7e9d17c41cf4ff03b0fbeb7c9f57 Mon Sep 17 00:00:00 2001 From: Craig Anderson Date: Thu, 9 Aug 2018 15:21:46 +0100 Subject: [PATCH 8/8] Remove apache2.pid which can hang around after dirty exit. --- start-apache.sh | 7 +++++++ 1 file changed, 7 insertions(+) mode change 100644 => 100755 start-apache.sh diff --git a/start-apache.sh b/start-apache.sh old mode 100644 new mode 100755 index a5c5b9b..7e9c11e --- a/start-apache.sh +++ b/start-apache.sh @@ -86,4 +86,11 @@ a2enmod rewrite # Stop apache first if is still running from the last time the container was run service apache2 stop +# apache2.pid can hang around from previous dirty exits +# (https://github.com/kwk/docker-registry-frontend/issues/159) +if [ -f /var/run/apache2/apache2.pid ] +then + rm /var/run/apache2/apache2.pid +fi + /usr/sbin/apache2ctl -D FOREGROUND ${useSsl}
    Tag Tag Image ID Created Author
    + +
    - {{tag.name}} +
    + + + {{tag.name}}