Dockerfile

A Dockerfile is a file that describes how to build a Docker image: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

A Dockerfile starts with a FROM directive that specifies the parent image to inherit from. Subsequent directives are essentially a script of actions to build the final image on top of the parent image. For example:

FROM fedora:latest
CMD echo "Hello World"

A searchable list of public images is here: https://hub.docker.com/search?q=&type=image&image_filter=store%2Cofficial

In the example above, the name before the colon (e.g. fedora) is the repository name and the name after the colon (e.g. latest) is the version of a particular image (the combination of repository name and version is called a tag): https://hub.docker.com/_/fedora

The CMD (or ENTRYPOINT) directive is required and it's the final executable (and any arguments) which runs to start the image as a container. When that executable ends, the container also ends. In the example above, "Hello World" is printed and the container ends.

A Dockerfile is built into an image with a path to the build context path (normally the current directory with "."):

$ docker build .
Sending build context to Docker daemon  6.144kB
Step 1/2 : FROM fedora
 ---> 8c568f104326
Step 2/2 : CMD echo "Hello World"
 ---> Using cache
 ---> e7f19ddca071
Successfully built e7f19ddca071

The image may be run by specifying the container name:

$ docker run e7f19ddca071
Hello World

An image is normally built with a tag:

$ docker build -t testimage:20190304 .
Sending build context to Docker daemon  6.144kB
Step 1/2 : FROM fedora:latest
 ---> 8c568f104326
Step 2/2 : CMD echo "Hello World"
 ---> Using cache
 ---> e7f19ddca071
Successfully built e7f19ddca071
Successfully tagged testimage:20190304

Then the human-readable tag may be used to run the image:

$ docker run testimage:20190304
Hello World

The $(docker ps) command will not show stopped containers. Instead use the -a flag:

$ docker ps -a
CONTAINER ID        IMAGE                        COMMAND                   CREATED             STATUS                    PORTS               NAMES
ec4942671282        testimage:20190304   "/bin/sh -c 'echo \"H..."   3 seconds ago       Exited (0) 1 second ago                       eloquent_kapitsa

If a container naturally stops because the CMD finishes (as opposed to a still-running container stopped with $(docker stop)), then the only way to "log in" and review the container is to commit the container's disk contents to a new image and then start that image with an alternative CMD that logs you in (this new container should only be used for investigation and grabbing logs because it does not contain important aspects of the previous container such as environment entries):

$ docker commit ec4942671282 testimage:20190304_run1
sha256:9e7d092f7686e126e94f03f6f6df32fe9292bdb4ee0018cdaa1cb0deaaf5c0d7
$ docker run -it --entrypoint=sh testimage:20190304_run1
sh-4.4#

A test image may run forever with a CMD such as:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

Another way to start a container and log in is to use:

CMD sh

And then run and allocate an interactive tty:

$ docker run -it testimage:20190304
sh-4.4#

Caching

If a Dockerfile command references a remote resource (e.g. RUN git clone or wget), Docker has no way to know when that remote resource has changed so it will gladly re-use a cached layer if available. Either delete that particular cached layer, or, during development, consider adding something trivial that changes the command such as incrementing a numeric value in an echo statement:

RUN echo "Cloning somerepo V1"; git clone somerepo

Secrets

Run-time secrets may be mounted through volumes: https://github.com/moby/moby/issues/13490

Build-time secrets using ARG, ENV, and multi-stage builds are generally not secure because they are difficult to completely purge from things like the docker layers, cache, etc. The alternative is tmpfs mounted secrets:

Kubernetes secrets: https://kubernetes.io/docs/concepts/configuration/secret/

Show Dockerfile from Image

There's no way to build a Dockerfile from an image, but you can see all the commands that were executed to build the image in order. For example:

$ docker history -H openliberty/open-liberty
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
086d92162c64   43 hours ago   /bin/sh -c #(nop)  CMD ["/opt/ol/wlp/bin/ser...   0B        
[...]

For the full commands, add the --no-trunc option.

Major Linux Flavors