Dockerfile

The Dockerfile allows you to define a blueprint for an image. Capatilization of docker directives like FROM and RUN is not mandatory however it is best practice.

You can base your docker image on an existing docker image using the FROM command followed by the name of the image (this can be as it appears on services like dockerhub).

FROM <IMAGE_NAME>

Run

You can customise your image by using the RUN command to execute a command in the environment that the image is based on. In the example below the dockerfile starts from the ubuntu environment and installs python.

FROM ubuntu
RUN apt-get install -y python3

A docker build will fail if the command that RUN called exits with a non-zero return code. However, this can be problematic when you include nested scripts as part of your docker file. For example RUN my-complex-script.sh. If there are points in the script where script failure should fail the build these needed to be tested and an exit 1 called to return the correct failing exit code, otherwise the script will simply run, even with failures and return a success code of 0.

The example below shows an extract of a test command being run as part of a script, if this was run with the docker RUN command directly then its failure would stop the build, however, because of its inclusion inside the script this won’t happen unless the result of the test command is checked with the $? variable and an exit 1 command called if it is non-zero.

# my-complex-script.sh
# --- snip other complex script stuff ---

npm test
if [ $? -e 1 ]; then exit 1; fi

Label

You can add metadata to your docker image by using the LABEL directive.

LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

The MAINTAINER directive has been deprecated. However if you can add meta to your dockerfile using the LABEL directive which takes a key-value pair assigned with an =.

LABEL maintainer="my_name@some-website.com"

Copy

You can use the copy files from an external source to your docker container using the COPY directive. This takes the file source on the machine building the image followed by the destination inside the targeted container image.

COPY my/local/file.txt some/container/directory

COPY will not copy the Dockerfile into the image.

Workdir

You can set a working directory inside a container using the WORKDIR command. This takes a path as an argument which subsequent RUN, COPY, CMD etc. commands will run from. If the directory specified doesn’t exist it in the container it will be created.

WORKDIR /usr/my/working/directory

You can call the WORKDIR command multiple times, each time it will create the new working directory relative to the last call. The example below outputs the working directory /usr/working/directory/.

WORKDIR /usr
WORKDIR working
WORKDIR directory

If the directory does not already exist then WORKDIR will create a new directory on the images file system.

Expose

You can expose ports on your docker container so that it can listen for external traffic using the EXPOSE directive.

EXPOSE 8080

The intention of EXPOSE is as documentation for the user of the image to show them which ports this docker image will output data from. It is the system that starts a container based on this image that will have to link one of its internal ports to the port on the container to listen for information.

CMD

You can run a command when your docker image starts by using the CMD directive. There can only be one of these in a Dockerfile. This command only runs once the docker image actually starts, where as the RUN command is committed to the image as it builds. CMD can be written using shell form or json form.

CMD sh my_script.sh        # shell form
CMD ["sh", "my_script.sh"] # json form

ENV

You can set environment variables that persist in the container environment by using the ENV command. There are a number of rules for what is valid as environment variables which can be found in the main docs for ENV. Anything defined with ENV in the Dockerfile can be used as an environment variable by services running inside the container

ENV MY_VAR="Some variable data"

ARG

You can pass run time environment variables into a docker container during the build process by using the --build-arg flag in conjunction with the ARG keyword in your Dockerfile. Note that if you pass in a --build-arg without the ARG property defined in the file then it won’t be picked up, a confusing quirk that can make you wonder why the args you are passing in are not working.

docker build . --build-arg MY_ARG=my_value

The corresponding Dockerfile would be:

FROM ubuntu

ARG MY_ARG

# stuff that uses the MY_ARG context down here such as a script or test run

You can pass in multiple arguments by using multiple --build-arg flags.

docker build . --build-arg FOO=bar --build-arg BAZ=qux --build-arg EGGS=spam