About your images, security tips

28 Dec 2016 · Three minute read · on Gianluca's blog

News! Tech related notes are NOW published to ShippingBytes. See you there! I always felt this was not the right place for me to write consistently about tech and tools. So if you want to read more about that see you at the other side

Everything unnecessary in your system could be a very stupid vulnerability. We already spoke about this idea in the capability chapter and the same rule exists when we build an image. Having tiny images with only what our application needs to run is not just a goal in terms of distribution but also in terms of cost of maintenance and security. If you have some small experience with docker already you probably know the alpine image. It is build from the Alpine distribution and it’s only 5MB size, if your application can run inside it then this is a very good optimization that you can do. What about your binaries? Can your application run standalone? If the answer is yes you can think about a very very minimal image. scratch is usually used as a base for other images like debian and ubuntu but you can also use it to run your golang binary and let me show you something with our micro application. In the release page, there are a list of binaries already compiled and ready to be used. In this case we can download the linux_386 binary.

curl -SsL https://github.com/gianarb/micro/releases/download/1.0.0/micro_1.0.0_linux_386 > micro

And we know we can include this binary in the scratch image with this Dockerfile

FROM scratch

ADD ./micro /micro
EXPOSE 8000

CMD ["/micro"]
docker build -t micro-scratch .
docker run -p 8000:8000 micro-scratch

The expectation is an http application on port 8000 but the main difference is the size of the image, the old one from alpine is 12M the new one is 5M.

The scratch image is impossibile to use with all applications but if you have a binary you can remove a lot of unused overhead.

Another way to understand the status of your image is to scan it to detect security vulnerabilities or exposures. Docker Hub and Docker Cloud can do it for private images. This is a great feature to have in your pipeline to scan an image after a build.

CoreOS provides an open source project called clair to do the same in your environment.

It is an application in Golang that exposes a set of HTTP API to pull, push and analyse images. It downloads vulnerabilities from different sources like Debian Security Tracker or RedHat Security Data. Each vulnerability is stored in Postgres. Clair works like static analyzer, this means that it doesn’t need to run our container to scan it but it persists different checks directly into the filesystem of the image.

docker run -it -p 5000:5000 registry

With this command we are running a private registry to use as a source for the image to scan

docker pull gianarb/micro:1.0.0
docker tag gianarb/micro:1.0.0 localhost:5000/gianarb/micro:1.0.0
docker push localhost:5000/gianarb/micro:1.0.0

Now that we pushed in our private repo the micro image we can setup clair.

mkdir $HOME/clair-test/clair_config
cd $HOME/clair-test
curl -L https://raw.githubusercontent.com/coreos/clair/v1.2.2/config.example.yaml -o clair_config/config.yaml
curl -L https://raw.githubusercontent.com/coreos/clair/v1.2.2/docker-compose.yml -o docker-compose.yml

Modify $HOME/clair_config/config.yml and add the proper source postgresql://postgres:password@postgres:5432?sslmode=disable

Now you can run the following command to start postgres and clair:

docker-compose up

To make our test easier, we will use another CLI called hyperclair that is just a client to work with this application. If you are using Mac OS, you can follow the above commands, if you are in another OS you can find the correct url in the release page

curl -SSl https://github.com/wemanity-belgium/hyperclair/releases/download/0.5.2/hyperclair-darwin-386 > ~/hyperclair
chmod 755 ~/hyperclair

Now we have an executable in ~/hyperclair

~/hyperclair pull localhost:5000/gianarb/micro:1.0.0
~/hyperclair push localhost:5000/gianarb/micro:1.0.0
~/hyperclair analyze localhost:5000/gianarb/micro:1.0.0
~/hyperclair report localhost:5000/gianarb/micro:1.0.0

The generated report looks like this:

Hyperclair is just one of the implementations of clair, you can decide to use it or build your own implementation in your pipeline.

Something weird with this website? Let me know.