Building a small docker image with a C executable
The problem with building an executable from a C program in Docker is that the image is extremely large. The way I chose to handle it for this experiment was to make a throwaway image to compile the C program, then copy that built executable into a much smaller container.
The C program for this proof-of-concept
This is, of course, the ubiquitous hello-world program:
#include <stdio.h>
int main() {
printf("Hello, world\n");
}The Dockerfile
FROM gcc:4.9 AS build
WORKDIR /app
COPY Hello.c .
RUN gcc -static -o myapp Hello.c
# Base image is an explicitly empty image.
# It has no shared object, it has no runtime libraries.
#
# Make sure you compile your binary with -static flags.
FROM alpine
WORKDIR /app
COPY --from=build /app/myapp /app/myapp
CMD ["/app/myapp"]Explanation:
- First block sets up the build environment, and calls it
build - The application is built here
- In theory I could strip the executable, but I haven’t bothered to
- The second block uses a miniscule base image
- It then copies the executable from the first image
- It then makes that executable the runable application
End result:
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest a92e11966d72 About a minute ago 5.11MB
<none> <none> cd28adb1bc19 About a minute ago 1.37GBAs you can see, the non-named image (cd28adb1bc19) is 1.37 GB as it contains a complete C development environment. But what we really want is a fraction of the size - only 5 MB.
Running docker commands
docker build -t hello .
docker run --rm helloProof it works!

Final notes
In theory this could be smaller:
# ls -ltrh
total 948K
-rw-r--r-- 1 root root 63 Aug 6 2017 Hello.c
-rwxr-xr-x 1 root root 942K Jan 19 18:29 myapp
# strip myapp
# ls -ltrh
total 736K
-rw-r--r-- 1 root root 63 Aug 6 2017 Hello.c
-rwxr-xr-x 1 root root 730K Jan 19 18:54 myappGaining that extra 212 KB is not worth it for my proof-of-concept, but your milage may vary.