Docker Certified Associate Part2 Image Creation Management and Registry
Docker Certified Associate Part2 Image Creation Management and Registry
com
Note: Dockerfile is a text file containing sequence of command instructions that is run in a
sequence in order to build an image. Dockerfile can contain comments and instructions in the
following pattern.
$ cat /path/to/Dockerfile
# Comment
INSTRUCTION arguments
"docker build” command is used for building an image out of the Docker file. “docker build”
command requires a Dockefile and a Context (a set of files in a directory path or URL). The URL
can contain a git source or plain text files or prepacked tarball. If a file named .dockerignore
file is placed in this context directory containing files or directories (can contain patterns too),
they are ignored from context.
$ cat /path/to/context-directory/.dockerignore
# comment
*/temp*
*/*/temp*
temp?
5. Build docker image using STDIN plain text Dockerfile from file path or URL
to Dockerfile.
# docker build - < Dockerfile # example with STDIN Dockerfile
# docker build https://path/to/Dockerfile # example with URL to Dockerfile
Note: If you use STDIN or specify a URL pointing to a plain text file, there is no context. The Dockerfile
cannot use a context since it would not work.
When you build an image with docker, let’s say you have specified an invalid URL for a file
download or may be an invalid command, this returns a non-zero exit value. The docker build
fails when a non zero exit value is returned by one of its instructions.
The following are different instructions that can be added to Dockerfile to build an image.
• FROM – Select the base image to build the new image on top of.
Let’s say you want your application to run with a centos base image, you begin the
docker file with the below lines to choose a centos 7 base image. Example,
RUN, CMD, ENTRYPOINT are the three instructions that are used to execute a command.
There are two methods that can be used to execute a command in Dockerfile, which are
the shell method and the exec method.
• RUN - This is executed only during image build time and not during run time. (i.e not
when the container is started). Example,
#install RPM
RUN yum install myapp.rpm
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
• ENTRYPOINT: can be used to specify command to run when container starts. Example,
start a service. Example,
• CMD: can be used to specify command to run when container starts OR it can also be
used to specify an argument which will get passed to an ENTRYPOINT command.
Example, Start a service or provide some arguments to ENTRYPOINT. Example,
CMD start
For the above reasons, the RUN instruction keyword can appear multiple times in
dockerfile whereas the CMD and ENTRYPOINT instruction keyword can appear only
ones. Either CMD or ENTRYPOINT command should be present at least once.
• SHELL– Useful to run commands in shell form by overriding the default shell. Example,
• USER - Define the default User all commands will be run as within any Container
created from your Image. Example,
USER admin:somegroup
# one can also use UID and GID instead.
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
• VOLUME - Creates a mount point within the Container and links it back to file systems
accessible by the Docker Host. Example,
VOLUME /var/www/html
• ADD – allows you to use a URL or a path to a file from Docker host as the source of a file
to be copied to a path in container. When a URL is provided, a file is downloaded from
the URL and copied to the destination specified in container. Example,
When URL is passed, the contents are downloaded and placed in destination.
When tar files are sourced, its contents are extracted to destination automatically.
--chown is supported only in Linux containers.
• COPY – allows you copy local files only. URL is only supported in ADD. Also, tarfiles are
not extracted like in ADD.
• WORKDIR – Define the default working directory for the commands defined in the
“ENTRYPOINT” or “CMD” instructions. Example,
WORKDIR /home
EXPOSE 80/tcp
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
EXPOSE 80/udp
This only exposes the port in container, but does not publish the port on host. To
publish port, it must be done with docker run command.
• ARG – define variables which can be used during build time. These variables cannot be
referenced in the container (i.e during runtime)
ARG appuser=nginxadmin
RUN useradd ${appuser}
# ARG is also the only instruction that can precede FROM instruction. Example,
ARG image_version=latest
FROM alpine:${image_version}
Scope of ARGs:
ARG can have key value pairs or just keys with no value. Example,
ARG appuser
ARG appversion=1.0
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
▪ An instruction can use an ARG only after it has been defined in the
docker file. Instructions that appear before ARG declaration will get
an empty string.
▪ If an instruction is using an ARG that only has a key and no value,
will get an empty string
▪ An ARG declared in Dockerfile can also be passed as an argument
with a different value to “docker build” command. Example,
▪ If the same variable is defined in ARG and ENV, ENV takes priority.
Example,
ENV name=name-env
ARG name=name-arg
RUN echo ${name}
#Will yield “echo name-env” during build time.
Predefined ARGS:
• ONBUILD – Used to specify instructions that gets triggered on builds that uses this as
baseimage and not during the build of the current Dockerfile itself.
• STOPSIGNAL– Used to specify signal call that will be sent to container to exit. Example,
STOPSIGNAL SIGTERM
#or
STOPSIGNAL SIGKILL
• HEALTHCHECK– Used to specify a CMD instruction that will be triggered for health check.
Example,
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
The health check command should constructed with the following rules.
# 0: success - the container is healthy and ready for use
# 1: unhealthy - the container is not working correctly
# 2: reserved - do not use this exit code
• LABEL– Labels are Key Value pairs defined in DockerFile used to add metadata to an image.
Example,
LABEL image_version=”1.0.0”
LABEL image_provider=”com.unixutils”
Following is an example of Docker file with the different instructions that was discussed in the
previous section.
# cat /path/to/my/Dockerfile
#use centos base image
FROM --platform=LINUX centos:7
#metadata
LABEL image_provider="com.unixutils"
LABEL author="vijay"
ONBUILD RUN ["/bin/sh", "-c", "echo Built from baseimage by UnixUtils> /tmp/test"]
#environmental variables
ENV app_binary_path="/opt/webapp/bin"
#install httpd
RUN ["yum", "install", "httpd", "-y"]
Following are the recommendations & best practices for creating an efficient image via
Dockerfile
• Create ephemeral containers – Containers that can be easily stopped, destroyed &
recreated with minimal setup and configuration.
• Build context – Exclude unnecessary files from build context. Use a .dockerignore file to
add a list of files and directories to exclude from build.
• Use Multistage builds – As we know, every line of instruction in a Dockerfile is built as an
individual layer in the image. When rebuilding a Dockerfile, only the changes are built
again, and the rest is pulled from cached layers. Multistage-build feature in Dockerfile
allows usage of multiple FROM instructions to leverage using this image cache. Every
time a FROM instruction is encountered in a Dockerfile, a new stage of build is started.
This is beneficial since a new image can be built based on a previous one. Example,
cat /multistage-build-example/Dockerfile
# STAGE1 – Build your artifacts for production and run test cases
# STAGE2 – Prod image creation – (this is the final image that contains only the
artifact that was built in STAGE1 and not the dependencies used for build)
per container (not mandatory). One can also have a single process with child worker
processes like in apache/HTTPD.
• Minimize no. of layers – less layers makes image build process performant.
NOTE: RUN, COPY, ADD instructions create separate layers when encountered.
• Sort multi-line arguments passed to a command alphanumerically, for easy maintenance
and readability
• Leverage Build Cache – Docker by default uses Build cache. In Dockerfile, if parent image
already exists, for every instruction, docker checks if an image layer exists that matches
the instruction then the layer is used. --no-cache=true disables this behavior. For ADD
and COPY instructions since it involves files, the source file’s checksum is compared to
validate and reuse the later.
• Use only official images as base images in FROM. (docker recommends Alpine)
• Use LABEL to organize images
• Do not major updates after starting container. Example, yum update. Instead, use
containers with updated packages. Example, “RUN yum update” will not run if an
existing image layer exists for this instruction
• Split long commands into multiline using backslashes (\)
• Use ENV to update $PATH. Example, ENV PATH /myapp/bin:$PATH.
• Group commands working towards same goal in a single instruction. Example,
RUN export version=1.0 && unset version instead of having the unset in a separate RUN
instruction. (because the var is unset the next image layer and would still persist in
previous layer)
• Use separate COPY or ADD instructions for different files - If copying files use separate
COPY instructions so that when individual files are update, only the layer for that
specific file would be rebuilt and rest will be picked up from cache.
• Use VOLUME for any mutable data storage such as DB, config files etc – non static data
should VOLUME.
• Use absolute path for WORKDIR
• Images built with ONBUILD instructions in it should get a separate tag. Example:
ruby:1.9-onbuild or ruby:2.0-onbuild
Recommended read: Best practices for building docker images using Dockerfile
Describe and demonstrate how to use CLI commands to manage images, such as list,
delete, prune, rmi
3. Import a docker image from a local tar file or URL to tar file.
# docker image import </local/file.tar.gz OR https://url/file.tar.gz>
LOAD vs IMPORT:
Load is used to load multiple images from a tar file. It loads all the image layers
including base image and versions. This type of a tar file can be created by using
docker image save command
IMPORT is used to import a docker filesystem image from a tar file. This type of a
tar file can be created by using docker container export
Describe and demonstrate how to inspect images and report specific attributes using
filter and format
Using --format, show only specific columns while listing images. Example, show only column ID
or Repository names etc.
Every image also has an imageID. An image can be referenced with the imagename or image-ID.
The following output shows image "centos:latest" with image ID 7e6257c9f8d8. (centos being
the reponame and latest being the tag separated by :)
One can reference the image with "centos:latest" OR "7e6257c9f8d8". One can pass either of
these to docker image ls and yield the same output.
With that, tags can be understood as aliases to the images. (An alias with naming convention to
convey useful information about the image.)
An existing image can be tagged multiple times. Which means, one can create multiple tags
(aliases) to same image and call them.
Examples:
# docker tag centos:7 centos_custom:dev
# docker tag 7e6257c9f8d8 centos_custom:test
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
Tagging can also be done to a private repository, by prefixing the private registry
server's hostname and port. Example
# docker tag centos:7 myregistryhost:5000/centos_custom:prod
As seen in the following output, when docker images are listed, same original image centos:7
with image-ID 7e6257c9f8d8 is tagged with new name centos_custon:dev, centos_custom:test,
myregistryhost:5000/centos_custom:prod
docker image inspect command and docker history command can be used to list the
layers of the command.
NOTE: --format can be used to filter the json and display a specific section or subsection.
An image can be made to contain a single layer by leveraging the multistage build option
explained in the following section that has been discussed already.
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
Multistage Build
Docker registry scalable and stateless application used for storing and distributing
docker images. This is useful when one does not want to store images in docker hub and
to take control of the image distribution pipeline.
The docker registry application is available as a docker image which can be pulled and
run as a service.
Deploy a registry
As we know now, Registry is nothing but an instance of the registry image available on
docker hub, which can be run as a standalone container or in swarm mode.
Below are a few key considerations for deploying a registry in a standalone container.
• Load balancing Considerations: The following should be the same for all
instances running registry, to ensure there is no issues in processing service
requests.
1. Storage Driver
2. HTTP Secret (to ensure uploads are coordinated)
3. Redis Cache (if configured)
4. All registry instances should Same share filesystem (on
same machine)
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
\
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
"allow-nondistributable-artifacts":
["myregistrydomain.com:5000"]
}
We have discussed restricting registry access in the previous section. The following
provides insight on logging into docker registry.
The config.json shoud be updated with helper program’s executable suffixed in the
following format. Also the executable should be available/exported in $PATH on
registry host.
"docker-credential-<credential-helper-program's executable>":
{
"credsStore": "<credential-helper-program's executable>"
}
Once you run # docker logout and log back in, plain text credentials should be
removed and the credential helper program should take effect.
Published by: unixutils.com | Author: Vijayendar Gururaja | Email: [email protected]
For linux, pass or secretservice are the credential helper programs. If the binaries
are not available, it fallsback to using the base64 encoded credentials stored in
config.json
It is possible to search for images from docker registry by passing the string to search
with.
An image can be pushed to docker registry for distribution. We have already seen
examples of this previously.
docker commit command allows committing the state of the container to an image.
Example,
images can be pulled from registry either as single image i.e a specific tag or all images
i.e the entire repository.
By default, Docker daemon pulls three layers of an image at a time. This number can be
modified by changing --max-concurrent-downloads in /etc/docker/daemon.json.
Similarly --max-concurrent-uploads controls the image push operation.