Why?

The other day I was helping some colleagues to develop a container application for Cisco APIC. To build a stateful application you must follow some specific steps and build it according to the APIC specification. If it sounds complex, you are right, is a bit complex.

When reviewing the components needed, I saw, it is need to use a special docker image, which has all the required packages. The downside, the packages were old, for example python2 was used.

As a good engineer I started to look for the dockerfile to have an updated image, but no dockerfile was avalaible, who knows why?. Then I tried to run the image, see what it is inside, but the image was crashing, good.

docker history

I remembered that you could see how a docker layer was built using docker history. So I tried and this was the result:

docker
╰─ docker history aci_appcenter_docker_image
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
62a3eb9c3646   5 years ago   /bin/sh -c apk --no-cache add          bash …   606MB
54ed6729adfb   5 years ago   /bin/sh -c #(nop) COPY dir:ff8259f4217102756…   81.1MB
d77e3599de56   5 years ago   /bin/sh -c mkdir /usr/local/cobrafiles          0B
ec521dc7384d   5 years ago   /bin/sh -c #(nop) MAINTAINER gursheno@cisco.…   0B
5339b29ce749   5 years ago   /bin/sh -c #(nop) ADD file:d6ee3ba7a4d59b161…   4.8MB

You can see on line 3, the important part is missing, where I can see how the image is build.

is there a better way?, yep, docker provides the option to use the --no-trunc command which can give us more infomation.

docker
╰─ docker history aci_appcenter_docker_image --no-trunc
IMAGE                                                                     CREATED       CREATED BY                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            SIZE      COMMENT
sha256:62a3eb9c364683751a2fc84227286a7d121a87efca5f043e299a6de62b2846a1   5 years ago   /bin/sh -c apk --no-cache add          bash                        python                        python-dev                        py-pip                        py-flask          py-requests=2.9.1-r0                        ca-certificates          openssl-dev          openssl          gcc                        libffi-dev                 build-base                       && update-ca-certificates                       && pip install --use-wheel pyopenssl                       && python /usr/local/cobrafiles/ez_setup.py                       && easy_install -Z /usr/local/cobrafiles/acicobra-2.2_0.184-py2.7.egg                       && easy_install -Z /usr/local/cobrafiles/acimodel-2.2_0.184-py2.7.egg   606MB
sha256:54ed6729adfbb5e0816cdd0d16153032a093d8a203390804e9544989f53e0c72   5 years ago   /bin/sh -c #(nop) COPY dir:ff8259f4217102756455051f7d44d6fd73b05936a199b32b9f5dab90f4e73670 in /usr/local/cobrafiles                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  81.1MB
sha256:d77e3599de5642e16d39a0c9455c7e850ee80ed700cd76cce6ba5deafb0dd616   5 years ago   /bin/sh -c mkdir /usr/local/cobrafiles                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                0B
sha256:ec521dc7384d86f97585c6b4b65a76aef37671e456ec303505bdb3c108b1dee4   5 years ago   /bin/sh -c #(nop) MAINTAINER gursheno@cisco.com                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       0B
sha256:5339b29ce7493a9dc881571d439e6a2cdc4ba5af3e1874c232296d4e6610b9c8   5 years ago   /bin/sh -c #(nop) ADD file:d6ee3ba7a4d59b161917082cc7242c660c61bb3f3cc1549c7e2dfff2b0de7104 in /                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      4.8MB

We can see now the commands used but still not very user friendly.

dfimage

So I looked in the internet and found this handy image which can give us the information we want. Check it out here

To use it you can create an alias

docker
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"

And run dfimage specifying the name and tag of the image you want to reverse engineer.

docker
╰─ dfimage -sV=1.36 aci_appcenter_docker_image:latest

Unable to find image 'alpine/dfimage:latest' locally
latest: Pulling from alpine/dfimage
df20fa9351a1: Pull complete
820dbffe2156: Pull complete
Digest: sha256:4a271e763d51b7f3cca72eac9bf508502c032665dde0e4c8d5fcf6376600f64a
Status: Downloaded newer image for alpine/dfimage:latest
Analyzing aci_appcenter_docker_image:latest
Docker Version: 1.8.2
GraphDriver: overlay2
Environment Variables
|PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Image user
|User is root

Potential secrets:
|Found match etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub Possible public key \.pub$ 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
|Found match etc/apk/keys/alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub Possible public key \.pub$ 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
|Found match etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub Possible public key \.pub$ 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
|Found match etc/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub Possible public key \.pub$ 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
|Found match etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub Possible public key \.pub$ 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
|Found match etc/udhcpd.conf DHCP server configs dhcpd[^ ]*.conf 1290a865bff43de688fdf7f813e14341692cde9719576c82ed5760bbbccbda36/layer.tar
Dockerfile:
MAINTAINER gursheno@cisco.com
RUN mkdir /usr/local/cobrafiles
COPY dir:ff8259f4217102756455051f7d44d6fd73b05936a199b32b9f5dab90f4e73670 in /usr/local/cobrafiles
    usr/
    usr/local/
    usr/local/cobrafiles/
    usr/local/cobrafiles/acicobra-2.2_0.184-py2.7.egg
    usr/local/cobrafiles/acimodel-2.2_0.184-py2.7.egg
    usr/local/cobrafiles/ez_setup.py

RUN apk --no-cache add bash python python-dev py-pip py-flask py-requests=2.9.1-r0 ca-certificates openssl-dev openssl gcc libffi-dev build-base  \
    && update-ca-certificates  \
    && pip install --use-wheel pyopenssl  \
    && python /usr/local/cobrafiles/ez_setup.py  \
    && easy_install -Z /usr/local/cobrafiles/acicobra-2.2_0.184-py2.7.egg  \
    && easy_install -Z /usr/local/cobrafiles/acimodel-2.2_0.184-py2.7.egg

From the output (lines 28 to the end) you can see we get what we wanted, the packages installed to build this application and also the SDKs installed.

Also on the messages of the potential secrets (line 19) we can see an alpine image was used as a base image.

From this point I was able to create my dockerfile and build my updated image for the APIC container app I was helping.