_     _             
                        _ __ | |__ | | ___   __ _ 
                       | '_ \| '_ \| |/ _ \ / _` |
                       | |_) | | | | | (_) | (_| |
                       | .__/|_| |_|_|\___/ \__, |
                       |_|    ...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