freshness: update top pages in the build section

Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
David Karlsson 2023-08-09 17:23:19 +02:00
parent e29944ad49
commit 2a6f7eac80
5 changed files with 242 additions and 291 deletions

View File

@ -1,6 +1,6 @@
--- ---
title: Multi-platform images title: Multi-platform images
description: Different strategies for building multi-platform images description: Introduction to multi-platform images and how to build them
keywords: build, buildx, buildkit, multi-platform images keywords: build, buildx, buildkit, multi-platform images
redirect_from: redirect_from:
- /build/buildx/multiplatform-images/ - /build/buildx/multiplatform-images/
@ -13,8 +13,8 @@ Docker images can support multiple platforms, which means that a single image
may contain variants for different architectures, and sometimes for different may contain variants for different architectures, and sometimes for different
operating systems, such as Windows. operating systems, such as Windows.
When running an image with multi-platform support, `docker` automatically When you run an image with multi-platform support, Docker automatically selects
selects the image that matches your OS and architecture. the image that matches your OS and architecture.
Most of the Docker Official Images on Docker Hub provide a [variety of architectures](https://github.com/docker-library/official-images#architectures-other-than-amd64){:target="blank" rel="noopener" class=""}. Most of the Docker Official Images on Docker Hub provide a [variety of architectures](https://github.com/docker-library/official-images#architectures-other-than-amd64){:target="blank" rel="noopener" class=""}.
For example, the `busybox` image supports `amd64`, `arm32v5`, `arm32v6`, For example, the `busybox` image supports `amd64`, `arm32v5`, `arm32v6`,
@ -23,55 +23,61 @@ on an `x86_64` / `amd64` machine, the `amd64` variant is pulled and run.
## Building multi-platform images ## Building multi-platform images
Docker is now making it easier than ever to develop containers on, and for Arm
servers and devices. Using the standard Docker tooling and processes, you can
start to build, push, pull, and run images seamlessly on different compute
architectures. In most cases, you don't have to make any changes to Dockerfiles
or source code to start building for Arm.
BuildKit with Buildx is designed to work well for building for multiple
platforms and not only for the architecture and operating system that the user
invoking the build happens to run.
When you invoke a build, you can set the `--platform` flag to specify the target When you invoke a build, you can set the `--platform` flag to specify the target
platform for the build output, (for example, `linux/amd64`, `linux/arm64`, or platform for the build output. For example, `linux/amd64`, `linux/arm64`, or
`darwin/amd64`). `darwin/amd64`.
When the current builder instance is backed by the `docker-container` driver, By default, you can only build for a single platform at a time. If you want to
you can specify multiple platforms together. In this case, it builds a manifest build for multiple platforms at once, you can:
list which contains images for all specified architectures. When you use this
image in [`docker run`](../../engine/reference/commandline/run.md) or
[`docker service`](../../engine/reference/commandline/service.md), Docker picks
the correct image based on the node's platform.
You can build multi-platform images using three different strategies that are - Create a new builder that uses the [`docker-container` driver](../drivers/docker-container.md)
supported by Buildx and Dockerfiles: - Turn on the [containerd snapshotter storage](../../desktop/containerd/index.md)
1. Using the QEMU emulation support in the kernel ## Strategies
2. Building on multiple native nodes using the same builder instance
3. Using a stage in Dockerfile to cross-compile to different architectures
QEMU is the easiest way to get started if your node already supports it (for You can build multi-platform images using three different strategies,
example. if you are using Docker Desktop). It requires no changes to your depending on your use case:
Dockerfile and BuildKit automatically detects the secondary architectures that
are available. When BuildKit needs to run a binary for a different architecture, 1. Using the [QEMU emulation](#qemu) support in the kernel
it automatically loads it through a binary registered in the `binfmt_misc` 2. Building on [multiple native nodes](#multiple-native-nodes) using the same
handler. builder instance
3. Using a stage in your Dockerfile to [cross-compile](#cross-compilation) to
different architectures
### QEMU
Building multi-platform images under emulation with QEMU is the easiest way to
get started if your builder already supports it. Docker Desktop supports it out
of the box. It requires no changes to your Dockerfile, and BuildKit
automatically detects the secondary architectures that are available. When
BuildKit needs to run a binary for a different architecture, it automatically
loads it through a binary registered in the `binfmt_misc` handler.
> **Note**
>
> QEMU performs full-system emulation of non-native platforms, which is much
> slower than native builds. Compute-heavy tasks like compilation and
> compression or decompression likely results in a large performance hit.
>
> Use [cross-compilation](#cross-compilation) instead, if possible.
For QEMU binaries registered with `binfmt_misc` on the host OS to work For QEMU binaries registered with `binfmt_misc` on the host OS to work
transparently inside containers, they must be statically compiled and registered transparently inside containers, they must be statically compiled and
with the `fix_binary` flag. This requires a kernel >= 4.8 and registered with the `fix_binary` flag. This requires a kernel version 4.8 or
binfmt-support >= 2.1.7. You can check for proper registration by checking if later, and `binfmt-support` version 2.1.7 or later.
`F` is among the flags in `/proc/sys/fs/binfmt_misc/qemu-*`. While Docker
Desktop comes preconfigured with `binfmt_misc` support for additional platforms, You can verify your registration by checking if `F` is among the flags in
for other installations it likely needs to be installed using `/proc/sys/fs/binfmt_misc/qemu-*`. While Docker Desktop comes preconfigured
[`tonistiigi/binfmt`](https://github.com/tonistiigi/binfmt){:target="blank" rel="noopener" class=""} with `binfmt_misc` support for additional platforms, for other installations it
image. likely needs to be installed using
[`tonistiigi/binfmt`](https://github.com/tonistiigi/binfmt) image:
```console ```console
$ docker run --privileged --rm tonistiigi/binfmt --install all $ docker run --privileged --rm tonistiigi/binfmt --install all
``` ```
### Multiple native nodes
Using multiple native nodes provide better support for more complicated cases Using multiple native nodes provide better support for more complicated cases
that are not handled by QEMU and generally have better performance. You can that are not handled by QEMU and generally have better performance. You can
add additional nodes to the builder instance using the `--append` flag. add additional nodes to the builder instance using the `--append` flag.
@ -85,13 +91,18 @@ $ docker buildx create --append --name mybuild node-arm64
$ docker buildx build --platform linux/amd64,linux/arm64 . $ docker buildx build --platform linux/amd64,linux/arm64 .
``` ```
Finally, depending on your project, the language that you use may have good For information on using multiple native nodes in CI, with GitHub Actions,
support for cross-compilation. In that case, multi-stage builds in Dockerfiles refer to
can be effectively used to build binaries for the platform specified with [Configure your GitHub Actions builder](../ci/github-actions/configure-builder.md#append-additional-nodes-to-the-builder).
`--platform` using the native architecture of the build node. A list of build
arguments like `BUILDPLATFORM` and `TARGETPLATFORM` is available automatically ### Cross-compilation
inside your Dockerfile and can be leveraged by the processes running as part
of your build. Depending on your project, if the programming language you use has good support
for cross-compilation, multi-stage builds in Dockerfiles can be effectively
used to build binaries for target platforms using the native architecture of
the build node. Build arguments such as `BUILDPLATFORM` and `TARGETPLATFORM`
are automatically available for use in your Dockerfile, and can be leveraged by
the processes running as part of your build.
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
@ -124,34 +135,7 @@ and the more advanced cache exporters, which are currently unsupported in the
default `docker` driver: default `docker` driver:
```console ```console
$ docker buildx create --name mybuilder --driver docker-container --bootstrap $ docker buildx create --name mybuilder --bootstrap --use
mybuilder
```
Switch to the new builder:
```console
$ docker buildx use mybuilder
```
> **Note**
>
> Alternatively, run `docker buildx create --name mybuilder --driver docker-container --bootstrap --use`
> to create a new builder and switch to it using a single command.
And inspect it:
```console
$ docker buildx inspect
Name: mybuilder
Driver: docker-container
Nodes:
Name: mybuilder0
Endpoint: unix:///var/run/docker.sock
Status: running
Buildkit: v0.10.4
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
``` ```
Now listing the existing builders again, we can see our new builder is Now listing the existing builders again, we can see our new builder is
@ -160,10 +144,10 @@ registered:
```console ```console
$ docker buildx ls $ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder docker-container mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running v0.10.4 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 mybuilder0 unix:///var/run/docker.sock running v0.12.1 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default * docker default docker
default default running v0.11.6 linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6 default default running v{{ site.buildkit_version }} linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
``` ```
## Example ## Example
@ -272,5 +256,5 @@ Linux architectures such as `arm`, `mips`, `ppc64le`, and even `s390x`.
This does not require any special configuration in the container itself as it This does not require any special configuration in the container itself as it
uses [qemu-static](https://wiki.qemu.org/Main_Page){:target="blank" rel="noopener" class=""} uses [qemu-static](https://wiki.qemu.org/Main_Page){:target="blank" rel="noopener" class=""}
from the **Docker for Mac VM**. Because of this, you can run an ARM container, from the Docker Desktop VM. Because of this, you can run an ARM container,
like the `arm32v7` or `ppc64le` variants of the busybox image. like the `arm32v7` or `ppc64le` variants of the busybox image.

View File

@ -1,6 +1,8 @@
--- ---
title: Multi-stage builds title: Multi-stage builds
description: Keeping your images small with multi-stage builds description: |
Learn about multi-stage builds and how you can use
them to improve your builds and get smaller images
keywords: build, best practices keywords: build, best practices
redirect_from: redirect_from:
- /engine/userguide/eng-image/multistage-build/ - /engine/userguide/eng-image/multistage-build/
@ -10,125 +12,46 @@ redirect_from:
Multi-stage builds are useful to anyone who has struggled to optimize Multi-stage builds are useful to anyone who has struggled to optimize
Dockerfiles while keeping them easy to read and maintain. Dockerfiles while keeping them easy to read and maintain.
> **Acknowledgment**
>
> Special thanks to [Alex Ellis](https://twitter.com/alexellisuk){:target="blank" rel="noopener" class=""}
> for granting permission to use his blog post [Builder pattern vs. Multi-stage builds in Docker](https://blog.alexellis.io/mutli-stage-docker-builds/){:target="blank" rel="noopener" class=""}
> as the basis of the examples on this page.
## Before multi-stage builds
One problem you may face as you build and publish images, is that the size of
those images can sometimes grow quite large. Traditionally, before multi-stage
builds were a thing, keeping the size of images down would require you to
manually clean up resources from the image, so as to keep it small.
In the past, it was common practice to have one Dockerfile for development,
and another, slimmed-down one to use for production.
The development version contained everything needed to build your application.
The production version only contained your application
and the dependencies needed to run it.
To write a truly efficient Dockerfile, you had to come up with shell tricks and
arcane solutions to keep the layers as small as possible.
All to ensure that each layer contained only the artifacts it needed,
and nothing else.
This has been referred to as the _builder pattern_.
The following examples show two Dockerfiles that adhere to this pattern:
- `build.Dockerfile`, for development builds
- `Dockerfile`, for slimmed-down production builds
**`build.Dockerfile`**:
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go ./
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED=0 go build -a -installsuffix cgo -o app .
```
Notice how this example artificially compresses two `RUN` commands together
using the Bash `&&` operator. This is done to avoid creating an additional
layer in the image. Writing Dockerfiles like this is failure-prone and hard to
maintain. It's easy to insert another command and forget to continue the line
using the `\` character, for example.
**`Dockerfile`**:
```dockerfile
# syntax=docker/dockerfile:1
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app ./
CMD ["./app"]
```
The following example is a utility script that:
1. Builds the first image.
2. Creates a container from it to copy the artifact out.
3. Builds the second image.
```bash
#!/bin/sh
echo Building alexellis2/href-counter:build
docker build -t alexellis2/href-counter:build . -f build.Dockerfile
docker container create --name extract alexellis2/href-counter:build
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app
docker container rm -f extract
echo Building alexellis2/href-counter:latest
docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app
```
Both images take up room on your system and you still end up with the `app`
artifact on your local disk as well.
Multi-stage builds simplifies this situation!
## Use multi-stage builds ## Use multi-stage builds
With multi-stage builds, you use multiple `FROM` statements in your Dockerfile. With multi-stage builds, you use multiple `FROM` statements in your Dockerfile.
Each `FROM` instruction can use a different base, and each of them begins a new Each `FROM` instruction can use a different base, and each of them begins a new
stage of the build. You can selectively copy artifacts from one stage to stage of the build. You can selectively copy artifacts from one stage to
another, leaving behind everything you don't want in the final image. To show another, leaving behind everything you don't want in the final image.
how this works, you can adapt the `Dockerfile` from the previous section to use
multi-stage builds. The following Dockerfile has two separate stages: one for building a binary,
and another where we copy the binary into.
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM golang:1.21
WORKDIR /src
COPY <<EOF ./main.go
package main
FROM golang:1.16 import "fmt"
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app .
FROM alpine:latest func main() {
RUN apk --no-cache add ca-certificates fmt.Println("hello, world")
WORKDIR /root/ }
COPY --from=0 /go/src/github.com/alexellis/href-counter/app ./ EOF
CMD ["./app"] RUN go build -o /bin/hello ./main.go
FROM scratch
COPY --from=0 /bin/hello /bin/hello
CMD ["/bin/hello"]
``` ```
You only need the single Dockerfile. You only need the single Dockerfile. No need for a separate build script. Just
No need for a separate build script. run `docker build`.
Just run `docker build`.
```console ```console
$ docker build -t alexellis2/href-counter:latest . $ docker build -t hello .
``` ```
The end result is the same tiny production image as before, with a The end result is a tiny production image with nothing but the binary inside.
significant reduction in complexity. You don't need to create any intermediate None of the build tools required to build the application are included in the
images, and you don't need to extract any artifacts to your local system at all. resulting image.
How does it work? The second `FROM` instruction starts a new build stage with How does it work? The second `FROM` instruction starts a new build stage with
the `alpine:latest` image as its base. The `COPY --from=0` line copies just the the `alpine:latest` image as its base. The `COPY --from=0` line copies just the
@ -146,18 +69,22 @@ Dockerfile are re-ordered later, the `COPY` doesn't break.
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM golang:1.21 as build
WORKDIR /src
COPY <<EOF /src/main.go
package main
FROM golang:1.16 AS builder import "fmt"
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app .
FROM alpine:latest func main() {
RUN apk --no-cache add ca-certificates fmt.Println("hello, world")
WORKDIR /root/ }
COPY --from=builder /go/src/github.com/alexellis/href-counter/app ./ EOF
CMD ["./app"] RUN go build -o /bin/hello ./main.go
FROM scratch
COPY --from=build /bin/hello /bin/hello
CMD ["/bin/hello"]
``` ```
## Stop at a specific build stage ## Stop at a specific build stage
@ -168,7 +95,7 @@ following command assumes you are using the previous `Dockerfile` but stops at
the stage named `builder`: the stage named `builder`:
```console ```console
$ docker build --target builder -t alexellis2/href-counter:latest . $ docker build --target build -t hello .
``` ```
A few scenarios where this might be useful are: A few scenarios where this might be useful are:
@ -179,7 +106,7 @@ A few scenarios where this might be useful are:
- Using a `testing` stage in which your app gets populated with test data, but - Using a `testing` stage in which your app gets populated with test data, but
building for production using a different stage which uses real data building for production using a different stage which uses real data
## Use an external image as a "stage" ## Use an external image as a stage
When using multi-stage builds, you aren't limited to copying from stages you When using multi-stage builds, you aren't limited to copying from stages you
created earlier in your Dockerfile. You can use the `COPY --from` instruction to created earlier in your Dockerfile. You can use the `COPY --from` instruction to
@ -284,5 +211,4 @@ Removing intermediate container bbc025b93175
Successfully built 09fc3770a9c4 Successfully built 09fc3770a9c4
``` ```
The legacy builder processes `stage1`, The legacy builder processes `stage1`, even if `stage2` doesn't depend on it.
even if `stage2` doesn't depend on it.

View File

@ -9,15 +9,15 @@ redirect_from:
It all starts with a Dockerfile. It all starts with a Dockerfile.
Docker builds images by reading the instructions from a Dockerfile. This is a Docker builds images by reading the instructions from a Dockerfile. A
text file containing instructions that adhere to a specific format needed to Dockerfile is a text file containing instructions for building your source
assemble your application into a container image and for which you can find code. The Dockerfile instruction syntax is defined by the specification
its specification reference in the [Dockerfile reference](../../engine/reference/builder.md). reference in the [Dockerfile reference](../../engine/reference/builder.md).
Here are the most common types of instructions: Here are the most common types of instructions:
| Instruction | Description | | Instruction | Description |
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`FROM <image>`](../../engine/reference/builder.md#from) | Defines a base for your image. | | [`FROM <image>`](../../engine/reference/builder.md#from) | Defines a base for your image. |
| [`RUN <command>`](../../engine/reference/builder.md#run) | Executes any commands in a new layer on top of the current image and commits the result. `RUN` also has a shell form for running commands. | | [`RUN <command>`](../../engine/reference/builder.md#run) | Executes any commands in a new layer on top of the current image and commits the result. `RUN` also has a shell form for running commands. |
| [`WORKDIR <directory>`](../../engine/reference/builder.md#workdir) | Sets the working directory for any `RUN`, `CMD`, `ENTRYPOINT`, `COPY`, and `ADD` instructions that follow it in the Dockerfile. | | [`WORKDIR <directory>`](../../engine/reference/builder.md#workdir) | Sets the working directory for any `RUN`, `CMD`, `ENTRYPOINT`, `COPY`, and `ADD` instructions that follow it in the Dockerfile. |
@ -26,35 +26,38 @@ Here are the most common types of instructions:
Dockerfiles are crucial inputs for image builds and can facilitate automated, Dockerfiles are crucial inputs for image builds and can facilitate automated,
multi-layer image builds based on your unique configurations. Dockerfiles can multi-layer image builds based on your unique configurations. Dockerfiles can
start simple and grow with your needs and support images that require complex start simple and grow with your needs to support more complex scenarios.
instructions. For all the possible instructions, see the [Dockerfile reference](../../engine/reference/builder.md).
### Filename
The default filename to use for a Dockerfile is `Dockerfile`, without a file The default filename to use for a Dockerfile is `Dockerfile`, without a file
extension. Using the default name allows you to run the `docker build` command extension. Using the default name allows you to run the `docker build` command
without having to specify additional command flags. without having to specify additional command flags.
Some projects may need distinct Dockerfiles for specific purposes. A common Some projects may need distinct Dockerfiles for specific purposes. A common
convention is to name these `<something>.Dockerfile`. Such Dockerfiles can then convention is to name these `<something>.Dockerfile`. You can specify the
be used through the `--file` (or `-f` shorthand) option on the `docker build` command. Dockerfile filename using the `--file` flag for the `docker build` command.
Refer to the ["Specify a Dockerfile" section](../../engine/reference/commandline/build.md#file) Refer to the
in the `docker build` reference to learn about the `--file` option. [`docker build` CLI reference](../../engine/reference/commandline/build.md#file)
to learn about the `--file` flag.
> **Note** > **Note**
> >
> We recommend using the default (`Dockerfile`) for your project's primary > We recommend using the default (`Dockerfile`) for your project's primary
> Dockerfile. > Dockerfile.
Docker images consist of **read-only layers**, each resulting from an ## Docker images
instruction in the Dockerfile. Layers are stacked sequentially and each one is
Docker images consist of layers. Each layer is the result of a build
instruction in the Dockerfile. Layers are stacked sequentially, and each one is
a delta representing the changes applied to the previous layer. a delta representing the changes applied to the previous layer.
## Example ### Example
Here's a simple Dockerfile example to get you started with building images. Here's what a typical workflow for building applications with Docker looks like.
We'll take a simple "Hello World" Python Flask application, and bundle it into
a Docker image that can test locally or deploy anywhere!
Let's say we have a `hello.py` file with the following content: The following example code shows a small "Hello World" application written in
Python, using the Flask framework.
```python ```python
from flask import Flask from flask import Flask
@ -65,18 +68,15 @@ def hello():
return "Hello World!" return "Hello World!"
``` ```
Don't worry about understanding the full example if you're not familiar with In order to ship and deploy this application without Docker Build, you would
Python, it's just a simple web server that will contain a single page that need to make sure that:
says "Hello World".
> **Note** - The required runtime dependencies are installed on the server
> - The Python code gets uploaded to the server's filesystem
> If you test the example, make sure to copy over the indentation as well! For - The server starts your application, using the necessary parameters
> more information about this sample Flask application, check the
> [Flask Quickstart](https://flask.palletsprojects.com/en/2.1.x/quickstart/){:target="blank" rel="noopener" class=""}
> page.
Here's the Dockerfile that will be used to create an image for our application: The following Dockerfile creates a container image, which has all the
dependencies installed and that automatically starts your application.
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
@ -95,6 +95,20 @@ EXPOSE 8000
CMD flask run --host 0.0.0.0 --port 8000 CMD flask run --host 0.0.0.0 --port 8000
``` ```
Here's a breakdown of what this Dockerfile does:
- [Dockerfile syntax](#dockerfile-syntax)
- [Base image](#base-image)
- [Environment setup](#environment-setup)
- [Comments](#comments)
- [Installing dependencies](#installing-dependencies)
- [Copying files](#copying-files)
- [Setting environment variables](#setting-environment-variables)
- [Exposed ports](#exposed-ports)
- [Starting the application](#starting-the-application)
### Dockerfile syntax
The first line to add to a Dockerfile is a [`# syntax` parser directive](../../engine/reference/builder.md#syntax). The first line to add to a Dockerfile is a [`# syntax` parser directive](../../engine/reference/builder.md#syntax).
While optional, this directive instructs the Docker builder what syntax to use While optional, this directive instructs the Docker builder what syntax to use
when parsing the Dockerfile, and allows older Docker versions with [BuildKit enabled](../buildkit/index.md#getting-started) when parsing the Dockerfile, and allows older Docker versions with [BuildKit enabled](../buildkit/index.md#getting-started)
@ -107,128 +121,156 @@ your Dockerfile, and should be the first line in Dockerfiles.
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
``` ```
> **Note** > **Tip**
> >
> We recommend using `docker/dockerfile:1`, which always points to the latest > We recommend using `docker/dockerfile:1`, which always points to the latest
> release of the version 1 syntax. BuildKit automatically checks for updates of > release of the version 1 syntax. BuildKit automatically checks for updates of
> the syntax before building, making sure you are using the most current version. > the syntax before building, making sure you are using the most current version.
{: .tip }
Next we define the first instruction: ### Base image
The line following the syntax directive defines what base image to use:
```dockerfile ```dockerfile
FROM ubuntu:22.04 FROM ubuntu:22.04
``` ```
Here the [`FROM` instruction](../../engine/reference/builder.md#from) sets our The [`FROM` instruction](../../engine/reference/builder.md#from) sets your base
base image to the 22.04 release of Ubuntu. All following instructions are image to the 22.04 release of Ubuntu. All instructions that follow are executed
executed on this base image, in this case, an Ubuntu environment. The notation in this base image: an Ubuntu environment. The notation `ubuntu:22.04`, follows
`ubuntu:22.04`, follows the `name:tag` standard for naming docker images. When the `name:tag` standard for naming Docker images. When you build images, you
you build your image you use this notation to name your images and use it to use this notation to name your images. There are many public images you can
specify any existing Docker image. There are many public images you can leverage in your projects, by importing them into your build steps using the
leverage in your projects. Explore [Docker Hub](https://hub.docker.com/search?image_filter=official&q=&type=image){:target="blank" rel="noopener" class=""} Dockerfile `FROM` instruction.
to find out.
[Docker Hub](https://hub.docker.com/search?image_filter=official&q=&type=image)
contains a large set of official images that you can use for this purpose.
### Environment setup
The following line executes a build command inside the base image.
```dockerfile ```dockerfile
# install app dependencies # install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip RUN apt-get update && apt-get install -y python3 python3-pip
``` ```
This [`RUN` instruction](../../engine/reference/builder.md#run) executes a shell This [`RUN` instruction](../../engine/reference/builder.md#run) executes a
command in the [build context](context.md). shell in Ubuntu that updates the APT package index and installs Python tools in
the container.
In this example, our context is a full Ubuntu operating system, so we have ### Comments
access to its package manager, apt. The provided commands update our package
lists and then, after that succeeds, installs `python3` and `pip`, the package
manager for Python.
Also note `# install app dependencies` line. This is a comment. Comments in Note the `# install app dependencies` line. This is a comment. Comments in
Dockerfiles begin with the `#` symbol. As your Dockerfile evolves, comments can Dockerfiles begin with the `#` symbol. As your Dockerfile evolves, comments can
be instrumental to document how your dockerfile works for any future readers be instrumental to document how your Dockerfile works for any future readers
and editors of the file. and editors of the file, including your future self!
> **Note** > **Note**
> >
> Starting your Dockerfile by a `#` like regular comments is treated as a > You might've noticed that comments are denoted using the same symbol as the
> directive when you are using BuildKit (default), otherwise it is ignored. > [syntax directive](#dockerfile-syntax) on the first line of the file.
> The symbol is only interpreted as a directive if the pattern matches a
> directive and appears at the beginning of the Dockerfile. Otherwise, it's
> treated as a comment.
### Installing dependencies
The second `RUN` instruction installs the `flask` dependency required by the
Python application.
```dockerfile ```dockerfile
RUN pip install flask==2.1.* RUN pip install flask==2.1.*
``` ```
This second `RUN` instruction requires that we've installed pip in the layer A prerequisite for this instruction is that `pip` is installed into the build
before. After applying the previous directive, we can use the pip command to container. The first `RUN` command installs `pip`, which ensures that we can
install the flask web framework. This is the framework we've used to write use the command to install the flask web framework.
our basic "Hello World" application from above, so to run it in Docker, we'll
need to make sure it's installed. ### Copying files
The next instruction uses the
[`COPY` instruction](../../engine/reference/builder.md#copy) to copy the
`hello.py` file from the local build context into the root directory of our image.
```dockerfile ```dockerfile
COPY hello.py / COPY hello.py /
``` ```
Now we use the [`COPY` instruction](../../engine/reference/builder.md#copy) to A [build context](context.md) is the set of files that you can access
copy our `hello.py` file from the local [build context](context.md) into the in Dockerfile instructions such as `COPY` and `ADD`.
root directory of our image. After being executed, we'll end up with a file
called `/hello.py` inside the image. After the `COPY` instruction, the `hello.py` file is added to the filesystem
of the build container.
### Setting environment variables
If your application uses environment variables, you can set environment variables
in your Docker build using the [`ENV` instruction](../../engine/reference/builder.md#env).
```dockerfile ```dockerfile
ENV FLASK_APP=hello ENV FLASK_APP=hello
``` ```
This [`ENV` instruction](../../engine/reference/builder.md#env) sets a Linux This sets a Linux environment variable we'll need later. Flask, the framework
environment variable we'll need later. This is a flask-specific variable, used in this example, uses this variable to start the application. Without this,
that configures the command later used to run our `hello.py` application. flask wouldn't know where to find our application to be able to run it.
Without this, flask wouldn't know where to find our application to be able to
run it. ### Exposed ports
The [`EXPOSE` instruction](../../engine/reference/builder.md#expose) marks that
our final image has a service listening on port `8000`.
```dockerfile ```dockerfile
EXPOSE 8000 EXPOSE 8000
``` ```
This [`EXPOSE` instruction](../../engine/reference/builder.md#expose) marks that This instruction isn't required, but it is a good practice and helps tools and
our final image has a service listening on port `8000`. This isn't required, team members understand what this application is doing.
but it is a good practice, as users and tools can use this to understand what
your image does. ### Starting the application
Finally, [`CMD` instruction](../../engine/reference/builder.md#cmd) sets the
command that is run when the user starts a container based on this image.
```dockerfile ```dockerfile
CMD flask run --host 0.0.0.0 --port 8000 CMD flask run --host 0.0.0.0 --port 8000
``` ```
Finally, [`CMD` instruction](../../engine/reference/builder.md#cmd) sets the In this case we'll start the flask development server listening on all addresses
command that is run when the user starts a container based on this image. In
this case we'll start the flask development server listening on all addresses
on port `8000`. on port `8000`.
## Testing ## Building
To test our Dockerfile, we'll first build it using the [`docker build` command](../../engine/reference/commandline/build.md): To build a container image using the Dockerfile example from the
[previous section](#example), you use the `docker build` command:
```console ```console
$ docker build -t test:latest . $ docker build -t test:latest .
``` ```
Here `-t test:latest` option specifies the name (required) and tag (optional) The `-t test:latest` option specifies the name and tag of the image.
of the image we're building. `.` specifies the [build context](context.md) as
the current directory. In this example, this is where build expects to find the
Dockerfile and the local files the Dockerfile needs to access, in this case
your Python application.
So, in accordance with the build command issued and how [build context](context.md) The single dot (`.`) at the end of the command sets the
works, your Dockerfile and python app need to be in the same directory. [build context](context.md) to the current directory. This means that the
build expects to find the Dockerfile and the `hello.py` file in the directory
where the command is invoked. If those files aren't there, the build fails.
Now run your newly built image: After the image has been built, you can run the application as a container with
`docker run`, specifying the image name:
```console ```console
$ docker run -p 8000:8000 test:latest $ docker run -p 127.0.0.1:8000:8000 test:latest
``` ```
From your computer, open a browser and navigate to `http://localhost:8000` This publishes the container's port 8000 to `http://localhost:8000` on the
Docker host.
> **Note**
>
> You can also build and run using [Play with Docker](https://labs.play-with-docker.com){:target="blank" rel="noopener" class=""}
> that provides you with a temporary Docker instance in the cloud.
## Other resources ## Other resources
If you are interested in examples in other languages, such as Go, check out If you are interested in examples in other languages, such as Go, check out
our [language-specific guides](../../language/index.md) in the Guides section. our [language-specific guides](../../language/index.md) in the Guides section.
For more information about building, including advanced use cases and patterns,
refer to the [Build with Docker](../guide/index.md) guide.

View File

@ -1,6 +1,6 @@
--- ---
title: Configuring your builder title: Configuring your GitHub Actions builder
description: Configuring BuildKit instances with GitHub Actions. description: Configuring BuildKit instances for building in CI with GitHub Actions
keywords: ci, github actions, gha, buildkit, buildx keywords: ci, github actions, gha, buildkit, buildx
--- ---

View File

@ -7,15 +7,14 @@ redirect_from:
- /develop/develop-images/build_enhancements/ - /develop/develop-images/build_enhancements/
--- ---
Docker Build is one of Docker Engine's most used features. Whenever you are Docker Build is one of Docker Engine's most used features. Whenever you're
creating an image you are using Docker Build. Build is a key part of your creating an image, you are using Docker Build. Build is a key part of your
software development life cycle allowing you to package and bundle your code and software development life cycle allowing you to package and bundle your code and
ship it anywhere. ship it anywhere.
Docker Build is more than a command for building images, and it's not only about Docker Build is more than a command for building images, and it's not only about
packaging your code. It's a whole ecosystem of tools and features that support packaging your code. It's a whole ecosystem of tools and features that support
not only common workflow tasks but also provides support for more complex and both common workflow tasks and more complex and advanced scenarios.
advanced scenarios.
<div class="component-container"> <div class="component-container">
<div class="row"> <div class="row">