Baha is a command-line utility that assists in the creation of docker images.
It addresses some of Dockerfiles shortcomings and encourages smaller, reusable, tagged images.
Why not Dockerfiles?
Dockerfiles are simple. They are an easy way to make a docker image without needing any other dependencies. However, their simplicity comes at a cost: redundancy. This redundancy is present in a few ways that make more complicated images difficult to make and maintain.
So why would I use Baha?
Baha attempts to address the shortcomings of Dockerfiles by factoring out redundancies and providing a modular interface for creating suites of dependent images.
1. Baha forbids more than 1 layer per image
If you split statements across multiple
RUN statements, each of these results in a new layer.
The more commands you run, the more layers you create. If you want to minimize the number of layers (See Official Recommendations)
then you must ensure that all statements can be condensed into one line - sacrificing maintainability in the process.
Baha encourages using scripts instead of
RUN statements to ensure that only one layer is created per image.
2. Baha encourages smaller images
The nature of the way the dockerfiles are processed means that each command you run commits a new image.
This means, that if you have a
RUN statement that downloads packages for installation.
This will commit a layer with the installation files. Later on if you clean up these files with further
RUN commands, they will still exist in your image lineage - thus having no space savings. Without proper precautions, you'll end up having unnecessarily large images.
Baha ensures that all setup tasks happen in a single commit - so you can write cleanup statements and be assured that they will indeed be absent in the resulting images.
3. Baha understands the bigger picture
Another best practice (2: #7) recommends that you use your own base image.
Dockerfiles make it simple to create your own 'base' image, but how about updates?
If you were to just rebuild all of your Dockerfiles, you would create an entirely new tree - even if nothing changed.
Baha will rebuild your entire lineage if the base image changes, but will not rebuild base images if only the children change.
Baha relies on tagging your releases, noticing when the tag has changed, and treating tags as immutable.
This is analogous to how git treats tags.
Tagging your images is another best-practice (2: #5) anyway, so this is encouraged by design.
Bottom line is: If you change your image, you should change the tag/version.
4. Baha lets you cache build dependencies
Most of the time, dependencies are downloaded and installed in the context of the docker container itself.
This means that rebuilding an image results in redundant downloads if files haven't changed.
Baha has pre-build steps that can be used to download files and prepare scripts on host machine.
This workspace is made available to the image via a bind mount during build-time. Not only do these dependencies stick around between builds, but they do not need to be cleaned up after the image is committed, since they are never persisted to the container.
This gem was just released (pre 1.0) and is not ready for production use yet.
During pre 1.0, things may change that break backwards compatibility between releases. Most likely these breaking
changes would be related to the YAML file syntax.
See the Issue Tracker
$ gem install baha
Baha Commands: baha build [options] CONFIG # Builds all docker images based on the given config baha convert DOCKERFILE n, --name=NAME # Converts an existing dockerfile to a Baha-compatible image.yml baha help [COMMAND] # Describe available commands or one specific command baha version # Print version and exit
Usage: baha build [options] CONFIG Options: [--logfile=LOGFILE] # Log output to LOGFILE. Omit to log to stdout. d, [--debug], [--no-debug] # Toggle debug logging. Includes verbose. v, [--verbose], [--no-verbose] # Toggle verbose logging q, [--quiet], [--no-quiet] # Suppress all logging Description: Reads the CONFIG file and builds all of the docker images in the order they appear.
Usage: baha convert DOCKERFILE n, --name=NAME Options: n, --name=NAME # The target image name t, [--tag=TAG] # The target image tag # Default: latest o, [--output=OUTPUT] # Target output file # Default: STDOUT Description: Reads the given Dockerfile and outputs a Baha-compatible image.yml which can be included or embedded within a CONFIG
Check out the example directory for a sample CONFIG.
To run the example build
### 1. ### If necessary (using boot2docker) export the correct environment variables ### You can find this by running boot2docker up # export DOCKER_HOST=tcp://192.168.59.103:2376 # export DOCKER_CERT_PATH=$HOME/.boot2docker/certs/boot2docker-vm # export DOCKER_TLS_VERIFY=1 ### 2. ### Checkout baha git clone https://github.com/justenwalker/baha.git cd baha ### 3. Install bundle bundle install ### 4. Run the example.yml bundle exec baha build -d example/example.yml
How it works
Baha will read a config.yml file first and load each image configuration.
It will build each image in the order they appear by doing the following.
Check if the image needs updating
- Check to see if the parent image changed
- Check to see if the tag does not exist in the repository
Prepare the image's workspace (bind mount)
- Create the workspace directory if it doesn't exist
- Run any
pre_buildtasks to prepare dependencies
Run the command inside the image
- Creates a new container and runs it with the
- Commits the container with the run options specified in the images
Tags the resulting image
Adds the appropriate tags to the image as defined in the image config for both the remote registry and local repository.
Baha inside Docker
If you'd like to use baha completely inside docker, you can follow these additional instructions.
Set up your environment
There are a few environment variables that Baha needs in order to work within docker. In most cases, the default values should be fine.
BAHA_IMAGE is the image that the
docker-baha.sh script uses to run baha inside a docker container. The default is
justenwalker/baha. Modify this if you want to use a different image.
BAHA_MOUNT is the location on the docker host that contains the config files. By default, this is the current working directory:
BAHA_WORKSPACE_MOUNT is the location where files generated by the build process will be stored and also where Baha will instruct docker to mount volumes from. By default, this is
DOCKER_SOCKET is the location of the unix socket for communicating with docker. baha-docker.sh mounts this inside the container so that it can interact with docker directly. By default, this is
/var/run/docker.sock which should be correct for boot2docker and Linux, unless you've modified the path.
Note: boot2docker only mounts
/Users, so setting
BAHA_WORKSPACE_MOUNT outside this setting will not work.
export BAHA_MOUNT=/Users/myself/baha export BAHA_WORKSPACE_MOUNT=/Users/myself/baha/workspace export DOCKER_SOCKET=/var/run/docker.sock
Copy docker-baha.sh to somewhere in your $PATH and make it executable
To be able to easily execute the cli,
docker-baha.sh has some sensible defaults and the actual docker run command-line options. Feel free to modify to suit your needs.
cp docker-baha.sh /usr/local/bin/baha chmod 755 /usr/local/bin/baha
Build baha as a docker image
If you want to get started quickly, you can just use the latest image built on the Docker Hub.
Run the following command inside your working-copy to create a new local image called 'justenwalker/baha'
docker build -t justenwalker/baha .
If you want to use a different image name, be sure to either modify
docker-baha.sh or modify
BAHA_IMAGE to use the new name.
Run baha as you would normally
baha build example.yml
How to Contribute
Contributions are welcome! Documentation, bug-fixes, patches, or new functionality, or comments/criticism.
Start by forking the github project.
Work on a topic branch instead of master (
git checkout -b my-feature) and submit a pull request when you are done.
Please add specs to cover the change so that we can avoid regressions and help future commits from breaking existing code.
Running the tests
$ bundle $ bundle exec rake spec
$ bundle $ [bundle exec] rake install
Please include a reproducible test case if possible. Otherwise, provide as much detail as you can.
Copyright (c) 2014 Justen Walker.
Released under the terms of the MIT License. For further information, please see the file