In our previous post, we explored how to significantly optimize Docker image size. Now, let's dive deeper and enhance our images with valuable metadata using Docker labels.
Remember this Dockerfile from last time?
FROM node:20-alpine AS build-env
WORKDIR /app
COPY package.json yarn.lock ./
ENV NODE_ENV=production
RUN yarn install --frozen-lockfile --production
COPY index.js ./
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=build-env /app /app
CMD ["index.js"]
If we inspect this image and check its labels using the command:
docker image inspect --format='{{json .Config.Labels}}' atharvaunde/dockerexamples:distroless
We'll see... null
. So, what's the point of Docker labels, and why should we care?
Why Use Docker Labels?
Docker labels are essentially metadata tags that you can add to your Docker images. Think of them as key-value pairs that provide extra information about the image.
Use Cases for Docker Labels
- Attribution: Who built this image? Include the author's name and email.
- Organization: Which company or team created this image?
- Version Tracking: What version of the application is contained within? This is especially useful if you consistently tag images as
latest
. - Description: Provide a short description of the image's purpose.
- Custom Metadata: Add any other relevant information, such as dependencies, build dates, or license details.
By embedding this information directly into the image, you provide valuable context to users who consume your images.
Adding Labels to Our Dockerfile
Let's enhance our Dockerfile with labels to include the author, company, version, and a description:
FROM node:20-alpine AS build-env
WORKDIR /app
COPY package.json yarn.lock ./
ENV NODE_ENV=production
RUN yarn install --frozen-lockfile --production
COPY index.js ./
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
LABEL org.opencontainers.image.authors="authoremail@example.com"
LABEL "com.example.vendor"="Example LLC"
LABEL version="1.0.0"
LABEL description="This image is used to run hello world backend written in Express Framework"
COPY --from=build-env /app /app
CMD ["index.js"]
Now, when we run the same inspection command:
docker image inspect --format='{{json .Config.Labels}}' atharvaunde/dockerexamples:distroless
We'll see the labels we added:
{
"com.example.vendor": "Example LLC",
"description": "This image is used to run hello world backend written in Express Framework",
"org.opencontainers.image.authors": "authoremail@example.com",
"version": "1.0.0"
}
Important Placement in Multi-Stage Builds
When using multi-stage Dockerfiles like ours, it's crucial to place the LABEL
instructions in the final stage (i.e., the one that creates the actual image you'll be distributing). If we had placed the LABEL
instructions before the FROM gcr.io/distroless/nodejs20-debian12
line, they would be lost in the final image. The final image is created in a separate stage with separate context, so it wouldn't inherit labels from any previous stage.
Docker Label Inheritance and Overriding
This table summarizes how labels are handled when a Dockerfile adds a label that either exists or doesn't exist in the base image.
Scenario | Base Image Label | Dockerfile Label | Resulting Image Label |
---|---|---|---|
Inheritance: Label Exists in Base Image | Exists | Absent | Retained (from base) |
Overriding: Label Exists in Base Image | Exists | Present | Overridden (Dockerfile value) |
Addition: Label Not in Base Image | Absent | Present | Retained (Dockerfile value) |
In Conclusion:
Docker labels are a simple yet powerful way to add metadata to your Docker images, providing valuable context and improving discoverability. Remember to place your LABEL
instructions in the correct stage of a multi-stage Dockerfile and be aware of how label inheritance works. Happy containerizing!
Top comments (0)