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:
- https://docs.docker.com/develop/develop-images/build_enhancements/
- https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
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.