- git
- Docker Desktop 4.24.0 or greater
- Docker Hub account
$ORG
Docker Desktop must be configured to use containerd. In Docker Desktop, go to the Settings (⚙️ icon) > Features in development and make sure the box next to "Use containerd for pulling and storing images". If you changed the setting, click the "Apply & Restart" button.
Conventions:
$ORG
is the name of the Docker Hub account you will use. It can be a personal or a team one. Better if you have full ownership on it.
-
Clone the repository on your local machine
-
(optional) export
ORG
environment variable so you can more easily copy/paste commandsexport ORG=<your organization namespace>
-
Configure organization for Docker Scout
docker scout config organization $ORG
-
Copy
env.dist
file to.env
-
Edit
.env
and setNAMESPACE
to$ORG
-
Enroll your organization to Docker Scout
docker scout enroll $ORG
-
Checkout Hands-On #1
git checkout hands-on-1
-
Build demo images
docker compose --profile images build
This command will build two images we will explore. To know more about how they are built look at
./docker-compose.yml
and./backend/Dockerfile
that contains the build definitions.In case of network issues, you can also build the following image that is prebuilt and don't need extra dependencies.
docker compose --profile low_network build
git reset --hard hands-on-1
-
Open Docker Desktop and select the image
$ORG/scout-demo-service:v1
-
Take the time to explore the different information displayed on this page
- Image hierarchy, layers and the Images tab
- Vulnerabilities
- Packages
-
Select your base image and explore vulnerabilities specific to the base image. Then select "Recommendations for base image…" in the "Recommended fixes" dropdown in the upper right portion of the window.
-
Select Change base image and set the current image to 3.14
-
Open
frontend/Dockerfile
in your favorite file editor and apply the "Tag is preferred tag" recommendation, i.e., change theFROM
line toFROM alpine:3.18
-
(optional) Update the tag to
v2
indocker-compose.yml
-
Rebuild the image
docker compose --profile scout-demo-service build
-
Open the image inside Desktop and see the impact of your change
-
Run
docker scout cves
command against the image you just built:docker scout cves $ORG/scout-demo-service:v1
-
(optional) Explore the filters options from
docker scout cves
command -
(optional) See vulnerable packages only
docker scout cves --format only-packages --only-vuln-packages $ORG/scout-demo-service:v1
-
Explore base image recommendations using
docker scout recommendations
-> specify the tag upfront, like we selected it in Docker Desktop
docker scout recommendations --tag 3.14 $ORG/scout-demo-service:v1
-
Apply the "Tag is preferred tag" recommendation to the
frontend/Dockerfile
-
(optional) Update the tag to
v2
indocker-compose.yml
-
Rebuild the image
docker compose --profile scout-demo-service build
-
Run
docker scout cves
command against the image you just built and see the changes:docker scout cves $ORG/scout-demo-service:v2
-
Compare the two images to see the differences:
docker scout compare $ORG/scout-demo-service:v2 --to $ORG/scout-demo-service:v1
- Explore the still existing vulnerabilities: (Desktop or CLI)
- find vulnerable package
- find fix version
- Update
package.json
to upgrade the dependency - (optional) Update the tag to
v3
indocker-compose.yml
- Rebuild the image
- Explore the built image to see what changed
- using Desktop
- using CLI
-
Get a quick overview of your image, including vulnerabilities and recommendations
docker scout quickview $ORG/scout-demo-service:v1
Repeat the above steps for the $ORG/scout-demo-service-back:v1
image (or any other image you have).
git reset --hard hands-on-2
Registry - https://scout.docker.com Integration
Go to https://hub.docker.com and create repositories for the images you will push
$ORG/scout-demo-service
$ORG/scout-demo-service-back
Option 1: Use Docker Scout Dashboard
- Go to https://scout.docker.com
- Select your organization in the dropdown next to your user
- Open the settings menu (⚙️ icon) and select Repository settings
- Select the repository to enable and enable it
Option 2: Docker Hub Integration using the CLI
docker scout repo enable $ORG/scout-demo-service
docker scout repo enable $ORG/scout-demo-service-back
-
Push an image to Hub
docker push $ORG/scout-demo-service:v1
-
Browse https://scout.docker.com and see your images (this might take up to a few minutes)
Reproduce the exploratory steps from Hands-on #1 on https://scout.docker.com. Find vulnerabilities, package information and compare your images.
You can build and push the different versions of the images you previously built (with vulnerabilities or with fixes). Or simply push the fixes you built in the first hands-on exercise.
docker push $ORG/scout-demo-service:v3
-
Record the image to an environment (adapt to your registry)
docker scout environment staging registry://$ORG/scout-demo-service:v1
This will explicitly record the image that has been pushed to a registry, to the environment
staging
. -
Investigate environment information from the CLI
docker scout environment
docker scout environment staging
-
Compare your fixed local image to the one recorded as part of the
staging
environmentdocker scout compare local://$ORG/scout-demo-service:v3 --to-env staging
-
Browse https://scout.docker.com
- find images recorded to an environment
- find vulnerabilities and packages in an environment
- compare images between versions and/or environments
-
Record
v3
to the staging environmentdocker scout environment staging registry://$ORG/scout-demo-service:v3
-
Verify you have no vulnerabilities in
staging
at https://scout.docker.com > Vulnerabilities and select the staging environment -
Browse available integrations on https://scout.docker.com > Settings (⚙️ icon) > Integrations
git reset --hard hands-on-3
Remember the --tag
flag when we explore the base image recommendations or the dropdown to pick
the right one in the UI?
docker scout recommendations --tag 3.14 $ORG/scout-demo-service:v1
This tag was needed because the base image exists under different tag (latest
, 3
, 3.14
at least)
and the information contained in the image are not sufficient to pick the right one.
So let's fix that.
-
We have added a new command to the end of the
frontend/Dockerfile
so it gets rebuilt, but quicklyENV DUMMY=1
(this line was introduced when you reset to the
hands-on-3
tag above) -
Build a new image with the provenance attestation
( cd frontend && \ docker build -t $ORG/scout-demo-service:provenance \ --provenance=mode=max --push . )
-
Get recommendations about the image that has been pushed
docker scout recommendations registry://$ORG/scout-demo-service:provenance
This time you didn't provided the
--tag
and it picked the right one!Base image is
alpine:3.14
-
How did it do that? Let's look at the provenance.
docker buildx imagetools inspect $ORG/scout-demo-service:provenance \ --format '{{ json .Provenance.SLSA }}'
(note we are extracting an element called
SLSA
!) That is a lot of information. Let's focus on information about the base image. One place to see that is in the first element of thellbDefinition
array:docker buildx imagetools inspect $ORG/scout-demo-service:provenance \ --format '{{ json .Provenance.SLSA }}' | jq '.buildConfig.llbDefinition[0]'
(requires the
jq
command) See how the identifier has the exact SHA used as the base image?
Note on
push
andregistry://
We need to access the provenance attestation from the image. It's written at the level of the Image Index (same as for multi-arch images). The local Docker daemon doesn't allow currently to easily access those information.
But they are available from registries. So when pushed, all these extra information will be available and CLI or https://scout.docker.com tools will be able to use them.
When an image is used on the CLI or pushed to https://scout.docker.com one of the first steps is to index it. It means to go through the image and find all the packages for instance.
It also means this action might be performed multiple times, like if we want to see the vulnerabilities of the image from different computers.
But it's possible to generate SBOM at the build time and push it along with the image. That way, whatever the size of the initial image, we will only require the SBOM (enhanced with provenance if available) and it will make all the CLI actions faster and be sure the information displayed on https://scout.docker.com are the right ones.
-
Change the value of the environment variable at the end of
frontend/Dockerfile
so the image gets rebuilt and pushed, quicklyENV DUMMY=2
-
Build a new image with an SBOM attestation (and keep the provenance!)
( cd frontend && \ docker build -t $ORG/scout-demo-service:attests \ --sbom=generator=docker/scout-sbom-indexer \ --provenance=mode=max --push . )
-
Run any
docker scout
CLI command, e.g.,docker scout quickview $ORG/scout-demo-service:attests
and you should see:
✓ Provenance obtained from attestation ✓ SBOM obtained from attestation, 79 packages indexed
This means we only get the SBOM from the attestation, and we are not indexing locally the image anymore. It's faster and more accurate.
-
Extract the SBOM in
SPDX
format:docker scout sbom --format spdx registry://$ORG/scout-demo-service:attests
That is a lot of process. Let's look at some more useful format options.
-
Display packages of the image:
docker scout sbom --format list registry://$ORG/scout-demo-service:attests
-
Display vulnerable packages:
docker scout cves --format only-packages --only-vuln-packages registry://$ORG/scout-demo-service:attests
git reset --hard hands-on-4
Up to now, we've focused on single images. Now let's see how policy highlights concerns across all our images.
-
Build and push both images in the app.
( cd frontend && \ docker build -t $ORG/scout-demo-service:4 \ --sbom=generator=docker/scout-sbom-indexer \ --provenance=mode=max --push . )
( cd backend && \ docker build -t $ORG/scout-demo-service-back:4 \ --sbom=generator=docker/scout-sbom-indexer \ --provenance=mode=max --push . )
-
View policy status for a single image using the CLI
docker scout policy $ORG/scout-demo-service-back:4
-
Go to https://scout.docker.com and click on "Policies EA" at the top
-
Explore the "Critical and high vulnerabilities with fixes" policy and view the details on the
$ORG/scout-demo-service
-
From looking through the layers before, we know how to fix that. Let's update the base image in
frontend/Dockerfile
:FROM alpine:3.18
-
Now rebuild, incrementing the tag
( cd frontend && \ docker build -t $ORG/scout-demo-service:4.1 \ --sbom=generator=docker/scout-sbom-indexer \ --provenance=mode=max --load . )
-
Note we did not push the image in the previous step. Entirely locally, we can see if we have improve policy compliance using the
compare
command we used previously when focusing on fixing vulnerabilitiesdocker scout compare $ORG/scout-demo-service:4.1 --to $ORG/scout-demo-service:4
Scrolling past the Overview to the Policies section of the output, you can see you improved two policies without pushing images or running CI.
-
We see from the above command that while we are now compliant with the "All critical vulnerabilities", we are still not in compliance with the "Critical and high vulnerabilities with fixes" policy, there are still two high vulnerabilities. From our first hands-on earlier today, we know how to fix that too. Update the express dependency in
frontend/package.json
to version 4.17.3 and rebuild the image.( cd frontend && \ docker build -t $ORG/scout-demo-service:4.2 \ --sbom=generator=docker/scout-sbom-indexer \ --provenance=mode=max --load . )
-
Run the
compare
command again to see if we are fully compliantdocker scout compare $ORG/scout-demo-service:4.2 --to $ORG/scout-demo-service:4
-
That did the trick, so push the image
docker push $ORG/scout-demo-service:4.2
-
Go to https://scout.docker.com
Repeat the above steps for the $ORG/scout-demo-service-back
image (or any other image you have).