Docker FROM scratch

Docker is a framework which makes it easy to wrap linux applications in “containers” – a sort chroot’d jail but with tools to take away the pain of setting up dependencies and also providing tools to help automate setting up dependencies between those containers.

The Docker Hub provides a bunch of pre-defined containers from major projects like Ubuntu, mysql, Redis, nginx, wordpress, postgres and java. It’s also a central store (like github, but for Docker) of publicly created and licensed Docker containers.

What’s the simplest quickest way to start? Well there is a special base container called SCRATCH, which is used in the Docker official hello world container. A container based on SCRATCH has nothing in it, so whatever you add has to be fully self sufficient. The Docker official hello world does this with some assembly code compiled by nasm which certainly covers the angle of a stand-alone executable but I think is arguably more complex than a statically compiled hello world – so here we go:

helloworld

Doesn’t really need much in the way of an explanation, but I’m going to write it in c and I’m including a bit of code to grab an environment variable to show how these can be passed into a Docker container to configure the way a container operates.

Here’s the helloworld c code:

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
  // Vars
  char *envVar;

  // do it
  printf("Hello From Brad\n");

  // Check for special environment variable, print it present
  envVar = getenv("BJDTEST");
  if ( envVar == NULL ) {
    printf("No special environment variable set - set BJDTEST to see this work\n");
  }
  else {
    printf("Special environment BJDTEST set to [%s]\n", envVar);
  }

  return 0;
}

That’s built statically the usual way – with this bit of Makefile:

helloworld: helloworld.c
    gcc -static -o helloworld helloworld.c

Note that without the static build the Docker container will fail because the linked libraries will not exist inside the Docker container.

The simplest of containers – FROM scratch

To defined a docker container you write a Dockerfile – this is just about as simple as it gets:

FROM scratch
COPY helloworld /
CMD ["/helloworld"]

Basically, start with the no-op scratch container, copy our statically compiled binary to a known location and run it.

Building this with docker is very fast, because there’s not much there and scratch is very small. Here’s another Makefile snipped:

docker: helloworld
      docker build --rm -t bradhello .

And here’s how that looks:

$ make docker
docker build --rm -t bradhello .
Sending build context to Docker daemon 885.2 kB
Sending build context to Docker daemon 
Step 0 : FROM scratch
 ---> 
Step 1 : COPY helloworld /
 ---> Using cache
 ---> a4a757585183
Step 2 : CMD /helloworld
 ---> Using cache
 ---> b32df200f4ed
Successfully built b32df200f4ed

And here’s how that runs, deleting the container after running otherwise it will leave an empty container waiting around to be removed:

$ docker run --rm=true bradhello
Hello From Brad
No special environment variable set - set BJDTEST to see this work

And finally, as you can see above my environment variable was not set. But I can do that – either a bunch of variables defined in a file and used with –env-file=<filename> or individually with –env=”foo=bar”.

$ docker run --rm=true --env="BJDTEST=value for demo" bradhello
Hello From Brad
Special environment BJDTEST set to [value for demo]

 

One Reply to “Docker FROM scratch”

Leave a Reply

Your email address will not be published. Required fields are marked *