not produce an image layer and don't take up any size, other than the metadata
itself. The output above shows that this image consists of 2 image layers.
```console
$ docker image history acme/my-final-image:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
8bd85c42fa7f 3 minutes ago CMD ["/bin/sh" "-c" "/app/hello.sh"] 0B buildkit.dockerfile.v0
<missing> 3 minutes ago RUN /bin/sh -c chmod +x /app/hello.sh # buil… 39B buildkit.dockerfile.v0
<missing> 3 minutes ago COPY . /app # buildkit 222B buildkit.dockerfile.v0
<missing> 4 minutes ago RUN /bin/sh -c apk add --no-cache bash # bui… 2.15MB buildkit.dockerfile.v0
<missing> 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:f278386b0cef68136… 5.6MB
```
Notice that all steps of the first image are also included in the final
image. The final image includes the two layers from the first image, and
two layers that were added in the second image.
The `<missing>` lines in the `docker history` output indicate that those
steps were either built on another system and part of the `alpine` image
that was pulled from Docker Hub, or were built with BuildKit as builder.
Before BuildKit, the "classic" builder would produce a new "intermediate"
image for each step for caching purposes, and the `IMAGE` column would show
the ID of that image.
BuildKit uses its own caching mechanism, and no longer requires intermediate
images for caching. Refer to [BuildKit](/manuals/build/buildkit/_index.md)
to learn more about other enhancements made in BuildKit.
9. Check out the layers for each image
Use the `docker image inspect` command to view the cryptographic IDs of the
layers in each image:
```console
$ docker image inspect --format "{{json .RootFS.Layers}}" acme/my-base-image:1.0
[
"sha256:72e830a4dff5f0d5225cdc0a320e85ab1ce06ea5673acfe8d83a7645cbd0e9cf",
"sha256:07b4a9068b6af337e8b8f1f1dae3dd14185b2c0003a9a1f0a6fd2587495b204a"
]
```
```console
$ docker image inspect --format "{{json .RootFS.Layers}}" acme/my-final-image:1.0
[
"sha256:72e830a4dff5f0d5225cdc0a320e85ab1ce06ea5673acfe8d83a7645cbd0e9cf",
"sha256:07b4a9068b6af337e8b8f1f1dae3dd14185b2c0003a9a1f0a6fd2587495b204a",
"sha256:cc644054967e516db4689b5282ee98e4bc4b11ea2255c9630309f559ab96562e",
"sha256:e84fb818852626e89a09f5143dbc31fe7f0e0a6a24cd8d2eb68062b904337af4"
]
```
Notice that the first two layers are identical in both images. The second
image adds two additional layers. Shared image layers are only stored once
in `/var/lib/docker/` and are also shared when pushing and pulling an image
to an image registry. Shared image layers can therefore reduce network
bandwidth and storage.
> [!TIP]
>
> Format output of Docker commands with the `--format` option.
>
> The examples above use the `docker image inspect` command with the `--format`
> option to view the layer IDs, formatted as a JSON array. The `--format`
> option on Docker commands can be a powerful feature that allows you to
> extract and format specific information from the output, without requiring
> additional tools such as `awk` or `sed`. To learn more about formatting
> the output of docker commands using the `--format` flag, refer to the
> [format command and log output section](/manuals/engine/cli/formatting.md).
> We also pretty-printed the JSON output using the [`jq` utility](https://stedolan.github.io/jq/)
> for readability.
### Copying makes containers efficient
When you start a container, a thin writable container layer is added on top of
the other layers. Any changes the container makes to the filesystem are stored
here. Any files the container doesn't change don't get copied to this writable