_ __ | |__ | | ___ __ _
| '_ \| '_ \| |/ _ \ / _` |
| |_) | | | | | (_) | (_| |
| .__/|_| |_|_|\___/ \__, |
|_| ...2017-12-12 |___/
A while back I did something which I've not heard about before, maybe it's such
a stupid idea that nobody else would consider it, but if that is the case, then
I've yet to hear it. It's about the way we're using Docker for building.
Now, building in docker is nothing new, but I think there's somthing cool in
the particular way we've set it up. Basically, we have a repository of docker
images containing our build environments. Every time a dependency is upgraded
or we're doing a change to the code requiring new or different tools, we make
a "golden image", the binary is then pushed to a central repository, and, this
is where it gets interesting: We update a file in our source-code, containing
the version number (tag) of the new image: When someone runs the build script,
it checks if an image in that version is locally available, if it is not, it
downloads and loads it into docker automatically, then it starts a container
with a user with the same UID/GID/Username as the user running the script, and
then starts the build-process proper.
Why this is the coolest thing since sliced bread:
1. Every dev (& buildserver) automatically, always, uses the same env.
2. Risk-free tinkering: Start container, try stuff, destroy or save.
3. No chance of build polluting host/relying on obscure details.
4. Not all devs need to understand how to setup the build env.
5. Time for building a build env. spent only by a single dev.
6. Old versions of the source-code, relying on older libs/compilers still work,
meaning that even if said libs vanish from the Internet, we can still build.
7. A very large decrease in "works on my machine" type errors.
8. A change in build-environment requires no action on build servers.
9. Developers can easily try the same code in different build-environments
by simply changing the tag in a single file.
A. Same developer/buildserver can build multiple versions of the software under
multiple versions of the build environment at the same time.
Here's how to do it (assumes some Bash and Docker knowledge):
Create a file called build_env_version in your project somewhere.
Add to it: BUILD_ENV_VERSION=something
Create a small script that sources that file, ensures that the image of that
tag exists on the machine (downloads and loads if not).
The script calls docker run with enough parameters to mount the source-code
into the container, and pass along enough information that a user of the same
permisisions can be created inside the container, it should pass along any
other parameters to the container, and the build script proper.
Now for the build environment itself:
Write a Dockerfile with whatever you need, and then add a script for entrypoint
which will take said variables, create a user with the right uid/gid/name, and
finally, execute the build script proper as that user..
Added bonus: Consider intercepting a special paramter (like --enter) and let
that spawn a bash shell inside the container, letting the developer work from
inside it, it makes debugging build-system stuff, easier and allows the dev
to make quick changes to the build environment itself. This is a very powerful
thing to be able to install/remove/change software inside an isolated
environment without risking having to spend hours reparing/getting back to last
known good state.
That's all, hopefully it'll be useful for someone.
- Yay, whales