Skip to content

Commit 7abf51a

Browse files
committed
Refactor project for 0.9.0 release
It's a big one, probably incomplete changes list: * Raise Bash min version to 4.2, add jq as host dependency for Docker usage * Add a Kubler bash-completion script * Prepare Kubler for installation as system app * Add support for user managed custom commands/engines or overrides * Prepare for split of example images into a separate git repo * Minor refactor of the build process, -i now builds missing parents for example * Add configure_builder hook, replaces configure_bob. Both will be supported for a while though * The portage container is no longer updated via git, the amount of upstream changes is too large, snapshots all the way now per default * Run a Docker health-check or custom image test script as part of the build * Review/improve all ui output for consistency, also now in glorius 8bit color! * Add compact output mode, if enabled almost all cmd output is logged to file logs * Add dep-graph command to visualize image dependencies in dot/ascii/png * Add a few clean command options to remove built and dangling images * Improve 'new' command user handling to be less confusing * Lots of minor improvements and some fixes for edge cases See also #154
1 parent 9927836 commit 7abf51a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2452
-1052
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ before_install:
99
- docker pull koalaman/shellcheck
1010

1111
script:
12-
- docker run -w /scripts -v $(pwd):/scripts koalaman/shellcheck -x
13-
kubler.sh lib/*.sh lib/engine/docker.sh lib/cmd/*.sh lib/bob-core/*.sh lib/argbash/argbash-refresh.sh
12+
- docker run --rm -w /scripts -v $(pwd):/scripts koalaman/shellcheck -x
13+
kubler.sh lib/*.sh lib/engine/docker.sh lib/cmd/*.sh lib/bob-core/*.sh lib/cmd/argbash/argbash-refresh.sh

README.md

Lines changed: 100 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -10,174 +10,139 @@ and the German name Schmidt, the cooper trade is also the origin of German names
1010
> There is still demand for high-quality ~~wooden barrels~~ containers, and it is thought that the
1111
highest-quality ~~barrels~~ containers are those hand-made by professional ~~coopers~~ kublers.
1212

13-
At the core Kubler is just a simple ~~craftsman~~ bash script that, well, builds things.. and things that
14-
can depend on other things. It does'nt really care all too much about the details as long as it gets
15-
to build. So what, some ~~people~~ scripts just like to build things. Don't judge.
13+
## Why Should You Care?
1614

17-
What kind of things? In theory your imagination is the limit, but we provide batteries for building
18-
[Docker][] images, with [acbuild][] (read: rkt and OCI) support in the works. PR are always welcome. ;)
15+
Perhaps:
1916

20-
Due to it's unrivaled flexibility [Gentoo][] is used under the hood as build container base,
21-
however the final images hold just the runtime dependencies for selected software packages, resulting
22-
in very slim images. To achieve this a 2 phase build process is employed, essentially the often requested, but
23-
still missing, Docker feature for [nested](https://github.com/docker/docker/issues/7115) image builds.
17+
1. You love Docker but are annoyed by some of the restrictions of it's `build` command that keep
18+
getting into your way. Wouldn't it be nice if you could `build` your images with all `docker run`
19+
args, like `-v`, at your disposal?
20+
2. You are a SysAdmin or DevOps engineer who seeks complete governance for the contents of their
21+
Docker images, with full control of the update cycle and the ability to track software version
22+
changes across the board from a centralized vcs repository.
23+
3. You need to manage a **lot** of Docker base/service images in a sane way and want peace of mind
24+
with automated post-build tests.
25+
4. You are a Gentoo user that wants to build slim Gentoo based images without having to wrestle
26+
with CrossDev.
27+
5. You are looking for an interactive OS host agnostic Gentoo playground or a portable ebuild
28+
development environment.
29+
6. You want to create custom root file systems, possibly for different cpu architectures, in a safe
30+
and repeatable manner.
2431

25-
## Goals
32+
## Cool. So What Exactly Is A Container Image Meta Builder?
2633

27-
* Central, organization-wide management of base images
28-
* Containers should only contain the bare minimum to run
29-
* Separate build and runtime dependencies
30-
* Only deploy runtime dependencies
31-
* Maximum flexibility while assembling the root file system, but with minimal effort
32-
* Keep things maintainable as the stack grows
34+
While Kubler was designed primarily for building and managing container images it doesn't
35+
particularly care about the way those images are built. At the core it's just a glorified directory
36+
crawler, with a simple dependency mechanism, that fires a command on a selected image or namespace
37+
dependency graph.
3338

34-
## Status
39+
The actual build logic is abstracted away into pluggable engines that may orchestrate other tools,
40+
like Docker, to create the final image, or whatever the selected namespace's configured engine
41+
produces.
3542

36-
* Stable for a while now and used in production
37-
* Monthly update cycle for all reference images
43+
Kubler is extendable, users may provide their own commands and/or build engines in a maintainable
44+
way. As both are just plain old Bash scripts this is usually a simple* and straight forward process
45+
with almost no limitations.
3846

39-
## Features
47+
`{ font-size: 2px; }` * Additional rates of blood, sweat and tears may apply when implementing a new engine
4048

41-
* Decoupled build logic
42-
* Maintain multiple image stacks with differing build engines
43-
* Generic [root-fs][bob-core] build script to quickly bootstrap a [Gentoo][] based build container
44-
* Utilizes Gentoo's [binary package][] features for quick rebuilds
45-
* Simple hook system allows for full control of the build process while retaining modularity
46-
* Generic image and builder dependencies that can be utilized by build engines
47-
* Automated image [documentation][nginx-packages] and history when using a CVS
49+
## Requirements
4850

49-
### Docker Features
51+
#### Kubler
5052

51-
* Essentially enables [nested](https://github.com/docker/docker/issues/7115) docker builds
52-
* Everything happens in docker containers except for some bash glue on the build host
53-
* Glibc, Musl and Uclibc based build containers, each with complete toolchain out of the box
54-
* Tiny static busybox-musl root image (~1.2mb), FROM scratch is fine too
55-
* Shared layer support for final images, images are not squashed and can depend on other images
56-
* [s6][] instead of [OpenRC][] as default supervisor (small footprint (<1mb) and proper docker SIGTERM handling),
57-
optional of course
58-
* Reference images are available on [docker hub][kubler-docker]
59-
* Push built image stack(s) to a public or private docker registry
53+
* Bash version 4.2+, using 4.4+ is highly recommended due to bugs in previous versions.
6054

61-
### Requirements
55+
Optional:
56+
57+
* GPG for download verification
58+
59+
#### Docker Build Engine
6260

63-
* Bash 4.x
6461
* Working Docker setup
62+
* GIT
63+
* jq to parse Docker json output
6564

66-
Optional:
65+
## Installation
6766

68-
* GPG for download verification
67+
#### On Gentoo
6968

70-
Kubler has been tested on Gentoo, CoreOS and macOS. It should run on all Linux distributions.
69+
An ebuild can be found at https://github.com/edannenberg/kubler-overlay/
7170

72-
## How much do I save?
71+
Add the overlay and install as usual:
7372

74-
* Quite a bit, the Nginx Docker image, for example, clocks in at ~17MB, compared to >1GB for a full Gentoo version
75-
or ~300MB for a similiar Ubuntu version
73+
emerge -av kubler
7674

77-
## Quick Start
75+
#### Manual Installation
7876

79-
$ git clone https://github.com/edannenberg/kubler.git
77+
Kubler has been tested on Gentoo, CoreOS and macOS. It should run on all Linux distributions.
8078

81-
Kubler needs a `working-dir` to operate from, much like `git` needs to be called from inside a git repo for most of its
82-
functionality. You may also call Kubler from any sub directory and it will detect the proper path. The Kubler git repo
83-
comes with an example image stack, let's build a provided `glibc` image:
79+
1. Clone the repo or download/extract the release archive to a location of your choice, i.e.
8480

85-
$ cd kubler/
86-
$ ./kubler.sh build kubler/glibc
81+
$ cd ~/tools/
82+
$ curl -L https://github.com/edannenberg/kubler/archive/master.tar.gz | tar xz
8783

88-
This will build a `kubler/busybox` and `kubler/glibc` image. You also get a glibc and musl based build container for
89-
free, which you can utilize for your own images.
84+
2. Add `kubler.sh` to your path
9085

91-
* You may add `kubler.sh` to your `PATH`, one-liner: `export PATH="${PATH}:/path/to/kubler/bin"`
92-
* If you don't have GPG available use `build -s ..` to skip verification of downloaded files (SHA512 is still checked)
93-
* The directories in `./dock/kubler/images/` contain image specific documentation
86+
If you are unsure add the following at the end of your `~/.bashrc` file, don't forget to adjust the
87+
path for each line accordingly:
9488

95-
Note: If you get a 404 error on downloading a Gentoo stage3 tar ball try running `kubler update` to resolve the issue.
96-
The Gentoo servers only keep those files for a few weeks.
89+
export PATH="${PATH}:/path/to/kubler/bin"
90+
# optional but highly recommended, adds bash completion support for all kubler commands
91+
source /path/to/kubler/lib/kubler-completion.bash
9792

98-
The first run will take quite a bit of time, don't worry, once the build containers and binary package cache
99-
are seeded future runs will be much faster.
93+
Note: You will need to open a new shell for this to take effect, if this fails on a Linux SystemD
94+
host re-logging might be required instead.
10095

101-
## Creating a new namespace
96+
#### Uninstall
10297

103-
Images are kept in a `namespace` directory in `--working-dir`. You may have any number of namespaces. A helper is
104-
provided to take care of the boiler plate for you:
98+
1. Remove any build artifacts and Docker images created by Kubler:
10599

106-
```
107-
$ cd kubler/
108-
$ ./kubler.sh new namespace testing
109-
110-
--> Who maintains the new namespace?
111-
Name (John Doe): My Name
112-
113-
--> What type of images would you like to build?
114-
Engine (docker):
100+
$ kubler clean -N
115101

116-
--> Successfully added "testing" namespace at ./dock/testing
102+
2. Delete the two entries from `~/.bashrc` you possibly added during manual installation
117103

118-
$ tree dock/testing/
119-
dock/testing/
120-
|-- .gitignore
121-
|-- kubler.conf
122-
.-- README.md
123-
```
104+
3. Delete any namespace dirs and configured `KUBLER_DATA_DIR` (default is `~/.kubler/`) you had in
105+
use, this may require su permissions.
124106

125-
You are now ready to work on your shiny new image stack.
107+
## Quick Start
126108

127-
## Adding Docker images
109+
#### The Basics
128110

129-
Let's create a [Figlet](http://www.figlet.org/) test image in our new namespace. If you chose a more
130-
sensible namespace name above replace `testing` accordingly:
111+
To get a quick overview/reminder of available commands/options run:
131112

132-
```
133-
$ ./kubler.sh new image testing/figlet
113+
$ kubler --help
134114

135-
--> Extend an existing image? Fully qualified image id (i.e. kubler/busybox) if yes or scratch
136-
Parent Image (scratch): kubler/glibc
115+
To view details for specific command:
137116

138-
--> Successfully added testing/figlet image at ./dock/testing/images/figlet
139-
```
117+
$ kubler build -h
140118

141-
We used `kubler/glibc` as parent image, or what you probably know as `FROM` in your `Dockerfiles`.
142-
The namespace now looks like this:
143-
144-
```
145-
$ tree dock/testing/
146-
dock/testing/
147-
|-- kubler.conf
148-
|-- images
149-
|   .-- figlet
150-
|   |-- build.conf
151-
|   |-- build.sh
152-
|   |-- Dockerfile.template
153-
|   .-- README.md
154-
.-- README.md
155-
```
119+
Almost all of Kubler's commands will need to be run from a `--working-dir`, if the option is
120+
omitted the current working dir of the executing shell is used. It functions much like Git in that
121+
regard, executing any Kubler command from a sub directory of a valid working dir will also work as
122+
expected.
156123

157-
Edit the new image's build script located at `./dock/testing/images/figlet/build.sh` and add `app-misc/figlet` to the
158-
`_packages` variable:
124+
A `--working-dir` is considered valid if it has a `kubler.conf` file and either an `images/` dir or
125+
one ore more namespace dirs, which are just a collection of images.
159126

160-
```
161-
_packages="app-misc/figlet"
162-
```
127+
#### Setup A New Namespace
163128

164-
When it's time to build this will instruct the build container in the *first build phase* to install the given package(s)
165-
from Gentoo's package tree at an empty directory. It's content is then exported to the host as a `rootfs.tar` file.
166-
In the *second build phase* a normal Docker build is started and the `rootfs.tar` file is added to the final image.
129+
First switch to a directory where you would like to store your Kubler managed images or namespaces:
167130

168-
See the 'how does it work' section below for more details on the build process. Also make sure to read the comments
169-
in `build.sh`. But let's build the darn thing already:
131+
$ cd ~/workspace
170132

171-
```
172-
$ ./kubler.sh build testing
173-
```
133+
Then use the `new` command to take care of the boiler plate for you, choose `single` as namespace
134+
type when asked:
174135

175-
Once that finishes we are ready to take the image for a test drive:
136+
$ kubler new namespace mytest
137+
$ cd mytest
176138

177-
```
178-
$ docker images | grep /figlet
179-
$ docker run -it --rm kubler/figlet figlet kubler sends his regards
180-
```
139+
### Hello Image
140+
141+
To create a new image in the current working dir:
142+
143+
$ kubler new image mytest/figlet
144+
145+
#TODO: finish docs
181146

182147
Some useful options for while working on an image:
183148

@@ -245,6 +210,18 @@ this preserves exact build state
245210
Build container names generally start with `*/bob`, when a new build container state is committed the current image
246211
name gets appended. For example `kubler/bob-openssl` refers to the container used to build the `kubler/openssl` image.
247212

213+
## Other Resources
214+
215+
* An excellent blog post, written by [@berney][], can be found at https://www.elttam.com.au/blog/kubler/
216+
217+
## Discord Community
218+
219+
For questions or chatting with other users you may join our Discord server at:
220+
221+
https://discord.gg/rH9R7bc
222+
223+
You just need a username, email verification with Discord is not required.
224+
248225
## Thanks
249226

250227
[@wking][] for his [gentoo-docker][] repo which served as an excellent starting point

kubler.conf

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,59 @@
1-
AUTHOR="${AUTHOR:-Erik Dannenberg <[email protected]>}"
2-
# Global tag (a.k.a version) for all images
3-
IMAGE_TAG="${IMAGE_TAG:-20181130}"
4-
# Cheeky example that always sets the current date:
5-
#IMAGE_TAG="${IMAGE_TAG:-$(date +%Y%m%d)}"
6-
7-
# Portage snapshot date that is used to bootstrap the portage container
8-
PORTAGE_DATE="${PORTAGE_DATE:-latest}"
1+
# The first config file read by Kubler. System wide settings, users may override via KUBLER_DATA_DIR/kubler.conf or
2+
# current --working-dir.
3+
4+
# Image version, ideally set via user config so it's shared by all --working-dirs of current user
5+
#IMAGE_TAG='20190123'
6+
# Default maintainer, override via namespace kubler.conf
7+
AUTHOR='Erik Dannenberg <[email protected]>'
8+
9+
# Kubler's runtime data dir, needs to be writable by the current user
10+
#KUBLER_DATA_DIR="${HOME}/.kubler}"
11+
# Gentoo's stage3 and portage files download location
12+
#KUBLER_DOWNLOAD_DIR="${KUBLER_DATA_DIR}/downloads"
13+
# Gentoo's build related downloads, like source code, patches, etc
14+
#KUBLER_DISTFILES_DIR="${KUBLER_DATA_DIR}/distfiles"
15+
# Gentoo's binary package cache location
16+
#KUBLER_PACKAGES_DIR="${KUBLER_DATA_DIR}/packages"
17+
18+
# Ouput related config
19+
# Disable compact output, effectively always passes -v to all commands
20+
#KUBLER_VERBOSE='false'
21+
# If true and compact output is enabled send output to log file instead of /dev/null
22+
#KUBLER_CMD_LOG='true'
23+
# Shall we ring the terminal bell on error?
24+
#KUBLER_BELL_ON_ERROR='true'
25+
# Disabling this only works when set as ENV before starting Kubler
26+
#KUBLER_COLORS='true'
27+
28+
# Update the portage container via git. Not recommended as it can be quite slow due to the amount of upstream changes.
29+
#KUBLER_PORTAGE_GIT='false'
30+
# Not recommended unless you are building your image stack from scratch and with your own stage3 build containers
31+
#KUBLER_DISABLE_KUBLER_NS='false'
32+
# Effectively always enables -s for the build command
33+
#KUBLER_DISABLE_GPG='false'
34+
35+
# Portage snapshot date that is used to bootstrap the portage container, 'latest' is highly recommended
36+
#PORTAGE_DATE='latest'
937
# Download location for stage3 and Portage files, use whitespace to set multiple servers
1038
# You may visit https://www.gentoo.org/downloads/mirrors/ and pick a http or ftp url near your physical location
11-
MIRROR="${MIRROR:-http://distfiles.gentoo.org/}"
12-
13-
DOWNLOAD_PATH="${DOWNLOAD_PATH:-${_KUBLER_DIR}/tmp/downloads}"
39+
MIRROR='http://distfiles.gentoo.org/'
1440

1541
# You can also define these per namespace conf
16-
BUILD_ENGINE="${BUILD_ENGINE:-docker}"
17-
DEFAULT_BUILDER="${DEFAULT_BUILDER:-kubler/bob}"
42+
BUILD_ENGINE='docker'
43+
DEFAULT_BUILDER='kubler/bob'
1844

1945
# Variables starting with BOB_ are exported as ENV to all build containers
2046

2147
# init Portage's make.conf defaults
2248

23-
BOB_GENTOO_MIRRORS="${BOB_GENTOO_MIRRORS:-${MIRROR}}"
49+
BOB_GENTOO_MIRRORS="${MIRROR}"
2450

25-
BOB_FEATURES="${BOB_FEATURES:-parallel-fetch nodoc noinfo noman binpkg-multi-instance}"
26-
BOB_EMERGE_DEFAULT_OPTS="${BOB_EMERGE_DEFAULT_OPTS:--b -k --binpkg-respect-use=y}"
51+
BOB_FEATURES='-parallel-fetch nodoc noinfo noman binpkg-multi-instance'
52+
BOB_EMERGE_DEFAULT_OPTS='-b -k --binpkg-respect-use=y'
2753

2854
# Timezone for build containers
29-
BOB_TIMEZONE="${BOB_TIMEZONE:-UTC}"
55+
BOB_TIMEZONE='UTC'
3056

3157
# Options passed on to the make jobs launched from Portage
3258
# -jX = number of cpu cores used for compiling, rule of thumb: amount_of_cores+1, i.e. -j9
33-
BOB_MAKEOPTS="${BOB_MAKEOPTS:--j9}"
59+
BOB_MAKEOPTS='-j9'

0 commit comments

Comments
 (0)