Dockerception: Docker building dockers – keeping them small
github.com
github.com
You can bind-mount in a directory for your build dockerfile and output to that directory and then use that as the input to the next dockerfile without having to rely on the build dockerfile creating a valid tarball containing a dockerfile etc.
The difference isn't huge, but I think it's good to uncouple the build/run-image creation logic a little more.
Doing so also lets you more easily work on the dockerfiles independently and debug certain issues (e.g. you can compile the binary outside of docker, put it in the run one, make sure things are okay).
As for his bonus points: You can avoid using busybox by compiling your go program with: "CGO_ENABLED=0 go build -a -installsuffix cgo my-program.go" (assuming go 1.4).
The output of this is a static binary which you can add to an empty docker container. The way to do that would be to have a dockerfile of `FROM empty; COPY ./my-program /my-program; ENTRYPOINT ["/my-program"]` with newlines replacing each semicolon.
It will end up somewhat smaller than the busybox image, but the savings aren't nearly as dramatic as you might expect. If you do tls/ssl or rely on any exec calls, you'll also probably be better off just using busybox for the certificates and basic binaries being present.
http://www.slideshare.net/KuanYenHeng/docker-on-a-diet
If you need a tiny base image with a decent package index, try Alpine Linux.
I am certain there are great use-cases for this, but it seems the discussions imply that "change your FROM, save a ton of disk space" but there is more to that story.
The requests would leave the machine, but it seemed none of the handlers were firing with the result. I thought, ok, perhaps I've made a configuration mistake or the target website is acting funny.
After 3 hours of inserting every kind of debugging print and log statement I could think of, I decided to sanity check the setup using debian:wheezy. As my post above implied, it worked immediately and flawlessly.
Thus: it may work great for you, but ensure their libraries and binaries are a good fit for your situation.
I did see quite a few other comments discussing Python, Ruby and other not-easily-statically-compilable stacks may not be a good fit for the system the article was proposing, so this may not strictly be Alpine's fault. It's just when I see a discussion of the great savings from using Alpine, I feel it's important to remind folks there is no free lunch.
Some standardisation in this area would be nice, but the problem can be solved rather trivially by using a separate container with all the tools for the build process, and placing the build product into a lean production image. This process is easy to automate/script, and I don't feel that there is much gain from having some encompassing spec or standard that has to consider all the edge cases and is more complex than necessary as a result.
Docker is a compiler (docker build), Dockerfiles are source code, and Docker images are binary artifacts. We already have tools that manage this for us: make, cmake, nmake, rake, scons, etc.
People need to get over their fear of build tools and use them. This is exactly the kind of problem they solve. Make IS the standard.
[0] https://github.com/crosbymichael/dockerui [1] https://github.com/CenturyLinkLabs/golang-builder
Is there any good way to bundle up, say, a Flask app on Gunicorn into a single, minimal-dependency executable? Or a Rails app? I haven't found any satisfactory solutions. There are projects that will compile python down, but that doesn't seem to cover the WSGI server part (gunicorn, etc).
You don't need to build a single executable for this approach to work. You could use something like buildroot to build your runtime docker image.
docker-nano was doing something to that effect, see for example nano/node.js: https://github.com/Docker-nano/Node.js
For Ruby, additionally "bundle install --standalone --path [..]" gets your far.
I'm going to use this in my projects from now on, would be great to do away with hundreds megabytes of layers.
I guess the downside is you lose some of the ability to find out where your final image came from, but that can easily be fixed with a well controlled build pipeline.
Make a folder with your app, identify and hardlink its dependencies into that folder, and stream the tar of that folder into Docker. No bash, no kernel, no /usr/bin, no binaries, libraries or files of any kind that you don't explicitly need.
It's a method that has been used for years in creating chroot environments, and it works for containers as well. It does require a bit more knowledge than `apt-get install`, however.