diff --git a/README.md b/README.md index d697ee6..16e52f9 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Grunt configuration Grunt-Dock supports main and targets level configuration. -Here is basic Grunt configuration: +Here is a basic Grunt configuration: ```javascript dock: { @@ -106,7 +106,11 @@ dock: { } // dock ``` -The property 'dockerfile' can be any supported Docker formats plus plain format (this case, Grunt-Dock will create a tar.gz stream to pass to Docker - very usefull for development -). +The property 'dockerfile' supports: + + * **tar archive** any tarballs supported by Docker (.tar, .tar.gz, .tar.bz2, .tar.xz). It will be passed directly to the Docker server. + * **directory** Grunt-Dock will create a tarball (gz compressed) of this directory before sending it to Docker. + * **plain file** Grunt-Dock will create a tarball containing 1 "Dockerfile" file. You can define some specifics options to pass for each commands of each images (start, stop, build, etc.). See Docker API/Dockerode documentations. diff --git a/lib/build.js b/lib/build.js index 286cad8..02dd34a 100644 --- a/lib/build.js +++ b/lib/build.js @@ -6,6 +6,7 @@ var fs = require('fs'), path = require('path'), tar = require('tar-stream'), + tarfs = require('tar-fs'), concat = require('concat-stream'), zlib = require('zlib'), async = require('async'), @@ -56,26 +57,55 @@ var buildCommands = function(grunt, docker, options, done, tag) { // Tar + gz if plain content. var process = function(tag, image, callback) { + if (!image.dockerfile) return callback(new Error('Dockerfile is null.')); + // Create the options object for the build var imageOptions = image.options || {}; var buildOpts = utils.merge({t: tag}, imageOptions.build || {}); - var fileExt = path.extname(image.dockerfile); + var stats = fs.statSync(path.resolve(image.dockerfile)); - if (fileExt) { + // Option 1: source is directory, pack it + if (stats.isDirectory()) { + tarfs.pack(path.resolve(image.dockerfile)) + .pipe(zlib.createGzip()) + .pipe(concat(function (data) { + build(data, buildOpts, callback); + })); + } + else if (stats.isFile()) { var content; - try { content = fs.readFileSync(image.dockerfile); - } catch (e) { + } catch(e) { return done(e); } - build(content, buildOpts, callback); - } else { - tarfs.pack(path.dirname(path.resolve(image.dockerfile))).pipe(zlib.createGzip()).pipe(concat(function (data) { - build(data, buildOpts, callback); - })); + var isTar = utils.isTarFile(image.dockerfile); + + switch(isTar) { + case true: + // The file is already a tar, build with it. + build(content, buildOpts, callback); + break; + + case false: + // Compress the file before sending to docker + var pack = tar.pack(); + pack.entry({ name:'Dockerfile' }, content); + pack.finalize(); + + pack.pipe(zlib.createGzip()) + .pipe(concat(function(data) { + build(data, buildOpts, callback); + })); + + break; + } + + } + else { + return callback(new Error('Unsupported format.')); } }; diff --git a/lib/utils.js b/lib/utils.js index 328d4d7..cfec53c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -97,5 +97,23 @@ utils.getUserHome = function() { return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; }; +/** + * Check if filename is a tar archive by checking the extension. + * @return {Boolean} True if yes, else false. + */ +utils.isTarFile = function(filename) { + var exts = ['.tar', '.tar.gz', '.tar.bz2', '.tar.xz', '.tgz', '.tbz2', '.txz'], + endsWith = function (str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + for (var i = 0; i < exts.length; i++) { + if (endsWith(filename, exts[i])) { + return true; + } + } + + return false; +}; module.exports = utils; diff --git a/package.json b/package.json index 7f8286c..b4c5e54 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "grunt-dock", "description": "A grunt plugin to manage Docker", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "author": "Johann Troendle", "maintainers": [ diff --git a/test/build.js b/test/build.js index d17abf0..3811e55 100644 --- a/test/build.js +++ b/test/build.js @@ -64,7 +64,7 @@ describe("build", function() { stubs.buildImage = sinon.stub(docker, 'buildImage').yields('error', null); - build(grunt, docker, {images: {}}, function(e) { + build(grunt, docker, {images: {'test' : {dockerfile: null}}}, function(e) { expect(e).not.to.be.null; done(); });