When building your own image from a Dockerfile, ensure you choose a minimal base
image that matches your requirements. A smaller base image not only offers
portability and fast downloads, but also shrinks the size of your image and
minimizes the number of vulnerabilities introduced through the dependencies.
You should also consider using two types of base image: one for building and
unit testing, and another (typically slimmer) image for production. In the
later stages of development, your image may not require build tools such as
compilers, build systems, and debugging tools. A small image with minimal
dependencies can considerably lower the attack surface.
## Rebuild your images often
Docker images are immutable. Building an image is taking a snapshot of that
image at that moment. That includes any base images, libraries, or other
software you use in your build. To keep your images up-to-date and secure, make
sure to rebuild your image often, with updated dependencies.
To ensure that you're getting the latest versions of dependencies in your build,
you can use the `--no-cache` option to avoid cache hits.
```console
$ docker build --no-cache -t my-image:my-tag .
```
The following Dockerfile uses the `24.04` tag of the `ubuntu` image. Over time,
that tag may resolve to a different underlying version of the `ubuntu` image,
as the publisher rebuilds the image with new security patches and updated
libraries. Using the `--no-cache`, you can avoid cache hits and ensure a fresh
download of base images and dependencies.
```dockerfile
# syntax=docker/dockerfile:1
FROM ubuntu:24.04
RUN apt-get -y update && apt-get install -y --no-install-recommends python3
```
Also consider [pinning base image versions](#pin-base-image-versions).
## Exclude with .dockerignore
To exclude files not relevant to the build, without restructuring your source
repository, use a `.dockerignore` file. This file supports exclusion patterns
similar to `.gitignore` files.
For example, to exclude all files with the `.md` extension: