Container Images and Build file

Container base images and build files govern the fundamentals of how a container instance from a particular image would behave. Ensuring that you are using proper base images and appropriate build files can be very important for building your containerized infrastructure. Below are some of the recommendations that you should follow for container base images and build files to ensure that your containerized infrastructure is secure.

Create a user for the container

Currently, mapping the container’s root user to a non-root user on the host is not supported by Docker. The support for user namespace would be provided in future releases. This creates a serious user isolation issue. It is thus highly recommended to ensure that there is a non-root user created for the container and the container is run using that user.

As we can see below that by default Centos docker image has user field as blank that means by default container will get root user during runtime which should be avoided.

$ docker inspect centos
[
{
    "Id": "e9fa5d3a0d0e19519e66af2dd8ad6903a7288de0e995b6eafbcb38aebf2b606d",
    "RepoTags": [
        "centos:latest"
    ],
    "RepoDigests": [],
    "Parent": "c9853740aa059d078b868c4a91a069a0975fb2652e94cc1e237ef9b961afa572",
    "Comment": "",
    "Created": "2015-10-13T23:29:04.138328589Z",
    "Container": "eaa200e2e187340f0707085b9b4eab5658b13fd190af68c71a60f6283578172f",
    "ContainerConfig": {
        "Hostname": "7aa5783a47d5",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"/bin/bash\"]"
        ],
        "Image": "4234bfdd88f8ed2bc4607bd2ebba2d41d61e2693ad0d184e7b05e1b57f8b8b33",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": {
            "License": "GPLv2",
            "Vendor": "CentOS"
        }
    },
    "DockerVersion": "1.8.2",
    "Author": "The CentOS Project \u003ccloud-ops@centos.org\u003e",
    "Config": {
        "Hostname": "7aa5783a47d5",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
                "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/bash"
        ],
        "Image": "4234bfdd88f8ed2bc4607bd2ebba2d41d61e2693ad0d184e7b05e1b57f8b8b33",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": {
            "License": "GPLv2",
            "Vendor": "CentOS"
        }
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 172289754,
    "GraphDriver": {
        "Name": "aufs",
        "Data": null
    }
}
]

While building the docker image we can provide the “test” user the less-privileged user in the Dockerfile as shown below;

$ cd
$ mkdir test-container
$ cd test-container/
$ cat Dockerfile
FROM centos:latest
RUN useradd test
USER test

root@ubuntu:~/test-container# docker build -t vkohli .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos:latest
 ---> e9fa5d3a0d0e
Step 2 : RUN useradd test
 ---> Running in 0c726d186658
 ---> 12041ebdfd3f
Removing intermediate container 0c726d186658
Step 3 : USER test
 ---> Running in 86c5e0599c72
 ---> af4ba8a0fec5
Removing intermediate container 86c5e0599c72
Successfully built af4ba8a0fec5

$ docker images | grep vkohli
vkohli              latest              af4ba8a0fec5        9 seconds ago       172.6 MB

When we start the docker container we can see that it gets “test” user and docker inspect command also shows the default user as “test”;

$ docker run -it vkohli /bin/bash
[test@2ff11ee54c5f /]$ whoami
test
[test@2ff11ee54c5f /]$ exit

$ docker inspect vkohli
[
{
    "Id": "af4ba8a0fec558d68b4873e2a1a6d8a5ca05797e0bfbab0772bcedced15683ea",
    "RepoTags": [
        "vkohli:latest"
    ],
    "RepoDigests": [],
    "Parent": "12041ebdfd3f38df3397a8961f82c225bddc56588e348761d3e252eec868d129",
    "Comment": "",
    "Created": "2015-11-27T14:10:49.206969614Z",
    "Container": "86c5e0599c72285983f3c5511fdec940f70cde171f1bfb53fab08854fe6d7b12",
    "ContainerConfig": {
        "Hostname": "7aa5783a47d5",
        "Domainname": "",
        "User": "test",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) USER [test]"
        ],
        "Image": "12041ebdfd3f38df3397a8961f82c225bddc56588e348761d3e252eec868d129",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": [],
        "Labels": {
            "License": "GPLv2",
            "Vendor": "CentOS"
        }
    },
    "DockerVersion": "1.9.1",
    "Author": "",
    "Config": {
        "Hostname": "7aa5783a47d5",
        "Domainname": "",
        "User": "test",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": [
            "/bin/bash"
        ],
        "Image": "12041ebdfd3f38df3397a8961f82c225bddc56588e348761d3e252eec868d129",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": [],
        "Labels": {
            "License": "GPLv2",
            "Vendor": "CentOS"
        }
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 172585404,
    "GraphDriver": {
        "Name": "aufs",
        "Data": null
    }
}
]