This repository contains the source code and resources for the 10 Docker Commandos workshop at JobRad in September 2025. The workshop will cover the following topics:
- 1️⃣ Docker Init
- 2️⃣ Docker Bake
- 3️⃣ Docker SBOM
- 4️⃣ SBOM Attestations
- 5️⃣ Docker Scout
- 6️⃣ Docker Debug
- 7️⃣ Docker Model Runner
- 8️⃣ Ask Gordon
- 9️⃣ Docker MCP Toolkit
- 🔟 CAgent
Installing the latest Docker Desktop will give you most of the commands. For more details, see the Pre-Workshop Installation Guide.
- Docker Desktop latest version
- Git
- A Bash shell (e.g., Git Bash, WSL, or any Linux terminal)
- A Docker Hub account (for pushing images)
On Windows, you can install Git Bash.
Main article: Dockerizing a Java 24 Project with Docker Init
Main article: JAVAPRO: How to Containerize a Java Application Securely
In case you want to skip Docker Init, you can use the flask-init directory, which contains the files created by Docker Init.
Docker Init is a command to initialize a Docker project with a Dockerfile and other necessary files:
Dockerfilecompose.yaml.dockerignoreREADME.Docker.md
The command doesn't use GenAI, so is deterministic, and employs best practices for Dockerfile creation.
Docker Init is available on Docker Desktop 4.27 or later and is generally available.
On the repo, go to the Flask example directory:
cd flaskThen, run the Docker Init command:
docker initThe command will ask you 4 questions, accept the defaults:
- ? What application platform does your project use? Python
- ? What version of Python do you want to use? 3.13.7
- ? What port do you want your app to listen on? 8000
- ? What is the command you use to run your app? gunicorn 'hello:app' --bind=0.0.0.0:8000
Then, start Docker Compose with build:
docker compose up --buildThe application will be available at http://localhost:8000.
- 1.1. If you want a more tricky example, try Dockerizing a Java 24 application using Docker Init. You can follow the instructions in the JAVAPRO article that I published in July 2025.
- 1.2. Compare the Dockerfile created for the Java application with the one created for the Python application. What are the differences?
Requirement: This step requires the Docker Init step to be completed first.
CLI reference: docker buildx bake
Docker Bake is to Docker Build, what Docker Compose is to Docker Run. It allows you to build multiple images at once, using a single command.
Docker Bake is a part of BuildKit, so it's open-source and available on Docker Desktop and Docker CE.
In the repo, go to the Flask example directory:
cd flaskThen, try to build the image using Docker Bake:
docker buildx bake -f docker-bake.hclThe command will build the image using the docker-bake.hcl file in the current directory. At the end, there is a Docker Desktop link shown in the output, with which you can see the build progress in the Docker Desktop UI.
Note. By default, docker buildx bake suffices. In this case, by executing the command without the -f docker-bake.hcl flag, the Baker will try to use both the HCL file and the Compose file as an input, and since they have clashing tags, the built image will have empty tag.
Also, there are probably some warnings about the Dockerfile.
- 2.1. Try to fix the warnings in the Dockerfile.
- 2.2. By changing the
docker-bake.hclfile, try building for multiple platforms, e.g.,linux/amd64andlinux/arm64. - 2.3. Try to build the image with a different Python version, e.g.,
3.13.1(the Python version is defined in the Dockerfile as a build argument,PYTHON_VERSION).
Requirement: This step requires the Docker Init step to be completed first.
In Docker Init step, we built an image with tag flask-server:latest when running docker compose up --build. Let's check the SBOM for this image.
Docker SBOM is integrated into Docker Desktop, but is also available for Docker CE as a CLI plugin that you need to install separately.
Note. Docker engineers want to remove docker sbom in favor of docker scout sbom, but the command is still available and there is not much attention to it. The docker sbom command is just a wrapper around the open-source syft than can be used directly, in case docker sbom is removed in the future.
To check the SBOM for the image, run:
docker sbom flask-server:latestThe output will show the SBOM in a table format. Try to export it to a SPDX file:
docker sbom --format spdx-json flask-server:latest > sbom.spdx.jsonIf you investigate the file, you will see that it contains a list of all the packages used in the image, their versions, and the licenses. It's especially useful for compliance and security purposes.
A more interesting example will be a C++ application.
Go to the C++ example directory:
cd cppThen, build the image:
docker build -t cpp-hello .Now, check the SBOM for the image:
docker sbom cpp-helloIt will say there are no packages in the image, because the image is built from a FROM scratch base image. But, in the build stage, we installed many packages, and a vulnerability in those packages can affect the final image.
We'll get back to this later.
- 3.1. Try to create a Docker Bake file for the C++ example, and build the image using Docker Bake.
- 3.2. Use
docker sbom --helpto check available formats for the SBOM output.
Requirement: This step requires the Docker SBOM step to be completed first.
Main article: DockerDocs: Supply-Chain Security for C++ Images
SBOM attestations are SBOMs generated for Docker images and uploaded with them to the registry.
In this step, we will use:
- SBOM attestations, that is a feature of BuildKit, to generate SBOMs during the build process (open-source).
- Docker Scout, to check the vulnerabilities in the image using the SBOM attestations (free tier).
SBOM attestations are generated during the build and pushed to the registry automatically:
docker buildx build --sbom=true --push -t aerabi/cpp-hello .Note. SBOM attestations are pushed to the registry only as a separate entry linked to the image, so to test them here we need to push the image to a registry. In this example, I used my own Docker Hub account, but you can use any registry that supports SBOM attestations, e.g., GitHub Container Registry, Amazon ECR, etc. Just make sure to change the image name accordingly.
Now, let's check the CVEs with Docker Scout (we will cover it in the next section):
docker scout cves aerabi/cpp-helloIt will say:
SBOM obtained from attestation, 0 packages found
The SBOM has no packages, because we built the image from a FROM scratch base image, and the build stage packages are not included in the SBOM. We can fix this by including the build stage packages in the SBOM.
To do that, we need to add the following line to the beginning of the Dockerfile:
ARG BUILDKIT_SBOM_SCAN_STAGE=trueThis line goes before the FROM line, and it tells Docker to include the build stage packages in the SBOM.
Now, rebuild the image with the new Dockerfile:
docker buildx build --sbom=true --push -t aerabi/cpp-hello:with-build-stage .Now, check the SBOM attestations for the image again:
docker scout cves aerabi/cpp-hello:with-build-stageIt will say:
SBOM of image already cached, 208 packages indexed
- 4.1. Here, the build command was super long. Try to create a Docker Bake file for the C++ example, and build the image using Docker Bake with SBOM attestations.
- 4.2. It's possible to check the generated SBOM attestations without using Docker Scout. One way would be writing the SBOM to disk instead of pushing it to the registry:
This is especially useful if you want to generate the SBOM, sign it using cosign, and then only push the signed SBOM to the registry.
docker buildx build --sbom=true --sbom-output=type=local,dest=. -t aerabi/cpp-hello:with-build-stage .
Requirement: This step requires the SBOM Attestations step to be completed first.
Docker Scout is a tool to analyze Docker images and check for vulnerabilities, misconfigurations, and other issues. It uses the SBOM attestations, when available, to provide more accurate results.
Docker Scout is available on Docker Desktop, and as a CLI plugin for Docker CE.
To check the vulnerabilities in the image, run:
docker scout cves aerabi/cpp-hello:with-build-stageYou can also check the vulnerabilities in the image using the Docker Desktop UI. Just go to the "Images" tab, select the image, and click on "Scout".
There are also recommendations for the image, which you can check by running:
docker scout recommendations flask-server- 5.1. Try to fix the vulnerabilities in the Flask image using the recommendations from Docker Scout.
Requirement: This step requires the Docker SBOM step to be completed first.
Docker Debug is a tool to debug Docker images and containers. It allows you to run a container with a debug shell, and inspect the image and the container.
Docker Debug is a paid feature available on Docker Desktop, so feel free to skip this step if you don't have a Pro, Team, or Business subscription.
Docker Debug can be used to investigate images or containers, when docker exec is not enough. For example, you can use it to inspect a scratch image:
docker debug aerabi/cpp-hello:with-build-stage- 6.1. Use Docker Debug to inspect the C++ image.
- 6.2. Use Docker Debug to inspect the Flask image.
- 6.3. Run the Flask image and inspect it with Docker Debug.
- 6.4. Install a tool like Vim using Docker Debug. The tools persist between different inspections. Try to inspect another container and check if the tool is still there.
Main article: Run GenAI Models Locally with Docker Model Runner
Docker Model Runner is a tool to run GenAI models locally using Docker. The feature is still in beta, but is available on Linux, macOS, and Windows.
- Linux: Docker CE
- macOS: Docker Desktop 4.40 or later
- Windows: Docker Desktop 4.41 or later
On Docker CE, you need to install the Docker Model Runner plugin:
sudo apt-get install docker-model-plugindocker model run ai/gemma3To use Docker Model Runner for developing GenAI applications, you can pull the models, and they will become available locally. Whenever an application needs to use a model, it can use the local models.
And example application is available here:
git clone https://github.com/aerabi/genai-app-demo
cd genai-app-demoEdit the file backend.env and make it match the following content:
BASE_URL: http://model-runner.docker.internal/engines/llama.cpp/v1/
MODEL: ai/gemma3
API_KEY: ${API_KEY:-dockermodelrunner}Then, run the application:
docker compose up -d- 7.1. Docker Compose now supports the
modelservice type (learn more). Try to adapt the Compose file in the repo to declare the model as a service.
Docker MCP Toolkit is a set of tools to manage install MCP servers seamlessly.
Open Docker Desktop, go to the "MCP Toolkit" tab. In the servers section, find "GitHub Official" and click the plus button to install it. It will ask for your GitHub token, which you can create in your GitHub account settings.
Then, you can connect to a client. To do that, in the "Clients" section, connect to a client that you're using. Examples are:
- Claude Desktop
- Cursor
- Visual Studio Code
For the sake of example, let's connect to Claude Desktop. You can install it in case you don't have it already.
Then, start the MCP toolkit server:
docker mcp gateway runThen, in Claude Desktop, ask questions about your GitHub repositories, e.g., "Explain the Dockerfile in my repository."
- 9.1. Try to connect to another client, e.g., Cursor or Visual Studio Code.
- 9.2. Try adding another MCP server, e.g., LinkedIn MCP Server, to ask about your LinkedIn data.
CAgent is introduced a few days ago, and is a multi-agent runtime that orchestrates multiple AI agents to perform complex tasks.
As it's rapidly evolving, please check the official repo for the latest instructions.

