From d4c883e55d67d50ed89267d3e58c30fb3e683b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mohammad-Ali=20A=27r=C3=A2bi?= Date: Wed, 4 Dec 2024 14:58:15 +0100 Subject: [PATCH 1/5] Add multi-stage builds to the C++ guide --- content/guides/cpp/_index.md | 5 +- content/guides/cpp/multistage.md | 109 +++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 content/guides/cpp/multistage.md diff --git a/content/guides/cpp/_index.md b/content/guides/cpp/_index.md index 1bfc404dca5..59face249fd 100644 --- a/content/guides/cpp/_index.md +++ b/content/guides/cpp/_index.md @@ -12,19 +12,20 @@ aliases: - /guides/language/cpp/ languages: [cpp] params: - time: 10 minutes + time: 20 minutes --- The C++ getting started guide teaches you how to create a containerized C++ application using Docker. In this guide, you'll learn how to: > **Acknowledgment** > -> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide. +> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for his contribution to this guide. - Containerize and run a C++ application - Set up a local environment to develop a C++ application using containers - Configure a CI/CD pipeline for a containerized C++ application using GitHub Actions - Deploy your containerized application locally to Kubernetes to test and debug your deployment +- Create multi-stage builds for your C++ application to optimize the size of your Docker image After completing the C++ getting started modules, you should be able to containerize your own C++ application based on the examples and instructions provided in this guide. diff --git a/content/guides/cpp/multistage.md b/content/guides/cpp/multistage.md new file mode 100644 index 00000000000..d99d1356ba9 --- /dev/null +++ b/content/guides/cpp/multistage.md @@ -0,0 +1,109 @@ +--- +title: Create a multi-stage build for your C++ application +linkTitle: Containerize your app +weight: 60 +keywords: C++, containerize, multi-stage +description: Learn how to create a multi-stage build for a C++ application. +aliases: +- /language/cpp/containerize/ +- /guides/language/cpp/containerize/ +--- + +## Prerequisites + +- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client. + +## Overview + +This section walks you through creating a multi-stage Docker build for a C++ application. +A multi-stage build is a Docker feature that allows you to use different base images for different stages of the build process, +so you can optimize the size of your final image and separate build dependencies from runtime dependencies. + +## Get the sample application + +We're using the same sample repository that you used in the previous sections of this guide. If you haven't already cloned the repository, clone it now: + +```bash +$ git clone https://github.com/dockersamples/c-plus-plus-docker.git +``` + +The example for this section is under the `hello` directory in the repository. Get inside it and take a look at the files: + +```bash +$ cd c-plus-plus-docker/hello +$ ls +``` + +You should see the following files: + +```text +Dockerfile hello.cpp +``` + +## Check the Dockerfile + +Open the `Dockerfile` in an IDE or text editor. The `Dockerfile` contains the instructions for building the Docker image. + +```Dockerfile +# Stage 1: Build stage +FROM ubuntu:latest AS build + +# Install build-essential for compiling C++ code +RUN apt-get update && apt-get install -y build-essential + +# Set the working directory +WORKDIR /app + +# Copy the source code into the container +COPY hello.cpp . + +# Compile the C++ code statically to ensure it doesn't depend on runtime libraries +RUN g++ -o hello hello.cpp -static + +# Stage 2: Runtime stage +FROM scratch + +# Copy the static binary from the build stage +COPY --from=build /app/hello /hello + +# Command to run the binary +CMD ["/hello"] +``` + +The `Dockerfile` has two stages: + +1. **Build stage**: This stage uses the `ubuntu:latest` image to compile the C++ code and create a static binary. +2. **Runtime stage**: This stage uses the `scratch` image, which is an empty image, to copy the static binary from the build stage and run it. + +## Build the Docker image + +To build the Docker image, run the following command in the `hello` directory: + +```bash +$ docker build -t hello . +``` + +The `-t` flag tags the image with the name `hello`. + +## Run the Docker container + +To run the Docker container, use the following command: + +```bash +$ docker run hello +``` + +You should see the output `Hello, World!` in the terminal. + +## Summary + +In this section, you learned how to create a multi-stage build for a C++ application. Multi-stage builds help you optimize the size of your final image and separate build dependencies from runtime dependencies. +In this example, the final image only contains the static binary and doesn't include any build dependencies. + +As the image has an empty base, the usual OS tools are also absent. So, for example, you can't run a simple `ls` command in the container: + +```bash +$ docker run hello ls +``` + +This makes the image very lightweight and secure. From 3d8e01fbad24ce31bee7f3929f7fe8d69622698c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mohammad-Ali=20A=27r=C3=A2bi?= Date: Wed, 4 Dec 2024 15:03:31 +0100 Subject: [PATCH 2/5] Fix the link to the new section --- content/guides/cpp/multistage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/guides/cpp/multistage.md b/content/guides/cpp/multistage.md index d99d1356ba9..0a93adea85d 100644 --- a/content/guides/cpp/multistage.md +++ b/content/guides/cpp/multistage.md @@ -5,8 +5,8 @@ weight: 60 keywords: C++, containerize, multi-stage description: Learn how to create a multi-stage build for a C++ application. aliases: -- /language/cpp/containerize/ -- /guides/language/cpp/containerize/ +- /language/cpp/multistage/ +- /guides/language/cpp/multistage/ --- ## Prerequisites From ff86f7f4e999b8e6447a7018631625069a7fcdbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mohammad-Ali=20A=27r=C3=A2bi?= Date: Tue, 25 Feb 2025 23:07:42 +0100 Subject: [PATCH 3/5] Move the multistage tutorial to the beginning --- content/guides/cpp/_index.md | 4 ++-- content/guides/cpp/containerize.md | 10 +++++----- content/guides/cpp/multistage.md | 9 ++++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/content/guides/cpp/_index.md b/content/guides/cpp/_index.md index 59face249fd..fd61f33ec6b 100644 --- a/content/guides/cpp/_index.md +++ b/content/guides/cpp/_index.md @@ -21,11 +21,11 @@ The C++ getting started guide teaches you how to create a containerized C++ appl > > Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for his contribution to this guide. -- Containerize and run a C++ application +- Containerize and run a C++ application using a multi-stage Docker build +- Build and run a C++ application using Docker Compose - Set up a local environment to develop a C++ application using containers - Configure a CI/CD pipeline for a containerized C++ application using GitHub Actions - Deploy your containerized application locally to Kubernetes to test and debug your deployment -- Create multi-stage builds for your C++ application to optimize the size of your Docker image After completing the C++ getting started modules, you should be able to containerize your own C++ application based on the examples and instructions provided in this guide. diff --git a/content/guides/cpp/containerize.md b/content/guides/cpp/containerize.md index 03042bc97e2..96c19430b88 100644 --- a/content/guides/cpp/containerize.md +++ b/content/guides/cpp/containerize.md @@ -1,9 +1,9 @@ --- title: Containerize a C++ application -linkTitle: Containerize your app +linkTitle: Build and run a C++ application using Docker Compose weight: 10 keywords: C++, containerize, initialize -description: Learn how to containerize a C++ application. +description: Learn how to use Docker Compose to build and run a C++ application. aliases: - /language/cpp/containerize/ - /guides/language/cpp/containerize/ @@ -15,17 +15,17 @@ aliases: ## Overview -This section walks you through containerizing and running a C++ application. +This section walks you through containerizing and running a C++ application, using Docker Compose. ## Get the sample application -Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository: +We're using the same sample repository that you used in the previous sections of this guide. If you haven't already cloned the repository, clone it now: ```console $ git clone https://github.com/dockersamples/c-plus-plus-docker.git ``` -You should now have the following contents in your `c-plus-plus-docker` +You should now have the following contents in your `c-plus-plus-docker` (root) directory. ```text diff --git a/content/guides/cpp/multistage.md b/content/guides/cpp/multistage.md index 0a93adea85d..0dbd3e35f58 100644 --- a/content/guides/cpp/multistage.md +++ b/content/guides/cpp/multistage.md @@ -1,7 +1,7 @@ --- title: Create a multi-stage build for your C++ application -linkTitle: Containerize your app -weight: 60 +linkTitle: Containerize your app using a multi-stage build +weight: 5 keywords: C++, containerize, multi-stage description: Learn how to create a multi-stage build for a C++ application. aliases: @@ -19,9 +19,12 @@ This section walks you through creating a multi-stage Docker build for a C++ app A multi-stage build is a Docker feature that allows you to use different base images for different stages of the build process, so you can optimize the size of your final image and separate build dependencies from runtime dependencies. +The standard practice for compiled languages like C++ is to have a build stage that compiles the code and a runtime stage that runs the compiled binary, +because the build dependencies are not needed at runtime. + ## Get the sample application -We're using the same sample repository that you used in the previous sections of this guide. If you haven't already cloned the repository, clone it now: +Let's use a simple C++ application that prints `Hello, World!` to the terminal. To do so, clone the sample repository to use with this guide: ```bash $ git clone https://github.com/dockersamples/c-plus-plus-docker.git From b98e40393d192e5de5cdc41461ee120e502ca736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mohammad-Ali=20A=27r=C3=A2bi?= Date: Wed, 26 Feb 2025 00:43:41 +0100 Subject: [PATCH 4/5] Add security page --- content/guides/cpp/_index.md | 1 + content/guides/cpp/security.md | 96 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 content/guides/cpp/security.md diff --git a/content/guides/cpp/_index.md b/content/guides/cpp/_index.md index fd61f33ec6b..9bfae826b19 100644 --- a/content/guides/cpp/_index.md +++ b/content/guides/cpp/_index.md @@ -26,6 +26,7 @@ The C++ getting started guide teaches you how to create a containerized C++ appl - Set up a local environment to develop a C++ application using containers - Configure a CI/CD pipeline for a containerized C++ application using GitHub Actions - Deploy your containerized application locally to Kubernetes to test and debug your deployment +- Use BuildKit to generate SBOM attestations during the build process After completing the C++ getting started modules, you should be able to containerize your own C++ application based on the examples and instructions provided in this guide. diff --git a/content/guides/cpp/security.md b/content/guides/cpp/security.md new file mode 100644 index 00000000000..919387631c2 --- /dev/null +++ b/content/guides/cpp/security.md @@ -0,0 +1,96 @@ +--- +title: Supply-chain security for C++ Docker images +linkTitle: Supply-chain security +weight: 60 +keywords: C++, security, multi-stage +description: Learn how to extract SBOMs from C++ Docker images. +aliases: +- /language/cpp/security/ +- /guides/language/cpp/security/ +--- + +## Prerequisites + +- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client. +- You have a Docker Desktop installed, with containerd enabled for pulling and storing images (it's a checkbox in Seetings > General). Otherwise, if you use Docker Engine: + - You have the [Docker SBOM CLI plugin](https://github.com/docker/sbom-cli-plugin) installed. To install it on Docker Engine, use the following command: + + ```bash + $ curl -sSfL https://raw.githubusercontent.com/docker/sbom-cli-plugin/main/install.sh | sh -s -- + ``` + + - You have the [Docker Scout CLI plugin](https://docs.docker.com/scout/install/) installed. To install it on Docker Engine, use the following command: + + ```bash + $ curl -sSfL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh | sh -s -- + ``` + + - You have [containerd enabled](https://docs.docker.com/engine/storage/containerd/) for Docker Engine. + +## Overview + +This section walks you through extracting Software Bill of Materials (SBOMs) from a C++ Docker image using the Docker SBOM CLI plugin. SBOMs provide a detailed list of all the components in a software package, including their versions and licenses. You can use SBOMs to track the provenance of your software and ensure that it complies with your organization's security and licensing policies. + +## Generate an SBOM + +Here we will use the Docker image that we built in the [Create a multi-stage build for your C++ application](/guides/language/cpp/multistage/) guide. If you haven't already built the image, follow the steps in that guide to build the image. +The image is named `hello`. To generate an SBOM for the `hello` image, run the following command: + +```bash +$ docker sbom hello +``` + +The command will say "No packages discovered". This is because the final image is a scratch image and doesn't have any packages. +Let's try again with Docker Scout: + +```bash +$ docker scout sbom --format=list hello +``` + +This command will tell you the same thing. + +## Generate an SBOM attestation + +The SBOM can be generated during the build process and "attached" to the image. This is called an SBOM attestation. +To generate an SBOM attestation for the `hello` image, first let's change the Dockerfile: + +```Dockerfile +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +FROM ubuntu:latest AS build + +RUN apt-get update && apt-get install -y build-essential + +WORKDIR /app + +COPY hello.cpp . + +RUN g++ -o hello hello.cpp -static + +# -------------------- +FROM scratch + +COPY --from=build /app/hello /hello + +CMD ["/hello"] +``` + +The first line `ARG BUILDKIT_SBOM_SCAN_STAGE=true` enables SBOM scanning in the build stage. +Now, build the image with the following command: + +```bash +$ docker buildx build --sbom=true -t hello:sbom . +``` + +This command will build the image and generate an SBOM attestation. You can verify that the SBOM is attached to the image by running the following command: + +```bash +$ docker scout sbom --format=list hello:sbom +``` + +Note that the normal `docker sbom` command will not load the SBOM attestation. + +## Summary + +In this section, you learned how to generate SBOM attestation for a C++ Docker image during the build process. +The normal image scanners will not be able to generate SBOMs from scratch images. \ No newline at end of file From d358ae055ee922fd4081ea92b72d44bce37dbdbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mohammad-Ali=20A=27r=C3=A2bi?= Date: Wed, 26 Feb 2025 22:42:14 +0100 Subject: [PATCH 5/5] Address Craig's comments --- content/guides/cpp/_index.md | 2 +- content/guides/cpp/security.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/guides/cpp/_index.md b/content/guides/cpp/_index.md index 9bfae826b19..85f317765e3 100644 --- a/content/guides/cpp/_index.md +++ b/content/guides/cpp/_index.md @@ -19,7 +19,7 @@ The C++ getting started guide teaches you how to create a containerized C++ appl > **Acknowledgment** > -> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for his contribution to this guide. +> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for their contribution to this guide. - Containerize and run a C++ application using a multi-stage Docker build - Build and run a C++ application using Docker Compose diff --git a/content/guides/cpp/security.md b/content/guides/cpp/security.md index 919387631c2..733c23c9a82 100644 --- a/content/guides/cpp/security.md +++ b/content/guides/cpp/security.md @@ -12,7 +12,7 @@ aliases: ## Prerequisites - You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client. -- You have a Docker Desktop installed, with containerd enabled for pulling and storing images (it's a checkbox in Seetings > General). Otherwise, if you use Docker Engine: +- You have a Docker Desktop installed, with containerd enabled for pulling and storing images (it's a checkbox in **Settings** > **General**). Otherwise, if you use Docker Engine: - You have the [Docker SBOM CLI plugin](https://github.com/docker/sbom-cli-plugin) installed. To install it on Docker Engine, use the following command: ```bash