Skip to content

Compile your application in Docker, and ship it as an image. Without shipping the build.

Notifications You must be signed in to change notification settings

SamirTalwar/docker-compilation-images

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Docker Compilation Images

Compile your application in Docker, and ship your application as an image. Without shipping the build.

Note: This is very much a proof of concept—a hacky Ruby script that has little to no error-handling and hasn't really been tested much. Use at your own risk.

That said, if you do want to use it, you can of course run it as a a Docker image:

docker run \
    --rm \
    --volume=/var/run/docker.sock:/var/run/docker.sock:ro \
    --volume=$PWD:/app:ro \
    samirtalwar/docker-compilation-images \
    --tag=build=my-app-build
    --tag=my-app
    /app

Say you have an application. Here's one in Go.

package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}

For consistency between development and production, it's becoming more and more common to run such an application inside a Docker container. And for consistency between developer machines, as well as continuous integration, it's becoming popular to build it in one too.

Building this in Docker is simple. All we need is a Dockerfile:

FROM golang:onbuild

Seriously, that's it. The golang:onbuild image is configured to copy the source files in, build them and spit out an application contained inside the image at /usr/bin/app.

Now, here's the problem.

$ docker build --tag=app .
...
$ docker inspect -f '{{ .VirtualSize }}' app
746433139

Our final Docker image is over 700 MB, which makes pushing it around pretty heavy. It also has a massive surface area—a running container has, among other things, a compiler sitting inside it and the source code to our application. While I wouldn't suggest that you could easily yank the source code out of the container, if you did find your way onto my servers, I'm sure it'd be a nice bonus.

This is where compilation images come in.


Here's a Dockerfile that takes advantage of compilation images.

NAME build
FROM golang:onbuild

FROM busybox
WORKDIR /app
COPY build:/go/bin/app .
CMD ["./app"]

This is really two Dockerfiles stuck together, but with a twist: the later images can reference earlier ones. This means that you can build your application in Docker, then easily yank the final product out with a souped-up COPY directive and add it to a minimal image. Here, we're using busybox, which is about as tiny as you can get.

The last one can omit the name, as it's assumed to be the one we actually care about.

Our new size?

$ ./docker-build --tag=app .
...
$ docker inspect -f '{{ .VirtualSize }}' app
3400732

3 MB. Busybox (approximately 1 MB) plus our application binary. That's it. No fluff, less attack surface and I can push it to my registry in no time.


Thanks to @sheerun for the NAME and COPY syntax used in this project.

About

Compile your application in Docker, and ship it as an image. Without shipping the build.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published