From b5a629e187969e88299cafb8e10326e30815847d Mon Sep 17 00:00:00 2001 From: Kenneth Falck Date: Fri, 17 Apr 2015 12:58:15 +0300 Subject: [PATCH] feat(gen) add Dockerfile and docker-compose.yml support Add support to run generated Angular-Fullstack applications as Docker containers by including Dockerfile, docker-compose.yml and .dockerignore. When the application is built with grunt build, these files are copied to the dist directory. The Docker container can then be built and started there with the "docker-compose up" command. When Mongoose is used, Docker Compose will also launch a MongoDB container, eliminating the need to install MongoDB on the local machine. Note that Docker and Docker Compose must be installed for Docker support to work. They are available on Linux, OS X and Windows. --- Gruntfile.js | 3 ++- app/index.js | 9 +++++++++ app/templates/.dockerignore(docker) | 2 ++ app/templates/Dockerfile(docker) | 4 ++++ app/templates/Gruntfile.js | 5 ++++- app/templates/docker-compose.yml(docker) | 13 +++++++++++++ .../server/config/environment/production.js | 6 +++++- test/test-file-creation.js | 17 +++++++++++++++-- 8 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 app/templates/.dockerignore(docker) create mode 100644 app/templates/Dockerfile(docker) create mode 100644 app/templates/docker-compose.yml(docker) diff --git a/Gruntfile.js b/Gruntfile.js index 38fc08efc..5d8a76c0d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -160,7 +160,8 @@ module.exports = function (grunt) { testing: 'jasmine', auth: true, oauth: ['googleAuth', 'twitterAuth'], - socketio: true + socketio: true, + docker: false }; var deps = [ diff --git a/app/index.js b/app/index.js index ec954aa46..1568e1896 100644 --- a/app/index.js +++ b/app/index.js @@ -212,8 +212,17 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ return answers.odms && answers.odms.length !== 0; }, default: true + }, { + type: 'confirm', + name: 'docker', + message: 'Would you like to include Docker support?', + when: function (answers) { + return answers.odms && answers.odms.length !== 0; + }, + default: false }], function (answers) { if(answers.socketio) this.filters.socketio = true; + if(answers.docker) this.filters.docker = true; if(answers.auth) this.filters.auth = true; if(answers.odms && answers.odms.length > 0) { var models; diff --git a/app/templates/.dockerignore(docker) b/app/templates/.dockerignore(docker) new file mode 100644 index 000000000..9daa8247d --- /dev/null +++ b/app/templates/.dockerignore(docker) @@ -0,0 +1,2 @@ +.DS_Store +node_modules diff --git a/app/templates/Dockerfile(docker) b/app/templates/Dockerfile(docker) new file mode 100644 index 000000000..16b8b9d6d --- /dev/null +++ b/app/templates/Dockerfile(docker) @@ -0,0 +1,4 @@ +# Production Dockerfile - Used in the dist directory after grunt build +FROM node:0.12-onbuild +ENV NODE_ENV production +EXPOSE 8080 diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 666681a89..7fd34da7b 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -391,7 +391,10 @@ module.exports = function (grunt) { }, { expand: true, dest: '<%%= yeoman.dist %>', - src: [ + src: [<% if (filters.docker) { %> + 'Dockerfile', + '.dockerignore', + 'docker-compose.yml',<% } %> 'package.json', 'server/**/*' ] diff --git a/app/templates/docker-compose.yml(docker) b/app/templates/docker-compose.yml(docker) new file mode 100644 index 000000000..b70bd29a6 --- /dev/null +++ b/app/templates/docker-compose.yml(docker) @@ -0,0 +1,13 @@ +# This file works in the dist directory after grunt build is finished. +# Usage: +# pip install docker-compose +# docker-compose up +<% if (filters.mongoose) { %> +<%= _.slugify(appname) %>mongodb: + image: mongo:latest<% } %> +<%= _.slugify(appname) %>: + build: . + links: + - "<%= _.slugify(appname) %>mongodb:mongodb" + ports: + - "8080:8080" diff --git a/app/templates/server/config/environment/production.js b/app/templates/server/config/environment/production.js index e0b77bf97..33035bcdb 100644 --- a/app/templates/server/config/environment/production.js +++ b/app/templates/server/config/environment/production.js @@ -18,7 +18,11 @@ module.exports = { uri: process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || process.env.OPENSHIFT_MONGODB_DB_URL + - process.env.OPENSHIFT_APP_NAME || + process.env.OPENSHIFT_APP_NAME ||<% if (filters.docker) { %> + (process.env.MONGODB_PORT_27017_TCP_ADDR ? 'mongodb://' + + process.env.MONGODB_PORT_27017_TCP_ADDR + ':' + + process.env.MONGODB_PORT_27017_TCP_PORT + + '/<%= _.slugify(appname) %>' : null) ||<% } %> 'mongodb://localhost/<%= _.slugify(appname) %>' } }; diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 7850fc9e4..ea5f221f6 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -22,7 +22,8 @@ describe('angular-fullstack generator', function () { odms: [ 'mongoose' ], auth: true, oauth: [], - socketio: true + socketio: true, + docker: false }, dependenciesInstalled = false; function copySync(s, d) { fs.writeFileSync(d, fs.readFileSync(s)); } @@ -304,6 +305,15 @@ describe('angular-fullstack generator', function () { ]); } + /* Docker support files */ + if (ops.docker) { + files = files.concat([ + 'Dockerfile', + '.dockerignore', + 'docker-compose.yml' + ]); + } + return files; } @@ -502,6 +512,7 @@ describe('angular-fullstack generator', function () { auth: true, oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], socketio: true, + docker: false, bootstrap: true, uibootstrap: true }; @@ -574,6 +585,7 @@ describe('angular-fullstack generator', function () { auth: true, oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], socketio: true, + docker: false, bootstrap: true, uibootstrap: true }; @@ -647,6 +659,7 @@ describe('angular-fullstack generator', function () { auth: false, oauth: [], socketio: false, + docker: false, bootstrap: false, uibootstrap: false }; @@ -720,6 +733,7 @@ describe('angular-fullstack generator', function () { auth: false, oauth: [], socketio: false, + docker: false, bootstrap: true, uibootstrap: true }; @@ -767,7 +781,6 @@ describe('angular-fullstack generator', function () { // runTest('grunt test:e2e:prod', this, done, 240000); //}); } - }); }); });