Build framework to produce minimal root file systems based on Gentoo. It's primarily intended for maintaining LXC base image stacks, but can probably fairly easy (ab)used for other use cases involving a custom root fs, cross compiling comes to mind.
Currently supported build engines:
Planned support:
PR are always welcome. ;)
- Containers should only contain the bare minimum to run
- Separate build and runtime dependencies
- Only deploy runtime dependencies
- Maximum flexibility while assembling the rootfs, but with minimal effort
- Keep things maintainable as the stack grows
- Decoupled build logic
- Maintain multiple image stacks with differing build engines
- Generic root-fs build script to quickly bootstrap a build container
- Utilizes Gentoo's binary package features for quick rebuilds
- Simple hook system allows for full control of the build process while retaining modularity
- Generic image and builder dependencies that can be utilized by build engines
- Automated image documentation and history when using a CVS
- Essentially enables nested docker builds
- Everything happens in docker containers except for some bash glue on the build host
- Tiny static busybox-uclibc root image (~1.2mb), FROM scratch is fine too
- Shared layer support for final images, images are not squashed and can depend on other images
- s6 instead of OpenRC as default supervisor (small footprint (<1mb) and proper docker SIGTERM handling)
- Reference images are available on docker.io
- Push image stack(s) to a public or private docker registry
- Quite a bit, the Nginx Docker image, for example, clocks in at ~20MB, compared to >1GB for a full Gentoo version or ~300MB for a similiar Ubuntu version
$ git clone https://github.com/edannenberg/gentoo-bb.git
$ cd gentoo-bb
$ ./build.sh
- If you don't have GPG available use
-s
to skip verification of downloaded files - Check the directories in
dock/gentoobb/images/
for image specific documentation bin/
contains a few scripts to start/stop container chains
$ cd gentoo-bb/
$ mkdir -p dock/mynamespace/images/
$ cat <<END > dock/mynamespace/build.conf
AUTHOR="My Name <my@mail.org>"
DEF_BUILD_CONTAINER="gentoobb/bob"
CONTAINER_ENGINE="docker"
END
You are now ready to work on your shiny new image stack. The build.conf
above defines the gentoobb/bob
image
as default build container
. You may set any build container from other namespaces or roll your own of course.
For most tasks the gentoobb/bob
image should do just fine though.
Let's setup a test image in our new namespace:
$ cd gentoo-bb/
$ mkdir -p dock/mynamespace/images/figlet
$ cat <<END > dock/mynamespace/images/figlet/Buildconfig.sh
PACKAGES="app-misc/figlet"
END
$ cat <<END > dock/mynamespace/images/figlet/Dockerfile.template
FROM gentoobb/glibc
ADD rootfs.tar /
CMD ["figlet", "gentoo-bb"]
END
$ ./build.sh build mynamespace
Pretty straight forward, pass a Gentoo package atom
to be installed in the first build phase and setup a Dockerfile
that
assembles the final image. Again we use an image from another namespace as base for the final image. (gentoobb/glibc)
See the 'how does it work' section below for more details on the build process.
The first run will take quite a bit of time, don't worry, once the build containers and binary package cache are seeded future runs will be much faster. Let's spin up the new image:
$ docker images | grep /figlet
$ docker run -it --rm mynamespace/figlet
- All images must be located in
dock/<namespace>/images/
, directory name = image name Dockerfile.template
andBuildconfig.sh
are the only required filesbuild.sh
will pick up the image on the next run
Some useful options for build.sh
while working on an image:
Start an interactive build container, same as used to create the rootfs.tar:
$ ./bin/bob-interactive.sh mynamespace/myimage
Force rebuild of myimage and all images it depends on:
$ ./build.sh -f build mynamespace/myimage
Same as above, but also rebuild all rootfs.tar files:
$ ./build.sh -F build mynamespace/myimage
Only rebuild myimage1 and myimage2, ignore images they depend on:
$ ./build.sh -nF build mynamespace/{myimage1,myimage2}
First check for a new release by running:
$ ./build.sh update
If a new release was found simply rebuild the stack by running:
$ ./build.sh -F
- Minor things might break, Oracle downloads, for example, may not work. You can always download them manually to
tmp/distfiles
.
build.sh
reads global defaults frombuild.conf
- iterates over
dock/
- reads
build.conf
in eachdock/<namespace>/
directory and imports definedCONTAINER_ENGINE
frominc/engine/
- generates build order by iterating over
dock/<namespace>/images/
- executes
build_core()
for each required engine to bootstrap the initial build container - executes
build_builder()
for any other required build containers indock/<namespace>/builder/<repo>
- executes
build_image()
to build eachdock/<namespace>/images/<repo>
Each implementation is allowed to only implement parts of the build process, if no build containers are required thats fine too.
build_core()
builds a clean stage 3 image with portage snapshot and helper files from./bob-core/
build_image()
mounts eachdock/<namespace>/images/<repo>
directory into a fresh build container as/config
- executes
build-root.sh
inside build container build-root.sh
readsBuildconfig.sh
from the mounted/config
directory- if
configure_bob()
hook is defined inBuildconfig.sh
, execute it package.installed
file is generated which is used by depending images aspackage.provided
- if
configure_rootfs_build()
hook is defined inBuildconfig.sh
, execute it PACKAGES
defined inBuildconfig.sh
are installed at a custom empty root directory- if
finish_rootfs_build()
hook is defined inBuildconfig.sh
, execute it - resulting
rootfs.tar
is placed in/config
, end of first build phase - used build container gets committed as a new builder image which will be used by other builds depending on this image, this preserves exact build state
build.sh
then starts a normal docker build that usesrootfs.tar
to create the final image
Build container names generally start with gentoobb/bob
, when a new build container state is committed the current image name gets appended.
For example gentoobb/bob-openssl
refers to the container used to build the gentoobb/openssl
image.
@wking for his gentoo-docker repo which served as an excellent starting point
@jbergstroem for all his contributions and feedback to this project <3