
Docker images are the building blocks of Docker containers. An image contains everything that is needed to run an application or service inside a container – the code or binaries, runtimes, dependencies, and configurations.
Images are immutable, meaning they can’t be changed once built. To make changes, you build a new image. Images are also layered, meaning each image builds on top of a base image, adding just the changes needed for that specific image. This makes images lightweight, reusable, and fast to build.
There are two main steps to working with Docker images:
- Building – Creates a Docker image from a Dockerfile
- Pushing – Uploads an image to a registry like Docker Hub
This guide will cover these steps in detail, including:
- Dockerfile basics
- Building images locally
- Tagging images
- Pushing images to registries
- Managing images
Dockerfile Basics
Docker images are built from a Dockerfile – a text file that contains instructions for building the image. A Dockerfile defines everything that goes into the image – the OS, configurations, files and folders to copy, network ports to expose, Docker volumes to create, and more.
Some common Dockerfile instructions include:
FROM
– Sets the base image to build uponCOPY
– Copy files from the host into the imageRUN
– Run commands and shell scripts during buildEXPOSE
– Expose network ports the container will listen onENV
– Set environment variablesENTRYPOINT
– Define the executable to run when container startsCMD
– Default parameters that get passed to the ENTRYPOINT
Here is a simple Dockerfile example that builds a Node.js app:
# Use the latest Node.js 11 base image
FROM node:11
# Set the working directory in the container
WORKDIR /app
# Copy package files and install dependencies
COPY package*.json ./
RUN npm install
# Copy app source code
COPY . .
# Expose port and start application
EXPOSE 8080
CMD ["node", "app.js"]
This uses the node:11
image as a starting point, copies the app source code into the image, installs dependencies, and sets the app to start on container launch.
Building Local Images
With a Dockerfile ready, you can build an image using the docker build
command. This will build the image step-by-step as per the Dockerfile instructions.
The basic format is:
$ docker build [options] PATH
Where PATH is the location of the Dockerfile.
For example:
$ docker build -t my-app .
This will look for a Dockerfile in the current directory and build an image called my-app
from it.
Some key options:
-t
– Tag the image with a repository name and tag--no-cache
– Rebuild the image from scratch instead of using cache-f
– Path to the Dockerfile if it’s not in the current directory
You can build images for different environments or parameters by simply having multiple Dockerfiles, e.g. Dockerfile.dev, Dockerfile.prod.
During development, you’ll want to iterate rapidly by rebuilding images frequently as you make changes to the application. Using the cache speeds up rebuild times significantly.
Tagging Images
Image tags identify an image as belonging to a repository and provide a version or variant name.
Tags consist of the repository name and tag name separated by a colon, such as my-app:latest
.
When building an image, the -t
flag tags it:
$ docker build -t my-app:latest .
This names the image my-app
and tags it latest
.
If no tag is provided, latest
is assumed.
Some common tagging strategies:
latest
– The most up-to-date stable version- Git commit SHA – Tag build with commit SHA for traceability
- Semantic versions – Tags like
v1.0.2
for release versions - Variant tags – Such as
prod
,test
,dev
to denote what the image is used for
Note: Tagging gives meaning and context to an image. Untagged images are difficult to manage.
You can retag an existing image to add or modify tags:
$ docker tag my-app:latest my-app:v1.0
Pushing Images to Docker Registries
To share Docker images with others, you push them to a registry. A registry stores Docker images that can then be pulled down and used by any Docker host.
The default registry is Docker Hub, which has public and private repositories.
To push an image:
- Tag the image with the registry name:
$ docker tag my-app:latest mydockerid/my-app:latest
- Push the tagged image:
$ docker push mydockerid/my-app:latest
This will upload the image my-app:latest
to the mydockerid
namespace on Docker Hub.
To push to a different registry:
$ docker push registry.example.com/my-app:latest
Some companies host internal private registries to store proprietary images. These require authentication and SSL for security.
In a CI/CD pipeline, you can automate building and pushing images to registries on each code change. This enables continuously deploying applications using the latest images.
Managing Local Images
As you build images, the Docker host will store them locally in the Docker engine. To free up disk space, you’ll need to occasionally clean up old and unused images.
Some useful commands for managing images:
docker images
– Lists all images on the hostdocker image rm
– Remove one or more imagesdocker image prune
– Remove unused and dangling imagesdocker rmi
– Remove image by ID or name
Example of removing images:
# Remove specific image
$ docker image rm my-app:latest
# Remove all images matching name
$ docker image rm my-app
# Remove dangling images
$ docker image prune
# Remove all images
$ docker rmi $(docker images -q)
Use these commands cautiously to avoid accidentally removing images still in use or needed.
You can also set up automated policies to delete old images. For example, always keeping only the 10 most recent image tags for each repository.
Conclusion
That covers the basics of building, tagging, pushing and managing Docker images!
Key takeaways include:
- Dockerfiles define how images are built
docker build
turns a Dockerfile into a runnable image- Images should be tagged with a repository and version names
docker push
uploads images to registries like Docker Hubdocker image
commands manage images on a Docker host
With these fundamentals, you can effectively use Docker images to package and deploy applications consistently and reliably. Automating image building and deployments will let you move towards mature DevOps practices.