|
| 1 | +# Chainguard Workshop: Containers 102 |
| 2 | +* Deep dive into container images |
| 3 | +* Hands on exercises to learn tactics needed for hardened, distroless-type images |
| 4 | + |
| 5 | +## Hands-on Exercises |
| 6 | +All exercises assume you are cd'd into the `containers-102` directory (where this README is located). |
| 7 | +### Understanding image layers |
| 8 | +Steps: |
| 9 | +1. Get a big file, untar it, and remove the tarball |
| 10 | + 1. `cd layers` |
| 11 | + 1. `cat Dockerfile.1` and note the 3 RUN lines to download a big file, untar it, and remove the tarball |
| 12 | + 1. `docker build . -t layers:1 -f Dockerfile.1` |
| 13 | + 1. `docker images layers` Note at the image size is ~33.5MB |
| 14 | + 1. `docker image history layers:1` You will see individual layers for each `RUN` line in the Dockerfile |
| 15 | + |
| 16 | +1. Concatenate operations into a single RUN line |
| 17 | + 1. `cat Dockerfile.2` and note change to a single `RUN` line to download a big file, untar it, and remove the tarball |
| 18 | + 1. `docker build . -t layers:2 -f Dockerfile.2` |
| 19 | + 1. `docker images layers` Compare the new image size which is about 1.5MB smaller due to the removal of the tarball in the same `RUN` line |
| 20 | + 1. `docker image history layers:2` You will see a single layer for the single `RUN` line in the Dockerfile |
| 21 | + |
| 22 | +### Multi-stage builds |
| 23 | +Steps: |
| 24 | +1. Using multistage to eliminate unwanted layers |
| 25 | + 1. `cd multistage` |
| 26 | + 1. `cat Dockerfile.1`<br>This is similar to the 1st step of the previous exercise, but with a multi-stage build. |
| 27 | + 1. `docker build . -t mstage:1 -f Dockerfile.1` |
| 28 | + 1. `docker images mstage` |
| 29 | + 1. `docker images layers`<br>Comparing the image sizes, this one is about 1.2MB smaller that the previous exercise |
| 30 | + 1. `docker image history mstage:1`<br>There is now a single layer for the COPY line |
| 31 | + |
| 32 | +1. Copying a dependency to a final stage w/out a package manager |
| 33 | + 1. `cat Dockerfile.2`<br>In this example, we want to get `jq` working in the final image but there's no `apk` tooling there because it's a non-dev Chainguard imag, so we are trying to just COPY it. |
| 34 | + 1. `docker build . -t mstage:2 -f Dockerfile.2` |
| 35 | + 1. `docker run --rm -it mstage:2`<br>We get an error because the required `libonig.so.5` library is missing |
| 36 | + |
| 37 | +1. Find out what libraries are needed, target the builder image |
| 38 | + 1. `docker build -t mstage:2b -f Dockerfile.2 --target=builder .`<br>This will build the `builder` stage only |
| 39 | + 1. `docker run --rm -it --entrypoint sh -u root mstage:2b` |
| 40 | + 1. `ldd /usr/bin/jq`<br>ldd is not installed so we need to find and add it |
| 41 | + 1. `apk search --no-cache cmd:ldd`<br>This will search for packages that provide the `ldd` command |
| 42 | + 1. `apk add --no-cache posix-libc-utils`<br>This will install the `ldd` command |
| 43 | + 2. `ldd /usr/bin/jq`<br>Now we can see the dependencies of the `jq` command and see that `libonig.so.5` is needed |
| 44 | + 3. `exit`<br>Exit the container |
| 45 | + |
| 46 | +1. Copy the .so file(s) to the final image |
| 47 | + 1. `cat Dockerfile.3`<br> Note the addition of the `libonig.so.5` library to the final image |
| 48 | + 1. `docker build . -t mstage:3 -f Dockerfile.3` |
| 49 | + 1. `docker run --rm -it mstage:3`<br>Now the `jq` command should work |
0 commit comments