diff --git a/Dockerfile b/Dockerfile index f5432d03461a..199c5e414305 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,42 +7,27 @@ ARG ALPINE_VERSION=3.20 ARG GO_VERSION=1.23 # HTMLTEST_VERSION sets the wjdp/htmltest version for HTML testing ARG HTMLTEST_VERSION=0.17.0 +# HUGO_VERSION sets the version of Hugo to build the site with +ARG HUGO_VERSION=0.136.2 -# base is the base stage with build dependencies -FROM golang:${GO_VERSION}-alpine AS base -WORKDIR /src -RUN apk --update add nodejs npm git gcompat - -# node installs Node.js dependencies -FROM base AS node -COPY package*.json . -ENV NODE_ENV=production -RUN npm install - -# hugo downloads and extracts the Hugo binary -FROM base AS hugo -ARG HUGO_VERSION=0.134.3 -ARG TARGETARCH -WORKDIR /tmp/hugo -RUN wget -O "hugo.tar.gz" "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz" -RUN tar -xf "hugo.tar.gz" hugo - -# build-base is the base stage for building the site -FROM base AS build-base -COPY --from=hugo /tmp/hugo/hugo /bin/hugo -COPY --from=node /src/node_modules /src/node_modules +# build-base is the base stage used for building the site +FROM ghcr.io/gohugoio/hugo:v${HUGO_VERSION} AS build-base +USER root +ENV NODE_ENV="production" +RUN --mount=source=package.json,target=package.json \ + --mount=source=package-lock.json,target=package-lock.json \ + --mount=type=cache,target=/root/.npm \ + npm ci COPY . . -# dev is for local development with Docker Compose -FROM build-base AS dev - # build creates production builds with Hugo FROM build-base AS build # HUGO_ENV sets the hugo.Environment (production, development, preview) -ARG HUGO_ENV +ARG HUGO_ENV="development" # DOCS_URL sets the base URL for the site -ARG DOCS_URL -RUN hugo --gc --minify -d /out -e $HUGO_ENV -b $DOCS_URL +ARG DOCS_URL="https://docs.docker.com" +RUN --mount=type=cache,target=/cache \ + hugo --gc --minify -d /out -e $HUGO_ENV -b $DOCS_URL # lint lints markdown files FROM davidanson/markdownlint-cli2:v0.14.0 AS lint @@ -122,7 +107,7 @@ fi EOT # pagefind installs the Pagefind runtime -FROM base AS pagefind +FROM node:alpine${ALPINE_VERSION} AS pagefind ARG PAGEFIND_VERSION=1.1.1 COPY --from=build /out ./public RUN --mount=type=bind,src=pagefind.yml,target=pagefind.yml \ diff --git a/archetypes/guides.md b/archetypes/guides.md new file mode 100644 index 000000000000..e92dea738922 --- /dev/null +++ b/archetypes/guides.md @@ -0,0 +1,13 @@ +--- +title: '{{ replace .File.ContentBaseName `-` ` ` | humanize }}' +# linkTitle: A shorter, alternative title +description: # Meta description for SEO. +summary: | # A summary of what's in this guide + In this guide, ... +languages: [] # Programming languages used +products: [] # Docker products involved +levels: [] # Experience level(s) of the intended audience (beginner|intermediate|advanced) +subjects: [] # What's it about? +params: + # time: 10 minutes +--- diff --git a/assets/images/guides/bake.webp b/assets/images/guides/bake.webp new file mode 100644 index 000000000000..7080871bd84d Binary files /dev/null and b/assets/images/guides/bake.webp differ diff --git a/compose.yaml b/compose.yaml index c8b7dc5f823b..27b072077494 100644 --- a/compose.yaml +++ b/compose.yaml @@ -2,7 +2,7 @@ services: server: build: context: . - target: dev + target: build-base ports: - "1313:1313" entrypoint: ["hugo", "server", "--bind", "0.0.0.0"] @@ -11,5 +11,3 @@ services: - action: sync path: . target: /src - ignore: - - node_modules/ \ No newline at end of file diff --git a/content/contribute/guides.md b/content/contribute/guides.md new file mode 100644 index 000000000000..ac775387465a --- /dev/null +++ b/content/contribute/guides.md @@ -0,0 +1,260 @@ +--- +title: Guidelines for writing Docker usage guides +linkTitle: Write a Docker guide +description: Learn how to write guides for learning about Docker, with Docker. +--- + + + +This guide provides instructions and best practices for writing tutorial-style +usage guides that help users achieve specific goals using Docker. These guides +will be featured in the [guides section](/guides/_index.md) of the website, +alongside our product manuals and reference materials. + +Our documentation is written in Markdown, with YAML front matter for metadata. +We use [Hugo](https://gohugo.io) to build the website. For more information +about how to write content for Docker docs, refer to our +[CONTRIBUTING.md](https://github.com/docker/docs/tree/main/CONTRIBUTING.md). + +## Purpose of the guides + +Our usage guides aim to: + +- Educate users on how to leverage Docker in various contexts. +- Provide practical, hands-on experience through step-by-step tutorials. +- Help users achieve specific goals relevant to their interests or projects. + +## Audience + +- Experience levels: From beginners to advanced users. +- Roles: Developers, system administrators, DevOps engineers, and more. +- Technologies: Various programming languages and frameworks. + +## Metadata for guides + +Each guide must include a metadata section at the beginning of the document. +This metadata helps users discover and filter guides based on their interests +and needs. + +### Example metadata format + +```yaml +--- +title: Deploy a machine learning model with Docker +linkTitle: Docker for ML deployment +description: Learn how to containerize and deploy a machine learning model using Docker. +summary: | + This guide walks you through the steps to containerize a machine learning + model and deploy it using Docker, enabling scalable and portable AI + solutions. +languages: [python] +subjects: [machine-learning, deployment] +levels: [intermediate] +params: + time: 30 minutes +--- +``` + +### Metadata fields + +- `title` (required): The main title of the guide in sentence case. +- `linkTitle` (optional): A shorter title used in navigation menus. +- `description` (required): A concise description for SEO purposes. +- `summary` (required): A brief overview of the guide's content. +- `languages` (optional): List of programming languages used. +- `subjects` (optional): Domains or subject areas covered. +- `levels` (optional): Intended audience experience level (`beginner`, `intermediate`, `advanced`). +- `products` (optional): List of programming languages used. +- `params` + - `time` (optional): Estimated reading or completion time. + +The `languages`, `subjects`, `levels`, and `products` keys are taxonomies, and +the values are used to associate the page with the filter options on the guides +landing page. + +## Document structure + +Our guides emphasize learning by doing. Depending on the type of guide, the +structure may vary to best suit the content and provide a smooth learning +experience. + +All guides live directly under the `content/guides/` directory in the Docker +docs repository. Guides can either be a single page or multiple pages. In the +case of multi-page guides, every page is a step in a sequential workflow. + +If you're creating a single-page guide, create a single markdown file in the +guides directory: + +```bash +# Create the file +touch content/guides/my-docker-guide.md +# or if you have Hugo installed: +hugo new content/guides/my-docker-guide.md +``` + +To create a multi-page guide, create a directory where each page is a markdown +file, with an `_index.md` file representing the introduction to the guide. + +```bash +# Create the index page for the guide +mkdir content/guides/my-docker-guide.md +touch content/guides/my-docker-guide/_index.md +# or if you have Hugo installed: +hugo new content/guides/my-docker-guide/_index.md +``` + +Then create the pages for the guide under `content/guides//.md` as +needed. The [metadata](#metadata-for-guides) lives on the `_index.md` page (you +don't need to assign metadata to individual pages). + +### Guides for specific frameworks or languages + +For guides that demonstrate how to use Docker with a particular framework or +programming language, consider the following outline: + +1. **Introduction** + - Briefly introduce the framework or language in the context of Docker. + - Explain what the user will achieve by the end of the guide. + - List required software, tools, and knowledge. +2. **Development setup** + - Guide the user through setting up a development environment. + - Include instructions on writing or obtaining sample code. + - Show how to run containers for local development. +3. **Building the application** + - Explain how to create a Dockerfile tailored to the application. + - Provide step-by-step instructions for building the Docker image. + - If applicable, show how to test the application using Docker. +4. **Deploying with Docker** + - Show how to run the application in a Docker container. + - Discuss configuration options and best practices. +5. **Best practices and conclusions** + - Offer tips for optimizing Docker usage with the framework or language. + - Summarize key takeaways, suggest next steps, and further reading. + +### Use-case guides + +For guides focused on accomplishing a specific goal or use case with Docker +(e.g., deploying a machine learning model), use a flexible outline that ensures +a logical flow. + +The following outline is an example. The structure should be adjusted to best +fit the content and ensure a clear, logical progression. Depending on the +subject matter of your use-case guide, the exact structure will vary. + +1. **Introduction** + - Describe the problem or goal. + - Explain the benefits of using Docker in this context. +2. **Prerequisites** + - List required tools, technologies, and prior knowledge. +3. **Setup** + - Provide instructions for setting up the environment. + - Include any necessary configuration steps. +4. **Implementation** + - Walk through the process step by step. + - Use code snippets and explanations to illustrate key points. +5. **Running or deploying the application** + - Guide the user on how to execute or deploy the solution. + - Discuss any verification steps to ensure success. +6. **Conclusion** + - Recap what was achieved. + - Suggest further reading or advanced topics. + +## Example code + +If you create an example repository with source code to accompany your guide, +we strongly encourage you to publish that repository under the +[dockersamples](https://github.com/dockersamples) organization on GitHub. +Publishing your source code under this organization, rather than your personal +account, ensures that the source code remains accessible to the maintainers of +the documentation site after publishing. In the event of a bug or an issue in +the guide, the documentation team can more easily update the guide and its +corresponding example repository. + +Hosting the examples in the official samples namespace also helps secure trust +with users who are reading the guide. + +### Publish a repository under `dockersamples` + +To publish your repository under the `dockersamples` organization, use the +[dockersamples template](https://github.com/dockersamples/sample-app-template) +to initiate a sample repository under your personal namespace. When you've +finished drafting your content and opened your pull request for the +documentation, we can transfer the repository to the dockersamples +organization. + +## Writing style + +Use [sentence case](/contribute/style/formatting.md#capitalization) for all +headings and titles. This means only the first word and proper nouns are +capitalized. + +### Voice and tone + +- **Clarity and conciseness**: Use simple language and short sentences to convey information effectively. +- **Active voice**: Write in the active voice to engage the reader (e.g., "Run the command" instead of "The command should be run"). +- **Consistency**: Maintain a consistent tone and terminology throughout the guide. + +For detailed guidelines, refer to our [voice and tone documentation](/contribute/style/voice-tone.md). + +### Formatting conventions + +- **Headings**: Use H2 for main sections and H3 for subsections, following sentence case. +- **Code examples**: Provide complete, working code snippets with syntax highlighting. +- **Lists and steps**: Use numbered lists for sequential steps and bullet points for non-sequential information. +- **Emphasis**: Use bold for UI elements (e.g., **Button**), and italics for emphasis. +- **Links**: Use descriptive link text (e.g., [Install Docker](/get-started/get-docker.md)). + +For more details, see our [content formatting guidelines](/contribute/style/formatting.md) +and [grammar and style rules](/contribute/style/grammar.md). + +## Best practices + +- **Test all instructions** + - Ensure all code and commands work as expected. + - Verify that the guide can be followed successfully from start to finish. +- **Relevance** + - Focus on real-world applications and scenarios. + - Keep the content up-to-date with the latest Docker versions. +- **Troubleshooting tips** + - Anticipate common issues and provide solutions or references. +- **Visual aids** + - Include screenshots or diagrams where they enhance understanding. + - Add captions and alt text for accessibility. +- **Third-party tools** + - Avoid requiring the user to install third-party tools or modify their local development environment. + - Prefer using containerized tools and methods where applicable (e.g. `docker exec`). + - Some tools are reasonable to assume as installed or prerequisites for guides, such as Node.js and npm. Use your better judgement. + +## Additional resources + +- **Existing guides** + - Refer to [Docker Guides](/guides/_index.md) for examples and inspiration. +- **Style guides** + - [Voice and tone](/contribute/style/voice-tone.md) + - [Content formatting](/contribute/style/formatting.md) + - [Grammar and style](/contribute/style/grammar.md) + +## Submission process + +- **Proposal** + - Raise an issue on the [Docker documentation GitHub repository](https://github.com/docker/docs) + with a request to add a new guide. + - Once the proposal has been accepted, start writing your guide by forking + the repository and creating a branch for your work. + + > [!NOTE] + > Avoid contributing from the `main` branch of your fork, since it makes it + > more difficult for maintainers to help you fix any issues that may arise. + +- **Review** + - Proofread your guide for grammar, clarity, and adherence to the guidelines. + - Once your draft is ready, raise a pull request, with a reference to the + original issue. + - The Docker documentation team and subject matter experts will review your + submission and provide feedback on the pull request directly. +- **Publishing** + - Your guide will be published on the Docker documentation website when the + reviewers have approved and merged your pull request. + +Thank you for contributing to the Docker community. Your expertise helps users +worldwide harness the power of Docker. diff --git a/content/get-started/workshop/06_bind_mounts.md b/content/get-started/workshop/06_bind_mounts.md index 9f2a20098774..8a825759c73c 100644 --- a/content/get-started/workshop/06_bind_mounts.md +++ b/content/get-started/workshop/06_bind_mounts.md @@ -59,7 +59,7 @@ filesystem you can share with containers. For details about accessing the settin bind mount. {{< tabs >}} - {{< tab name="Mac / Linux / PowerShell" >}} + {{< tab name="Mac / Linux" >}} ```console $ docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash @@ -79,6 +79,13 @@ filesystem you can share with containers. For details about accessing the settin $ docker run -it --mount type=bind,src="/$(pwd)",target=/src ubuntu bash ``` + {{< /tab >}} + {{< tab name="PowerShell" >}} + + ```console + $ docker run -it --mount "type=bind,src=$($pwd),target=/src" ubuntu bash + ``` + {{< /tab >}} {{< /tabs >}} diff --git a/content/guides/bake/index.md b/content/guides/bake/index.md new file mode 100644 index 000000000000..c3eafa98d12c --- /dev/null +++ b/content/guides/bake/index.md @@ -0,0 +1,518 @@ +--- +title: Mastering multi-platform builds, testing, and more with Docker Buildx Bake +linkTitle: Mastering Docker Buildx Bake +description: > + Learn how to manage simple and complex build configurations with Buildx Bake. +summary: > + Learn to automate Docker builds and testing with declarative configurations using Buildx Bake. +languages: [go] +subjects: [devops] +levels: [advanced] +params: + time: 30 minutes + featured: true + image: /images/guides/bake.webp +--- + +This guide demonstrates how to simplify and automate the process of building +images, testing, and generating build artifacts using Docker Buildx Bake. By +defining build configurations in a declarative `docker-bake.hcl` file, you can +eliminate manual scripts and enable efficient workflows for complex builds, +testing, and artifact generation. + +## Assumptions + +This guide assumes that you're familiar with: + +- Docker +- [Buildx](/manuals/build/concepts/overview.md#buildx) +- [BuildKit](/manuals/build/concepts/overview.md#buildkit) +- [Multi-stage builds](/manuals/build/building/multi-stage.md) +- [Multi-platform builds](/manuals/build/building/multi-platform.md) + +## Prerequisites + +- A recent version of Docker is installed on your machine. +- Git is installed for cloning repositories. +- You're using the [containerd](/manuals/desktop/containerd.md) image store. + +## Introduction + +This guide uses an example project to demonstrate how Docker Buildx Bake can +streamline your build and test workflows. This repository includes both a +Dockerfile and `docker-bake.hcl`, giving you a ready-to-use setup to try out +Bake commands. + +Start by cloning the example repository: + +```bash +git clone https://github.com/dvdksn/bakeme.git +cd bakeme +``` + +The Bake file, `docker-bake.hcl`, defines the build targets in a declarative +syntax, using targets and groups, allowing you to manage complex builds +efficiently. + +Here's what the Bake file looks like out-of-the-box: + +```hcl +target "default" { + target = "image" + tags = [ + "bakeme:latest", + ] + attest = [ + "type=provenance,mode=max", + "type=sbom", + ] + platforms = [ + "linux/amd64", + "linux/arm64", + "linux/riscv64", + ] +} +``` + +The `target` keyword defines a build target for Bake. The `default` target +defines the target to build when no specific target is specified on the command +line. Here's a quick summary of the options for the `default` target: + +- `target`: The target build stage in the Dockerfile. +- `tags`: Tags to assign to the image. +- `attest`: [Attestations](/manuals/build/metadata/attestations/_index.md) to attach to the image. + + > [!TIP] + > The attestations provide metadata such as build provenance, which tracks + > the source of the image's build, and an SBOM (Software Bill of Materials), + > useful for security audits and compliance. + +- `platforms`: Platform variants to build. + +To execute this build, simply run the following command in the root of the +repository: + +```console +$ docker buildx bake +``` + +With Bake, you avoid long, hard-to-remember command-line incantations, +simplifying build configuration management by replacing manual, error-prone +scripts with a structured configuration file. + +For contrast, here's what this build command would look like without Bake: + +```console +$ docker buildx build \ + --target=image \ + --tag=bakeme:latest \ + --provenance=true \ + --sbom=true \ + --platform=linux/amd64,linux/arm64,linux/riscv64 \ + . +``` + +## Testing and linting + +Bake isn't just for defining build configurations, and running builds. You can +also use Bake to run your tests, effectively using BuildKit as a task runner. +Running your tests in containers is great for ensuring reproducible results. +This section shows how to add two types of tests: + +- Unit testing with `go test`. +- Linting for style violations with `golangci-lint`. + +In Test-Driven Development (TDD) fashion, start by adding a new `test` target +to the Bake file: + +```hcl +target "test" { + target = "test" + output = ["type=cacheonly"] +} +``` + +> [!TIP] +> Using the `type=cacheonly` ensures that the build output is effectively +> discarded; the layers are saved to BuildKit's cache, but Buildx will not +> attempt to load the result to the Docker Engine's image store. +> +> For test runs, you don't need to export the build output — only the test +> execution matters. + +To execute this Bake target, run `docker buildx bake test`. At this time, +you'll receive an error indicating that the `test` stage does not exist in the +Dockerfile. + +```console +$ docker buildx bake bake test +[+] Building 1.2s (6/6) FINISHED + => [internal] load local bake definitions +... +ERROR: failed to solve: target stage "test" could not be found +``` + +To satisfy this target, add the corresponding Dockerfile target. The `test` +stage here is based on the same base stage as the build stage. + +```dockerfile +FROM base AS test +RUN --mount=target=. \ + --mount=type=cache,target=/go/pkg/mod \ + go test . +``` + +> [!TIP] +> The [`--mount=type=cache` directive](/manuals/build/cache/optimize.md#use-cache-mounts) +> caches Go modules between builds, improving build performance by avoiding the +> need to re-download dependencies. This shared cache ensures that the same +> dependency set is available across build, test, and other stages. + +Now, running the `test` target with Bake will evaluate the unit tests for this +project. If you want to verify that it works, you can make an arbitrary change +to `main_test.go` to cause the test to fail. + +Next, to enable linting, add another target to the Bake file, named `lint`: + +```hcl +target "lint" { + target = "lint" + output = ["type=cacheonly"] +} +``` + +And in the Dockerfile, add the build stage. This stage will use the official +`golangci-lint` image on Docker Hub. + +> [!TIP] +> Because this stage relies on executing an external dependency, it's generally +> a good idea to define the version you want to use as a build argument. This +> lets you more easily manage version upgrades in the future by collocating +> dependency versions to the beginning of the Dockerfile. + +```dockerfile {hl_lines=[2,"6-8"]} +ARG GO_VERSION="1.23" +ARG GOLANGCI_LINT_VERSION="1.61" + +#... + +FROM golangci/golangci-lint:v${GOLANGCI_LINT_VERSION}-alpine AS lint +RUN --mount=target=.,rw \ + golangci-lint run +``` + +Lastly, to enable running both tests simultaneously, you can use the `groups` +construct in the Bake file. A group can specify multiple targets to run with a +single invocation. + +```hcl +group "validate" { + targets = ["test", "lint"] +} +``` + +Now, running both tests is as simple as: + +```console +$ docker buildx bake validate +``` + +## Building variants + +Sometimes you need to build more than one version of a program. The following +example uses Bake to build separate "release" and "debug" variants of the +program, using [matrices](/manuals/build/bake/matrices.md). Using matrices lets +you run parallel builds with different configurations, saving time and ensuring +consistency. + +A matrix expands a single build into multiple builds, each representing a +unique combination of matrix parameters. This means you can orchestrate Bake +into building both the production and development build of your program in +parallel, with minimal configuration changes. + +The example project for this guide is set up to use a build-time option to +conditionally enable debug logging and tracing capabilities. + +- If you compile the program with `go build -tags="debug"`, the additional + logging and tracing capabilities are enabled (development mode). +- If you build without the `debug` tag, the program is compiled with a default + logger (production mode). + +Update the Bake file by adding a matrix attribute which defines the variable +combinations to build: + +```diff {title="docker-bake.hcl"} + target "default" { ++ matrix = { ++ mode = ["release", "debug"] ++ } ++ name = "image-${mode}" + target = "image" +``` + +The `matrix` attribute defines the variants to build ("release" and "debug"). +The `name` attribute defines how the matrix gets expanded into multiple +distinct build targets. In this case, it's relatively simple. The matrix +attribute expands the build into two workflows: `image-release` and +`image-debug`, each using different configuration parameters. + +Next, when building the development variant, we'll pass in a `BUILD_TAGS` +argument with the value of the matrix variable, which we'll later consume in +the Dockerfile. + +```diff {title="docker-bake.hcl"} + target = "image" ++ args = { ++ BUILD_TAGS = mode ++ } + tags = [ +``` + +You'll also want to change how the image tags are assigned to these builds. +Currently, both matrix paths would generate the same image tag names, and +overwrite each other. Update the `tags` attribute use a conditional operator to +set the tag depending on the matrix variable value. + +```diff {title="docker-bake.hcl"} + tags = [ +- "bakeme:latest", ++ mode == "release" ? "bakeme:latest" : "bakeme:dev" + ] +``` + +- If `mode` is `release`, the tag name is `bakeme:latest` +- If `mode` is `debug`, the tag name is `bakeme:dev` + +Finally, update the Dockerfile to consume the `BUILD_TAGS` argument during the +compilation stage. When the `-tags="${BUILD_TAGS}"` option evaluates to +`-tags="debug"`, the compiler uses the `configureLogging` function in the +[`debug.go`](https://github.com/dvdksn/bakeme/blob/75c8a41e613829293c4bd3fc3b4f0c573f458f42/debug.go#L1) +file. + +```diff {title=Dockerfile} + # build compiles the program + FROM base AS build +-ARG TARGETOS TARGETARCH ++ARG TARGETOS TARGETARCH BUILD_TAGS + ENV GOOS=$TARGETOS + ENV GOARCH=$TARGETARCH + RUN --mount=target=. \ + --mount=type=cache,target=/go/pkg/mod \ +- go build -o "/usr/bin/bakeme" . ++ go build -tags="${BUILD_TAGS}" -o "/usr/bin/bakeme" . +``` + +That's all. With these changes, your `docker buildx bake` command now builds +two multi-platform image variants. You can introspect the canonical build +configuration that Bake generates using the `docker buildx bake --print` +command. Running this command shows that Bake will run a `default` group with +two targets with different build arguments and image tags. + +```json {collapse=true} +{ + "group": { + "default": { + "targets": ["image-release", "image-debug"] + } + }, + "target": { + "image-debug": { + "attest": ["type=provenance,mode=max", "type=sbom"], + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "BUILD_TAGS": "debug" + }, + "tags": ["bakeme:dev"], + "target": "image", + "platforms": ["linux/amd64", "linux/arm64", "linux/riscv64"] + }, + "image-release": { + "attest": ["type=provenance,mode=max", "type=sbom"], + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "BUILD_TAGS": "release" + }, + "tags": ["bakeme:latest"], + "target": "image", + "platforms": ["linux/amd64", "linux/arm64", "linux/riscv64"] + } + } +} +``` + +Factoring in all of the platform variants as well, this means that the build +configuration generates 6 different images. + +```console +$ docker buildx bake +$ docker image ls --tree + +IMAGE ID DISK USAGE CONTENT SIZE USED +bakeme:dev f7cb5c08beac 49.3MB 28.9MB +├─ linux/riscv64 0eae8ba0367a 9.18MB 9.18MB +├─ linux/arm64 56561051c49a 30MB 9.89MB +└─ linux/amd64 e8ca65079c1f 9.8MB 9.8MB + +bakeme:latest 20065d2c4d22 44.4MB 25.9MB +├─ linux/riscv64 7cc82872695f 8.21MB 8.21MB +├─ linux/arm64 e42220c2b7a3 27.1MB 8.93MB +└─ linux/amd64 af5b2dd64fde 8.78MB 8.78MB +``` + +## Exporting build artifacts + +Exporting build artifacts like binaries can be useful for deploying to +environments without Docker or Kubernetes. For example, if your programs are +meant to be run on user's local machine. + +> [!TIP] +> The techniques discussed in this section can be applied not only to build +> output like binaries, but to any type of artifacts, such as test reports. + +With programming languages like Go and Rust where the compiled binaries are +usually portable, creating alternate build targets for exporting only the +binary is trivial. All you need to do is add an empty stage in the Dockerfile +containing nothing but the binary that you want to export. + +First, let's add a quick way to build a binary for your local platform and +export it to `./build/local` on the local filesystem. + +In the `docker-bake.hcl` file, create a new `bin` target. In this stage, set +the `output` attribute to a local filesystem path. Buildx automatically detects +that the output looks like a filepath, and exports the results to the specified +path using the [local exporter](/manuals/build/exporters/local-tar.md). + +```hcl +target "bin" { + target = "bin" + output = ["build/bin"] + platforms = ["local"] +} +``` + +Notice that this stage specifies a `local` platform. By default, if `platforms` +is unspecified, builds target the OS and architecture of the BuildKit host. If +you're using Docker Desktop, this often means builds target `linux/amd64` or +`linux/arm64`, even if your local machine is macOS or Windows, because Docker +runs in a Linux VM. Using the `local` platform forces the target platform to +match your local environment. + +Next, add the `bin` stage to the Dockerfile which copies the compiled binary +from the build stage. + +```dockerfile +FROM scratch AS bin +COPY --from=build "/usr/bin/bakeme" / +``` + +Now you can export your local platform version of the binary with `docker +buildx bake bin`. For example, on macOS, this build target generates an +executable in the [Mach-O format](https://en.wikipedia.org/wiki/Mach-O) — the +standard executable format for macOS. + +```console +$ docker buildx bake bin +$ file ./build/bin/bakeme +./build/bin/bakeme: Mach-O 64-bit executable arm64 +``` + +Next, let's add a target to build all of the platform variants of the program. +To do this, you can [inherit](/manuals/build/bake/inheritance.md) the `bin` +target that you just created, and extend it by adding the desired platforms. + +```hcl +target "bin-cross" { + inherits = ["bin"] + platforms = [ + "linux/amd64", + "linux/arm64", + "linux/riscv64", + ] +} +``` + +Now, building the `bin-cross` target creates binaries for all platforms. +Subdirectories are automatically created for each variant. + +```console +$ docker buildx bake bin-cross +$ tree build/ +build/ +└── bin + ├── bakeme + ├── linux_amd64 + │   └── bakeme + ├── linux_arm64 + │   └── bakeme + └── linux_riscv64 + └── bakeme + +5 directories, 4 files +``` + +To also generate "release" and "debug" variants, you can use a matrix just like +you did with the default target. When using a matrix, you also need to +differentiate the output directory based on the matrix value, otherwise the +binary gets written to the same location for each matrix run. + +```hcl +target "bin-all" { + inherits = ["bin-cross"] + matrix = { + mode = ["release", "debug"] + } + name = "bin-${mode}" + args = { + BUILD_TAGS = mode + } + output = ["build/bin/${mode}"] +} +``` + +```console +$ rm -r ./build/ +$ docker buildx bake bin-all +$ tree build/ +build/ +└── bin + ├── debug + │   ├── linux_amd64 + │   │   └── bakeme + │   ├── linux_arm64 + │   │   └── bakeme + │   └── linux_riscv64 + │   └── bakeme + └── release + ├── linux_amd64 + │   └── bakeme + ├── linux_arm64 + │   └── bakeme + └── linux_riscv64 + └── bakeme + +10 directories, 6 files +``` + +## Conclusion + +Docker Buildx Bake streamlines complex build workflows, enabling efficient +multi-platform builds, testing, and artifact export. By integrating Buildx Bake +into your projects, you can simplify your Docker builds, make your build +configuration portable, and wrangle complex configurations more easily. + +Experiment with different configurations and extend your Bake files to match +your project's needs. You might consider integrating Bake into your CI/CD +pipelines to automate builds, testing, and artifact deployment. The flexibility +and power of Buildx Bake can significantly improve your development and +deployment processes. + +### Further reading + +For more information about how to use Bake, check out these resources: + +- [Bake documentation](/manuals/build/bake/_index.md) +- [Matrix targets](/manuals/build/bake/matrices.md) +- [Bake file reference](/manuals/build/bake/reference.md) +- [Bake GitHub Action](https://github.com/docker/bake-action) diff --git a/content/manuals/build/bake/variables.md b/content/manuals/build/bake/variables.md index 1dfa803900df..b584cc1483a2 100644 --- a/content/manuals/build/bake/variables.md +++ b/content/manuals/build/bake/variables.md @@ -78,6 +78,35 @@ $ docker buildx bake --print } ``` +## Escape variable interpolation + +If you want to bypass variable interpolation when parsing the Bake definition, +use double dollar signs (`$${VARIABLE}`). + +```hcl +target "default" { + dockerfile-inline = <`. You can customize how the secrets get mounted in the build container using the `target` and `env` options for the `RUN --mount` flag in diff --git a/content/subjects/devops/_index.md b/content/subjects/devops/_index.md new file mode 100644 index 000000000000..2d9ad1867487 --- /dev/null +++ b/content/subjects/devops/_index.md @@ -0,0 +1,3 @@ +--- +title: DevOps +--- diff --git a/docker-bake.hcl b/docker-bake.hcl index 8a556ea2aac6..32f915ed24d2 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -1,9 +1,9 @@ variable "HUGO_ENV" { - default = "development" + default = null } variable "DOCS_URL" { - default = "https://docs.docker.com" + default = null } variable "DOCS_SITE_DIR" { diff --git a/netlify.toml b/netlify.toml index 05b792caa331..b73f1fe9636a 100644 --- a/netlify.toml +++ b/netlify.toml @@ -4,7 +4,7 @@ publish = "public" [context.deploy-preview.environment] NODE_VERSION = "20" NODE_ENV = "production" -HUGO_VERSION = "0.134.3" +HUGO_VERSION = "0.136.2" HUGO_ENABLEGITINFO = "true" HUGO_ENVIRONMENT = "preview"