|
| 1 | +# 📦 Base image selection |
| 2 | + |
| 3 | +Choosing a good base image is critically important when it comes to your overall container security. |
| 4 | + |
| 5 | +Some things to think about include: |
| 6 | + |
| 7 | +- **Who is providing the base image?** Will it be supported and maintained? |
| 8 | +- **What OS distribution is being used?** Can you configure the environment with the packages and dependencies your application requires? |
| 9 | +- **What packages and tools are provided?** Are the required tools available? Are there extras that aren't needed? |
| 10 | + |
| 11 | +Ideally, you want to keep the idea of "least privilege" - include only what's needed to run your application and nothing more. This reduces both maintenance and potential attack surfaces. |
| 12 | + |
| 13 | +> [!TIP] |
| 14 | +> If your organization is looking for minimal images with near-zero CVEs and enterprise-grade SLAs, check out [Docker Hardened Images](https://www.docker.com/products/hardened-images/). |
| 15 | +
|
| 16 | + |
| 17 | + |
| 18 | +## 🗺️ Choosing a base image |
| 19 | + |
| 20 | +The current `Dockerfile` has the following base image: |
| 21 | + |
| 22 | +```dockerfile |
| 23 | +FROM node:18 |
| 24 | +``` |
| 25 | + |
| 26 | +Based on the previous analysis, there were several issues. And, Node 18 is no longer supported. Time to update! |
| 27 | + |
| 28 | +1. Use the `docker scout recommendations` command to get recommendations for a newer base image: |
| 29 | + |
| 30 | + ```bash |
| 31 | + docker scout recommendations node-app:v1 |
| 32 | + ``` |
| 33 | + |
| 34 | + In the output, you will see quite a few options provided to you. |
| 35 | + |
| 36 | +2. As of writing this lab, Node 22 is the current LTS (Long Term Support) release. Scan through the list to find the two Node 22 options: |
| 37 | + |
| 38 | + ```plaintext no-copy-button |
| 39 | + Tag │ Details │ Pushed │ Vulnerabilities |
| 40 | + ───────────────────────────────┼─────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────── |
| 41 | + 22-slim │ Benefits: │ 1 day ago │ 0C 0H 1M 24L |
| 42 | + Major runtime version update │ • Image is smaller by 292 MB │ │ -2 -20 -21 -85 -4 |
| 43 | + Also known as: │ • Image contains 418 fewer packages │ │ |
| 44 | + • 22.20.0-slim │ • Major runtime version update │ │ |
| 45 | + • 22.20-slim │ • Tag was pushed more recently │ │ |
| 46 | + • lts-slim │ • Image introduces no new vulnerability but removes 128 │ │ |
| 47 | + • jod-slim │ • Tag is using slim variant │ │ |
| 48 | + • 22-bookworm-slim │ │ │ |
| 49 | + • lts-bookworm-slim │ Image details: │ │ |
| 50 | + • jod-bookworm-slim │ • Size: 79 MB │ │ |
| 51 | + • 22.20-bookworm-slim │ • Runtime: 22.20.0 │ │ |
| 52 | + • 22.20.0-bookworm-slim │ │ │ |
| 53 | + │ │ │ |
| 54 | + ... │ ... │ ... │ ... |
| 55 | + │ │ │ |
| 56 | + 22 │ Benefits: │ 1 day ago │ 0C 6H 3M 143L 4? |
| 57 | + Major runtime version update │ • Major runtime version update │ │ -2 -14 -19 +34 |
| 58 | + Also known as: │ • Tag was pushed more recently │ │ |
| 59 | + • 22.20.0 │ • Image has similar size │ │ |
| 60 | + • 22.20 │ • Image contains similar number of packages │ │ |
| 61 | + • lts │ │ │ |
| 62 | + • jod │ Image details: │ │ |
| 63 | + • lts-jod │ • Size: 399 MB │ │ |
| 64 | + • 22-bookworm │ • Runtime: 22.20.0 │ │ |
| 65 | + • jod-bookworm │ │ │ |
| 66 | + • lts-bookworm │ │ │ |
| 67 | + • 22.20-bookworm │ │ │ |
| 68 | + • 22.20.0-bookworm │ |
| 69 | + ``` |
| 70 | + |
| 71 | + You will see that one image is significantly smaller than the other (79MB vs 399MB) and includes far fewer packages (about 418 fewer). |
| 72 | + |
| 73 | + With this difference, the `-slim` variant also has far fewer vulnerabilities. |
| 74 | + |
| 75 | +3. In the `Dockerfile`, update the base image to use the `node:22-slim` image: |
| 76 | + |
| 77 | + ```dockerfile |
| 78 | + FROM node:22-slim |
| 79 | + ``` |
| 80 | + |
| 81 | +4. Build the image again using the new base image. This time though, you're going to add two additional flags: |
| 82 | +
|
| 83 | + ```bash |
| 84 | + docker build -t node-app:v2 --sbom=true --provenance=mode=max . |
| 85 | + ``` |
| 86 | +
|
| 87 | + - **`--sbom=true`** - automatically produce and attach a SBOM (Software Bill of Materials) to the image |
| 88 | + - **`--provenance=mode=max`** - automatically product and attach build provenance to the image. This includes details about how the image was built, its base image, and more. This is very valuable in multi-stage builds, as it captures details about all intermediate stages. |
| 89 | +
|
| 90 | +5. Before performing an analysis, take a look at the image size of the original image with this newer slim-variant-based image with the following `docker image ls` command: |
| 91 | +
|
| 92 | + ```bash |
| 93 | + docker image ls --filter=reference=node-app |
| 94 | + ``` |
| 95 | +
|
| 96 | + You should see output similar to the following, showing the image size reduction: |
| 97 | +
|
| 98 | + ```plaintext no-copy-button |
| 99 | + REPOSITORY TAG IMAGE ID CREATED SIZE |
| 100 | + node-app v2 029dbef31e69 2 minutes ago 363MB |
| 101 | + node-app v1 2fcf7b363939 About an hour ago 1.57GB |
| 102 | + ``` |
| 103 | +
|
| 104 | + Look at that! **1.57GB shrunk down to 363MB. That's a ~77% smaller image!** 🎉 |
| 105 | + |
| 106 | +6. Run another analysis on the image to determine if the problems have been fixed: |
| 107 | + |
| 108 | + ```bash |
| 109 | + docker scout quickview node-app:v2 |
| 110 | + ``` |
| 111 | + |
| 112 | + This time, when the analysis is performed, you should see it perform faster for two reasons: |
| 113 | + |
| 114 | + 1. **The image is smaller.** Smaller images will be analyzed faster. |
| 115 | + 2. **`SBOM obtained from attestation.`** Scout leverages the SBOM attached to an image, if it exists. Otherwise, it will index the image itself. Since you built the image with the SBOM flag, that indexing has already been completed! |
| 116 | + |
| 117 | + The output should now show a much better position: |
| 118 | + |
| 119 | + ```plaintext no-copy-button |
| 120 | + Target │ node-app:v2 │ 0C 5H 2M 28L |
| 121 | + digest │ 21616770631b │ |
| 122 | + Base image │ node:22-slim │ 0C 0H 1M 24L |
| 123 | + Updated base image │ node:24-slim │ 0C 0H 1M 24L |
| 124 | + ``` |
| 125 | + |
| 126 | + This indicates that there are still a few _high_ vulnerabilities. But, they are no longer coming from our base image. These must have been introduced by the application you packaged into the container image. |
0 commit comments