Home

Awesome

WARNING: I haven't had time to maintain this project. Use them at your own risk. Thank you for your understanding.

Table of contents

Description

Bocker makes your Dockerfile reusable. The name is combined from B(ash) and (D)ocker.

Dockerfile is a mix of shell commands, run-time settings and stuff. It looks simple at first, but in a long run, you'll have some problems:

This project is to solve these problems. It will read some Bash source files, and write new Dockerfile to STDOUT. The output is cacheable, and can be executed by docker build command.

Getting started

A minimal example

Take a look at a quite minimal example in examples/Bockerfile.alpine.

#!/usr/bin/env bash

# The default Alpine shell /bin/sh

ed_shell  /bin/sh
ed_from   alpine:3.8
ed_env    --later Hello World

ed_bocker() {
  :
}

To use this file, type the following commands

$ cd examples/
$ ../bocker.sh Bockerfile.alpine > Dockerfile.alpine

New contents are exactly a Dockerfile for your build.

More examples

Overloading? Improve caching with --later? Use ship instead of ADD / COPY commands?

See more from examples/README.md at https://github.com/icy/bocker/blob/master/examples/README.md or a collection of Bockerfile at https://github.com/icy/docker/tree/master/bocker.

Install and Usage

Requirements

Bocker requires the popular tools:

base64 is a basic tool from coreutils package.

Installation

There is only one Bash script bocker.sh. Put this script in one of your binary directories, and start it with Bockerfile

$ bocker.sh MyBockerfile >/dev/null # to see if there is any error
$ bocker.sh MyBockerfile            # to see Dockerfile output

The output is written to STDOUT. You should check if there is anything wrong from STDERR, because Bocker is unable to check if your source file has problem.

Command line options

Syntax of Bockerfile

All Bockerfiles are Bash source files. That means you can write your source in some small files, and include them in other files.

The first rule is that every method is started with ed_.

Front matter

There are some basic methods to define your meta information. For your overview, let's see:

ed_from        YOUR_BASE_IMAGE
ed_maintainer  "YOUR INFORMATION"

ed_env         FOO /bar/
ed_expose      80
ed_volume      /example.net/
ed_cmd         '["/supervisor.sh", "foo", "bar"]'
ed_ship        foobar
....

Think of FROM, MAINTAINER, EXPOSE. They are:

All these commands can be used multiple times, and/or be put in your base libraries. (See examples/lib/core.sh.)

The last statement of ed_from (ed_maintainer, ed_cmd, ed_entrypoint) will win; other functions have additive effect.

Main matter

You can define your set of methods as Bash functions, each of them has a name started by ed_. For example, in examples/lib/debian.sh, you will see ed_apt_clean that removes unused apt-get variable data to minimize the size of your result image.

Main function: ed_bocker

This is a must-have function. Bocker will raise error if you don't define it.

This function should not contain any function from PREAMBLE section.

It can have some special functions

Bocker will read the contents of this ed_bocker function, replace every appearance of ed_* by __ed_ship_method ed_*. That means, if you type ed_apt_clean, Bocker will invoke __ed_ship_method ed_apt_clean for you.

Because this is actually a replace-execute trick, it's your duty to make your definition of ed_bocker as simple as possible. Don't use complex stuff like expansion and (WHO KNOWS?) If you have to do that, put your stuff under some functions, ship them to the image with ed_ship, and that's just enough.

Dockerfile vs. Bockerfile

Facts

Here is a table for quick reference.

PurposeDockerfileBockerfile (Preamble)ed_bocker
Base imageFROMed_from
Base scripted_reuse
Base scripted_source, source
MaintainerMAINTAINERed_maintainer
Volume exposeVOLUMEed_volume
Port exposeEXPOSEed_expose
Init scriptENTRYPOINTed_entrypoint
Init commandCMDed_cmd
Int commandONBUILDed_onbuild
VariableENVed_env [--later]
Build commandRUNed_bockered_foo, ed_run
Build commandADDed_copy --add --latered_add
Build commandCOPYed_copy --latered_copy
Build commandUSERed_user --latered_user
Build commandWORKDIRTODOed_workdir
Declare methodN/Aed_ship [--later]
Grouping&&ed_group
LabelLABELed_labelecho "LABEL foo=bar"
Raw statementecho "# Something"

/bocker.sh script

The result image has /bocker.sh script that contains (almost) all your functions.

When you use ed_ship or invoke some command inside your ed_bocker, your function definitions are saved originally (except the comments, of course) to the /bocker.sh script in the result image.

This script only contains functions, and if you provide any arguments to it, they are considered as command in the environment where your functions are defined. For example

# ed_ship --later my_method
/bocker.sh ed_my_method
# /bocker.sh find

will invoke ed_my_method (or find command) that you have shipped.

Because of this, you can simply define a start-up function, and use /bocker.sh to call them. That exactly means, bocker.sh can be used as your ENTRYPOINT.

Important notes

History

When the project is started, its name is EDocker, that's why you see ed_ prefixes. EDocker isn't a good name, hence you see Bocker now.

License. Author

This work is released the terms of MIT license. The author is Anh K. Huynh.