dockerspaniel
v0.2.0
Published
Create Dockerfiles from JSON
Downloads
22
Maintainers
Readme
Why would anyone ever use this?
Short answer? Continuous delivery.
Docker has wide applications in platform engineering. It is particularly useful for creating isolated build environments. Docker images are created from Dockerfiles, which contain various steps. If you are targeting multiple platforms, you may find yourself juggling a bunch of similar Dockerfiles with slight variations.
This tool will help maximize code reuse and enable you to generate unique Dockerfiles on-the-fly based on several features, such as tag-driven step inclusion/exclusion and variable substitution.
Installation
$ npm install -g dockerspaniel
Quick Start
Create a Spanielfile (JSON)
{
"from": "ubuntu:12.04",
"maintainer": "Josh Dolitsky <[email protected]>",
"steps": [
{
"instruction": "run",
"arguments": "apt-get update",
"comment": "update packages"
},
{
"instruction": "run",
"arguments": "apt-get install -y nodejs",
"comment": "install dependencies"
}
]
}
Convert the Spanielfile to a Dockerfile
The following command
$ dockerspaniel
will create a Dockerfile in the same directory:
FROM ubuntu:12.04
MAINTAINER Josh Dolitsky <[email protected]>
# update packages
RUN apt-get update
# install dependencies
RUN apt-get install -y nodejs
Command-line Options
Usage: dockerspaniel -i [input] -o [output] -b [baseimage] -t [tag]
-h|--help This help screen
-i|--input JSON file to use for input (default: Spanielfile)
-o|--output Path of new Dockerfile to create (default: Dockerfile)
-b|--base Override Docker base image to use in FROM instruction
-t|--tag Tag(s) for use by 'unless' and 'only' step attributes
Supports mutliple tags via format '-t tag1 -t tag2' etc.
Tagging
The step attributes unless_one, unless, only_one, and only will allow you to include or exclude steps based on provided tags.
{
"from": "ubuntu:12.04",
"steps": [
{
"instruction": "run",
"arguments": "apt-get update",
"unless_one": [
"no_update"
]
},
{
"instruction": "run",
"arguments": "apt-get install -y nodejs",
"only_one": [
"nodejs"
]
}
]
}
From the above Spanielfile, many different Dockerfiles can be created.
(no tags)
Includes all steps without an only or only_one array.
$ dockerspaniel
. . .
FROM ubuntu:12.04
RUN apt-get update
no_update
Prevents update step because 'no_update' is present in the step's unless_one array.
$ dockerspaniel -t no_update
. . .
FROM ubuntu:12.04
nodejs
Includes nodejs install step because 'nodejs' is present in the step's only_one array.
$ dockerspaniel -t nodejs
. . .
FROM ubuntu:12.04
RUN apt-get update
RUN apt-get install -y nodejs
no_update and nodejs
Prevents update AND installs nodejs.
$ dockerspaniel -t no_update -t nodejs
. . .
FROM ubuntu:12.04
RUN apt-get install -y nodejs
Variable Substitution
Variable substitution is supported via Handlebars in the format {{my_var}}.
The following Spanielfile has the defaults object defined, which defines default values:
{
"from": "ubuntu:12.04",
"steps": [
{
"instruction": "run",
"arguments": "apt-get install -y {{dependencies}}"
}
],
"defaults": {
"dependencies": "wget curl screen vim"
}
}
$ dockerspaniel
...
FROM ubuntu:12.04
RUN apt-get install -y wget curl screen vim
Variables can be overridden by environment variables prefixed with DS_:
$ export DS_DEPENDENCIES="tmux nodejs"
$ dockerspaniel
...
FROM ubuntu:12.04
RUN apt-get install -y tmux nodejs
You are also able to use other Handlebar features, such as the each block helper. Notice in the example below that defaults.dependencies is now an array.
{
"from": "ubuntu:12.04",
"steps": [
{
"instruction": "run",
"arguments": "apt-get install -y {{#each dependencies}}{{this}} {{/each}}"
}
],
"defaults": {
"dependencies": ["wget", "curl", "screen", "vim"]
}
}
$ dockerspaniel
...
FROM ubuntu:12.04
RUN apt-get install -y wget curl screen vim
External Files
If a step contains either the file or include attribute, step.arguments and step.instuction are ignored.
file attribute
step.file is the path to a raw Dockerfile to include in place, which supports templating.
Spanielfile
{
"from": "ubuntu:12.04",
"steps": [
{
"file": "path/to/Dockerfile1",
"newline": true
}
],
"defaults": {
"install_jdk": "RUN apt-get install -y openjdk-7-jdk"
}
}
path/to/Dockerfile1
# Dockerfile1
RUN apt-get update
{{install_jdk}}
Resulting Dockerfile
FROM ubuntu:12.04
# Dockerfile1
RUN apt-get update
RUN apt-get install -y openjdk-7-jdk
include attribute
step.include is the path to another Spanielfile to include in place.
Spanielfile
{
"from": "fedora:20",
"steps": [
{
"include": "path/to/add_user.json",
"comment": "create new user"
}
],
"defaults": {
"username": "paul"
}
}
path/to/add_user.json
{
"steps": [
{
"instruction": "run",
"arguments": "adduser {{username}}"
}
]
}
Resulting Dockerfile
FROM fedora:20
# create new user with sudo access
RUN adduser paul
Spanielfile Attributes
from
Base image for subsequent instructions. Required unless the --base option is used.
maintainer
Author field of generated images.
defaults
Key-value pairs to use for Handlebars templating.
steps
Array of step objects. A step object has the following attributes:
step.instruction
Docker instruction. All instructions are supported, see the official documentation for a list: https://docs.docker.com/reference/builder
step.arguments
Arguments to pass to Docker instruction. For the step RUN apt-get update, RUN is the instruction and apt-get update is the arguments.
step.unless_one
Array of tags that, when ONE is provided, will cause this step to be excluded. See NOR gates.
step.unless
Array of tags that, when ALL are provided, will cause this step to be excluded. See NAND gates.
step.only_one
Array of tags that, when ONE is provided, will cause this step to be included. See OR gates.
step.only
Array of tags that, when ALL are provided, will cause this step to be included. See AND gates.
step.comment
Comment placed above the step.
step.newline
When true, adds a newline above the step without a comment.
step.include
Include an external Spanielfile. This should be either an absolute path, or a path relative to the parent file. Any defaults defined here will override defaults from the parent (but environment variables will still override these). This causes both step.instruction and step.arguments to be ignored.
step.file
Include an external Dockerfile (with optional Handlebars templating). This should be either an absolute path, or a path relative to the parent file. This causes step.include, step.instruction, and step.arguments to be ignored.
Using Programmatically
generateContents(data, callback)
var ds = require('dockerspaniel');
var data = {
from: 'ubuntu:12.04',
maintainer: 'John Smith',
steps: [
{
instruction: 'run',
arguments: 'apt-get update'
},
{
instruction: 'run',
arguments: 'apt-get install -y nodejs',
only: [
'nodejs'
]
},
{
instruction: 'run',
arguments: 'apt-get install -y mysql-server mysql-client',
unless: [
'no_database'
]
}
]
};
var tags = ['nodejs', 'no_database'];
ds.generateContents(data, tags, function(err, contents) {
if (err) throw err;
console.log(contents);
});
createDockerfile(options, callback)
var ds = require('dockerspaniel');
var options = {
input: '/path/to/json/file.json',
output: '/path/to/new/Dockerfile',
tags: [
'nodejs',
'no_database'
],
base: 'ubuntu:12.04'
};
ds.createDockerfile(options, function (err) {
if (err) throw err;
// new Dockerfile was created at options.output
});