Docker 2
Docker recipes: build your images
OS commands in image building
Depending on the underlying OS, there are different ways to build images.
Know your base system and its packages. Popular ones:
Update and upgrade packages
In Ubuntu:
apt-get update && apt-get upgrade -y
In CentOS:
yum check-update && yum update -y
Search and install packages
In Ubuntu:
apt search libxml2
apt install -y libxml2-dev
In CentOS:
yum search libxml2
yum install -y libxml2-devel.x86_64
Note the -y option that we set for updating and for installing.<br> It is an important option in the context of Docker: it means that you answer yes to all questions regarding installation.
Building recipes
All commands should be saved in a text file, named by default Dockerfile.
Basic instructions
Each row in the recipe corresponds to a layer of the final image.
FROM: parent image. Typically, an operating system. The base layer.
FROM ubuntu:24.04
RUN: the command to execute inside the image filesystem.
Think about it this way: every RUN line is essentially what you would run to install programs on a freshly installed Ubuntu OS.
RUN apt install wget
A basic recipe:
FROM ubuntu:24.04
RUN apt update && apt -y upgrade
RUN apt install -y wget
docker build
Implicitely looks for a Dockerfile file in the current directory:
docker build .
Same as:
docker build --file Dockerfile .
Syntax: –file / -f
. stands for the build process’s context (in this case, the current directory). This makes sense if copying files from the filesystem, for instance. IMPORTANT: Avoid contexts (directories) overpopulated with files (even if they are not used in the recipe).
You can define a specific name for the image during the build process.
Syntax: -t imagename:tag. If not defined `:tag`
default is latest.
docker build -t mytestimage .
# Same as:
docker build -t mytestimage:latest .
IMPORTANT: Avoid contexts (directories) over-populated with files (even if not used in the recipe).
To avoid some directories or files being inspected or included (e.g., with COPY command in Dockerfile), you can use the .dockerignore file to specify which paths should be avoided. More information at: https://codefresh.io/docker-tutorial/not-ignore-dockerignore-2/
The last installation line should be Successfully built …: you are good to go.
Check with docker images
to see if the newly built image is on the list…
Then, let’s check the ID of the image and run it!
docker images
docker run f9f41698e2f8
docker run mytestimage
More instructions
WORKDIR: all subsequent actions will be executed in that working directory
WORKDIR ~
ADD, COPY: add files to the image filesystem
Difference between ADD and COPY explained here and here
COPY: lets you copy a local file or directory from your host (the machine from which you are building the image)
ADD: The same, but ADD also works for URLs and .tar archives that will be automatically extracted upon being copied.
If we have a file, let’s say `example.jpg`
, we can copy it.
# COPY source destination
COPY example.jpg .
A more sophisticated case:
FROM ubuntu:24.04
RUN apt update && apt -y upgrade
RUN apt install -y wget
RUN mkdir -p /data
WORKDIR /data
COPY example.jpg .
ENV, ARG: run and build environment variables
Difference between ARG and ENV explained here.
ARG values: available only while the image is built.
ENV values: available during the image build process and for future running containers. * It can be checked in a resulting running container by running
env
.
CMD, ENTRYPOINT: command to execute when generated container starts
The ENTRYPOINT specifies a command that will always be executed when the container starts. The CMD specifies arguments that will be fed to the ENTRYPOINT
In the example below, when the container is run without an argument, it will execute echo “hello world”. If it is run with the argument hello moon it will execute echo “hello moon”
FROM ubuntu:24.04
ENTRYPOINT ["/bin/echo"]
CMD ["hello world"]
A more complex recipe (save it in a text file named Dockerfile:
FROM ubuntu:24.04
WORKDIR /data
RUN apt-get update && apt-get -y upgrade
RUN apt-get install -y wget
ENTRYPOINT ["/usr/bin/wget"]
CMD ["https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg"]
docker build -t downloadimg .
mkdir images
docker run -v $(pwd)/images:/data downloadimg
docker run -v $(pwd)/images:/data downloadimg https://upload.wikimedia.org/wikipedia/commons/1/11/Canis_lupus_familiaris.002_-_Monfero.jpg
docker tag
To tag a local image with ID “e23aaea5dff1” into the “ubuntu_wget” image name repository with version “1.0”:
docker tag e23aaea5dff1 ubuntu_wget:1.0
Build exercise
Random numbers
Copy the following short bash script in a file called random_numbers.sh.
#!/usr/bin/bash
seq 1 1000 | shuf | head -$1
This script outputs random integers from 1 to 1000; the number of integers selected is given as the first argument.
Write a recipe for an image:
Based on centos:7
That will execute this script (with bash) when it is run, giving it 2 as a default argument (i.e. outputs 2 random integers): the default can be changed as the image is run.
Build the image.
Start a container with the default argument, then try it with another argument.
Suggested solution
FROM centos:7
# Copy script from host to image
COPY random_numbers.bash .
# Make script executable (optional)
# Alternative ways to do this: https://stackoverflow.com/questions/56558570/copying-files-with-execute-permissions-in-docker-image
RUN chmod +x random_numbers.bash
# As the container starts, "random_numbers.sh" is run
# If executable /usr/bin/bash not strictly needed
ENTRYPOINT ["/usr/bin/bash", "random_numbers.sh"]
# default argument (that can be changed on the command line)
CMD ["2"]
Build and run:
docker build -f Dockerfile_RN -t random_numbers .
docker run random_numbers
docker run random_numbers 10