Learn Docker:Fundamentals of Docker 19.x
上QQ阅读APP看书,第一时间看更新

Interactive image creation

The first way we can create a custom image is by interactively building a container. That is, we start with a base image that we want to use as a template and run a container of it interactively. Let's say that this is the Alpine image.

To interactively create an image follow along:

  1. The command to run the container would be as follows:
$ docker container run -it \
--name sample \
alpine:3.10 /bin/sh

The preceding command runs a container based on the alpine:3.10 image.

We run the container interactively with an attached teletypewriter (TTY) using the -it parameter, name it sample with the --name parameter, and—finally—run a shell inside the container using /bin/sh.

In the Terminal window where you run the preceding command, you should see something similar to this:

Unable to find image 'alpine:3.10' locally
3.10: Pulling from library/alpine
921b31ab772b: Pull complete
Digest: sha256:ca1c944a4f8486a153024d9965aafbe24f5723c1d5c02f4964c045a16d19dc54
Status: Downloaded newer image for alpine:3.10
/ #

By default, the alpine container does not have the ping tool installed. Let's assume we want to create a new custom image that has ping installed.

  1. Inside the container, we can then run the following command:
/ # apk update && apk add iputils

This uses the apk Alpine package manager to install the iputils library, of which ping is a part. The output of the preceding command should look approximately like this:

Installing ping on Alpine
  1. Now, we can indeed use ping, as the following code snippet shows:
Using ping from within the container
  1. Once we have finished our customization, we can quit the container by typing exit at the prompt.

If we now list all containers with the ls -a Docker container, we can see that our sample container has a status of Exited, but still exists on the system, as shown in the following code block:

$ docker container ls -a | grep sample
040fdfe889a6 alpine:3.10 "/bin/sh" 8 minutes ago Exited (0) 4 seconds ago
  1. If we want to see what has changed in our container in relation to the base image, we can use the docker container diff command, as follows:
$ docker container diff sample

The output should present a list of all modifications done on the filesystem of the container, as follows:

C /usr
C /usr/sbin
A /usr/sbin/getcap
A /usr/sbin/ipg
A /usr/sbin/tftpd
A /usr/sbin/ninfod
A /usr/sbin/rdisc
A /usr/sbin/rarpd
A /usr/sbin/tracepath
...
A /var/cache/apk/APKINDEX.d8b2a6f4.tar.gz
A /var/cache/apk/APKINDEX.00740ba1.tar.gz
C /bin
C /bin/ping
C /bin/ping6
A /bin/traceroute6
C /lib
C /lib/apk
C /lib/apk/db
C /lib/apk/db/scripts.tar
C /lib/apk/db/triggers
C /lib/apk/db/installed

We have shortened the preceding output for better readability. In the list, A stands for added, and C stands for changed. If we had any deleted files, then those would be prefixed with a D.

  1. We can now use the docker container commit command to persist our modifications and create a new image from them, like this:
$ docker container commit sample my-alpine
sha256:44bca4141130ee8702e8e8efd1beb3cf4fe5aadb62a0c69a6995afd49c2e7419

With the preceding command, we have specified that the new image will be called my-alpine. The output generated by the preceding command corresponds to the ID of the newly generated image.

  1. We can verify this by listing all images on our system, as follows:
$ docker image ls

We can see this image ID (shortened) as follows:

REPOSITORY   TAG      IMAGE ID       CREATED              SIZE
my-alpine latest 44bca4141130 About a minute ago 7.34MB
...

We can see that the image named my-alpine has the expected ID of 44bca4141130 and automatically got a latest tag assigned. This happens since we did not explicitly define a tag ourselves. In this case, Docker always defaults to the latest tag.

  1. If we want to see how our custom image has been built, we can use the history command as follows:
$ docker image history my-alpine

This will print a list of the layers our image consists of, as follows:

History of the my-alpine Docker image 

The first layer in the preceding output is the one that we just created by adding the iputils package.