Creating Image
There are two main approaches to creating an image -
- Using a running container: a container is started, and modifications are applied to the container. The docker commit command is used to write modifications
Must cleanup before creating image. For example - you have installed some pckages and you didn't deleted those packages then the image size will be more than 100MB or more
- Using a Dockerfile: a Dockerfile contains instructions for building an image. Each instruction adds a new layer to the image, which offers more control over the files that are added to an image at a later stage
Image creation terminology
- Dockerfile is the original terminology, which was introduced by Docker
- OCI has standardized the name to Containerfile
- Feel free to use either of these file names
Understanding parent/child Images
- When working with Dockerfile, using Parent/Child images is common
- A child image is an image that is created from a parent image and incorporates everything in the parent image
- Starting from a parent image makes it easier to create a reliable image
Understanding the Process
- First, you'll create a working directory: each project should have its own project directory
- Next, you'll write the Dockerfile: the Dockerfile contains instructions to build the image
- Finally, build the image with docker
Writing a dockerfile
Each Dockerfile starts with FROM, identifying the base image to use
Next, instructions are executed in that base image
- Instructions are executed in the order specified
- Each Dockerfile instruction runs in an independent container, using an intermediate image built from a previous command, which means that adding multiple instructions results in multiple layers
Adding multiple layers to an image will increase the size of image, so it is recommended to have minimum layer possible while creating your image
Dockerfile instruction
- FROM identifies the base image to use
- LABEL is a key-value pair that is used for identification
- MAINTAINER is the name of the person that maintains the image
- RUN executes commands on the FROM image while building the image
- EXPOSE has metadata-only information on where the image should run
- ENV defines environment variables to be used within the container
- ADD copies files from the project directory to the image
- COPY copies files from the local project directory, using ADD is preferred
- USER specifies username for RUN, CMD and ENTRYPOINT instructions
- ENTRYPOINT has the standard command that the image will run (cannot be overridden by user)
- CMD can have the standard command, as well as arguments to the ENTRYPOINT command (canbe overridden by user)
Understanding ENTRYPOINT
ENTRYPOINT is the default command to be processed. If not specified, /bin/sh -c
is executed as the default command
Arguments to the ENTRYPOINT command should be specified separately
using CMD
ENTRYPOINT ["command"]; ENTRYPOINT ["/usr/sbin/httpd"]
CMD ["argl","arg2"]; CMD [-D", "FOREGROUND"]
If the default command is specified using CMD instead of ENTRYPOINT, the command is executed as an argument to the default entrypoint sh -c
which can give unexpected results
If the arguments to the command are specified within the ENTRYPOINT, then they cannot be overwritten from the command line; so to make your Dockerfile flexible, make sure to pass the command arguments separately in a CMD section
Understanding ADD or COPY
-
ADD and COPY are doing the same thing
-
COPY is simpler and has less features
-
ADD has specific features
- ADD can directly extract the contents of a tar file into the container
- ADD can fetch files from a URL, but this is deprecated. Rather, use
RUN wget
to fetch the file, and delete them afterwards when the file is no longer needed
Understanding formats
Options like ADD, COPY, ENTRYPOINT, CMD are used in shell form and in exec form
- Shell form is a list of items
- ADD /my/file /mydir
- ENTRYPOINT /usr/bin/nmap -sn 172.17.0.0/24
- Exec form is a JSON array of items
- ADD ["/my/file", "/mydir"]
- ENTRYPOINT ["/usr/bin/nmap", "-sn", "172.17.0.0/24"]
Using Exec form is preferred, as shell form wraps command in a /bin/sh -c
shell, which creates a sometimes unnecessary shell process
Avoiding multi-layer Image
Each command used in a Dockerfile creates a new layer and this should be avoided. So don't run multiple RUN commands, connect them using &&
For example -
RUN yum --disablerepo=* --enablerepo="myrepo" && yum update -y && yum install nmap
- To maintain readability, write the commands on different lines using
&& \
at the end of each line:
RUN yum --disablerepo=* && \
yum update -y && \
yum install -y nginx
Building Image with Dockerfile
Use docker build -t nmap .
to run it from the current directory.
Tip: use
docker build --no-cache -t nmap .
to ensure the complete procedure is performed again
Next, use docker run nmap
to run it. For troubleshooting - docker run -it nmap /bin/bash
. Will only work if you've installed bash!
Using docker commit
After making changes to a container, you can save it to an image. Use docker commit
to do so.
docker commit -m "custom web server" -a "Sandervan Vugt" myapache myapache
- Use
docker images
to verify
Next, use docker save -o myapache.tar myapache
and transport it to anywhere you'd like. From another system, use docker load -i myapache.tar
to import it as an image.