mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-09-04 16:30:52 +00:00
230
docs/packages.md
230
docs/packages.md
@@ -9,7 +9,7 @@ you should be able to build a LinuxKit package.
|
||||
|
||||
All official LinuxKit packages are:
|
||||
- Enabled with multi-arch manifests to work on multiple architectures.
|
||||
- Derived from well-known (and signed) sources for repeatable builds.
|
||||
- Derived from well-known sources for repeatable builds.
|
||||
- Built with multi-stage builds to minimise their size.
|
||||
|
||||
|
||||
@@ -67,33 +67,172 @@ during the build.
|
||||
|
||||
### Build Targets
|
||||
|
||||
LinuxKit builds packages as docker images. It deposits the built package as a docker image in one of two targets:
|
||||
LinuxKit builds packages as docker images. It deposits the built package as a docker image in one or both of two targets:
|
||||
|
||||
* the linuxkit cache `~/.linuxkit/` (configurable) - default option
|
||||
* the docker image cache
|
||||
* the linuxkit cache, which is at `~/.linuxkit/cache/` (configurable)
|
||||
* the docker image cache (optional)
|
||||
|
||||
If you want to build images and test and run them _in a standalone_ fashion locally, then you should pick the docker image cache. Otherwise, you should use the default linuxkit cache. LinuxKit defaults to building OS images using docker images from this cache,\
|
||||
only looking in the docker cache if instructed to via `linuxkit build --docker`.
|
||||
The package _always_ is built and saved in the linuxkit cache. However, you _also_ can load the package for the current
|
||||
architecture, if available, into the docker image cache.
|
||||
|
||||
When using the linuxkit cache as the package build target, it creates all of the layers, the manifest that can be uploaded
|
||||
If you want to build images and test and run them _in a standalone_ fashion locally, then you should add the docker image cache.
|
||||
Otherwise, you don't need anything more than the default linuxkit cache. LinuxKit defaults to building OS images using docker
|
||||
images from this cache, only looking in the docker cache if instructed to via `linuxkit build --docker`.
|
||||
|
||||
In the linuxkit cache, it creates all of the layers, the manifest that can be uploaded
|
||||
to a registry, and the multi-architecture index. If an image already exists for a different architecture in the cache,
|
||||
it updates the index to include additional manifests created.
|
||||
|
||||
As of this writing, `linuxkit pkg build` only builds packages for the platform on which it is running; it does not (yet) support cross-building the packages for other architectures.
|
||||
The order of building is as follows:
|
||||
|
||||
Note that the local docker option is available _only_ when building without pushing to a remote registry, i.e.:
|
||||
1. Build the image to the linuxkit cache
|
||||
1. If `--docker` is provided, load the image into the docker image cache
|
||||
|
||||
```
|
||||
linuxkit pkg build
|
||||
linuxkit pkg build --docker
|
||||
For example:
|
||||
|
||||
```bash
|
||||
linuxkit pkg build pkg/foo # builds pkg/foo and places it in the linuxkit cache
|
||||
linuxkit pkg build pkg/foo --docker # builds pkg/foo and places it in the linuxkit cache and also loads it into docker
|
||||
```
|
||||
|
||||
If you push to a registry, it _always_ uses the linuxkit cache only:
|
||||
#### Build Platforms
|
||||
|
||||
By default, `linuxkit pkg build` builds for all supported platforms in the package's `build.yml`, whose syntax is available
|
||||
[here][Package source]. If no platforms are provided in the `build.yml`, it builds for all platforms that linuxkit supports.
|
||||
As of this writing, those are:
|
||||
|
||||
* `linux/amd64`
|
||||
* `linux/arm64`
|
||||
* `linux/s390x`
|
||||
|
||||
You can override the target build platform by passing it the `--platforms` option:
|
||||
|
||||
```
|
||||
linuxkit pkg push
|
||||
linuxkit pkg build --platforms <platform1,platform2,...platformN>
|
||||
```
|
||||
|
||||
The options for `--platforms` are identical to those for [docker build](https://docs.docker.com/engine/reference/commandline/build/).
|
||||
An example is available in the official [buildx documentation](https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images).
|
||||
|
||||
Given that this is linuxkit, i.e. all builds are for linux, the `OS` part would seem redundant, and it should be sufficient to pass `--platform arm64`. However, for complete consistency, the _entire_ platform, e.g. `--platforms linux/amd64,linux/arm64`, must be provided.
|
||||
|
||||
#### Where it builds
|
||||
|
||||
You are running the `linuxkit pkg build` command on a single platform, e.g. your local linux cloud instance running on `amd64`, or
|
||||
a MacBook with Apple Silicon running on `arm64`.
|
||||
|
||||
How does linuxkit determine where to build the target images?
|
||||
|
||||
linuxkit uses a combination of buildx builders and docker contexts, controlled by your input, to determine where to build.
|
||||
|
||||
Upon startup, it looks for a buildx builder named `linuxkit`. If it cannot find that builder, it creates it.
|
||||
|
||||
When linuxkit needs to build a package for a particular architecture:
|
||||
|
||||
1. If a context for that architecture was provided, use that context.
|
||||
1. If no context for that architecture was provided, use the default `linuxkit` context
|
||||
|
||||
The actual building then will be one of:
|
||||
|
||||
1. native, if the provided context has the same architecture as the target build architecture; else
|
||||
1. cross-build, if the provided context has a different architecture, but the package's `Dockerfile` supports cross-building; else
|
||||
1. emulated build, using docker's qemu binfmt capabilities
|
||||
|
||||
Cross-building, i.e. building on one platform using that platform's binaries to create outputs for a different platform,
|
||||
depends on the package's `Dockerfile`. Details are available in the
|
||||
[official Docker buildx docs](https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images).
|
||||
|
||||
* if the image is just `FROM something`, then it runs it under qemu using binfmt
|
||||
* if the image is `FROM --platform=$BUILDPLATFORM something`, then it runs it using the local architecture, invoking cross-builders
|
||||
|
||||
Read the official docs to learn more how to leverage cross-building with buildx.
|
||||
|
||||
**Important:** When building, if the local architecture is not one of those being build,
|
||||
selecting `--docker` to load the images into the docker image cache will result in an error.
|
||||
You _must_ be building for the local architecture - optionally for others as well - in order to
|
||||
pass the `--docker` option.
|
||||
|
||||
#### Providing native builder nodes
|
||||
|
||||
linuxkit is capable of using native build nodes to do the build, even remotely. To do so, you must:
|
||||
|
||||
1. Create a [docker context](https://docs.docker.com/engine/context/working-with-contexts/) that references the build node
|
||||
1. Tell linuxkit to use that context for that architecture
|
||||
|
||||
linuxkit will then use that provided context to create a buildx builder and use it for that architecture.
|
||||
|
||||
linuxkit looks for contexts in the following descending order of priority:
|
||||
|
||||
1. CLI option `--builders <platform>=<context>,<platform>=<context>`, e.g. `--builders linux/arm64=linuxkit-arm64,linux/amd64=default`
|
||||
1. Environment variable `LINUXKIT_BUILDERS=<platform>=<context>,<platform>=<context>`, e.g. `LINUXKIT_BUILDERS=linux/arm64=linuxkit-arm64,linux/amd64=default`
|
||||
1. Existing context named `linuxkit-<platform>`, e.g. `linuxkit-linux-arm64` or `linuxkit-linux-s390x`, with "/" replaced by "-", as "/" is an invalid character.
|
||||
1. Default builder named `linuxkit`, created by linuxkit, running in the default context
|
||||
|
||||
If a builder name is provided for a specific platform, and it doesn't exist, it will be treated as a fatal error.
|
||||
|
||||
#### Examples
|
||||
|
||||
##### Simple build
|
||||
|
||||
There are no contexts starting with `linuxkit-`, no environment variable `LINUXKIT_BUILDERS`, no command-line argument `--builders`.
|
||||
|
||||
linuxkit will build any requested packages using `docker buildx` on the local platform, with a builder (created, if necessary) named `linuxkit`.
|
||||
Builds for the same architecture will be native, builds for other platforms will use either qemu or cross-building.
|
||||
|
||||
|
||||
##### Specified target
|
||||
|
||||
You create a context named `my-remote-arm64` and then run:
|
||||
|
||||
```bash
|
||||
linuxkit pkg build --platforms=linux/arm64,linux/amd64 --builders linux/arm64=my-remote-arm64
|
||||
```
|
||||
|
||||
linuxkit will build:
|
||||
|
||||
* for arm64 using the context `my-remote-arm64`, since you specified in `--builders` to use `my-remote-arm64` for `linux/arm64`
|
||||
* for amd64 using the context `default` and the `linuxkit` builder, as that is the default fallback
|
||||
|
||||
The same would happen if you used `LINUXKIT_BUILDERS=linux/arm64=my-remote-arm64` instead of the `--builders` flag.
|
||||
|
||||
##### Named context
|
||||
|
||||
You create a context named `linuxkit-linux-arm64` and then run:
|
||||
|
||||
```bash
|
||||
linuxkit pkg build --platforms=linux/arm64,linux/amd64
|
||||
```
|
||||
|
||||
linuxkit will build:
|
||||
|
||||
* for arm64 using the context `linuxkit-linux-arm64`, since there is a context with the name `linuxkit-<platform>`, and you did not override it using `--builders` or the environment variable `LINUXKIT_BUILDERS`
|
||||
* for amd64 using the context `default` and the `linuxkit` builder, as that is the default fallback
|
||||
|
||||
##### Combination
|
||||
|
||||
You create a context named `linuxkit-arm64`, and another named `my-remote-builder-amd64` and then run:
|
||||
|
||||
```bash
|
||||
linuxkit pkg build --platforms=linux/arm64,linux/amd64 --builders linux/amd64=my-remote-builder-amd64
|
||||
```
|
||||
|
||||
linuxkit will build:
|
||||
|
||||
* for arm64 using the context `linuxkit-arm64`, since there is a context with the name `linuxkit-<arch>`, and you did not override that particular architecture using `--builders` or the environment variable `LINUXKIT_BUILDERS`
|
||||
* for amd64 using the context `my-remote-builder-amd64`, since you specified for that architecture using `--builders`
|
||||
|
||||
The same would happen if you used `LINUXKIT_BUILDERS=linux/arm64=my-remote-builder-amd64` instead of the `--builders` flag.
|
||||
|
||||
##### Missing context
|
||||
|
||||
You do not have a context named `my-remote-arm64`, and run:
|
||||
|
||||
```bash
|
||||
linuxkit pkg build --platforms=linux/arm64 --builders linux/arm64=my-remote-arm64
|
||||
```
|
||||
|
||||
linuxkit will try to build for `linux/arm64` using the context `my-remote-arm64`. Since that context does not exist, you will get an error.
|
||||
|
||||
### Build packages as a maintainer
|
||||
|
||||
All official LinuxKit packages are multi-arch manifests and most of
|
||||
@@ -103,78 +242,33 @@ them are available for the following platforms:
|
||||
* `linux/arm64`
|
||||
* `linux/s390x`
|
||||
|
||||
Official images *must* be built on all architectures for which they are available.
|
||||
They can be built and pushed in parallel, but the manifest should be pushed once
|
||||
when all of the images are done.
|
||||
Official images *must* be built for all architectures for which they are available.
|
||||
|
||||
Pushing out a package as a maintainer involves two distinct stages:
|
||||
Pushing out a package as a maintainer involves two stages:
|
||||
|
||||
1. Building and pushing out the platform-specific image
|
||||
1. Creating, pushing out and signing the multi-arch manifest, a.k.a. OCI image index
|
||||
1. Building and pushing out the platform-specific images
|
||||
1. Creating and pushing out the multi-arch manifest, a.k.a. OCI image index
|
||||
|
||||
The `linuxkit pkg` command contains automation which performs all of the steps.
|
||||
Note that `«path-to-package»` is the path to the package's source directory
|
||||
(containing at least `build.yml` and `Dockerfile`). It can be `.` if
|
||||
the package is in the current directory.
|
||||
|
||||
|
||||
#### Image Only
|
||||
|
||||
To build and push out the platform-specific image, on that platform:
|
||||
|
||||
```
|
||||
linuxkit pkg push --manifest=false «path-to-package»
|
||||
linuxkit pkg push «path-to-package»
|
||||
```
|
||||
|
||||
The options do the following:
|
||||
|
||||
* `--manifest=false` means not to push or sign a manifest
|
||||
|
||||
Repeat the above on each platform where you need an image.
|
||||
|
||||
This will do the following:
|
||||
|
||||
1. Determine the name and tag for the image as follows:
|
||||
* The tag is from the hash of the git tree for that package. You can see it by doing `linuxkit pkg show-tag «path-to-package»`.
|
||||
* The name for the image is from `«path-to-package»/build.yml`
|
||||
* The organization for the package is given on the command-line, default to `linuxkit`.
|
||||
1. Build the package in the given path using your local docker instance for the local platform. E.g. if you are running on `linux/arm64`, it will build for `linux/arm64`.
|
||||
1. Tag the build image as `«image-name»:«hash»-«arch»`
|
||||
1. Push the image to the hub
|
||||
|
||||
#### Manifest Only
|
||||
|
||||
To perform just the manifest steps, do:
|
||||
|
||||
```
|
||||
linuxkit pkg push --image=false --manifest «path-to-package»
|
||||
```
|
||||
|
||||
The options do the following:
|
||||
|
||||
* `--image=false` do not push the image, as you already did it; you can, of course, skip this argument and push the image as well
|
||||
* `--manifest` create and push the manifest
|
||||
|
||||
This will do the following:
|
||||
|
||||
1. Find all of the images on the hub of the format `«image-name»:«hash»-«arch»`
|
||||
1. Build the package in the given path using your local docker instance for all the platforms in `«path-to-package»/build.yml`
|
||||
1. Save the built image in the linuxkit cache
|
||||
1. Tag each built image as `«image-name»:«hash»-«arch»`
|
||||
1. Create a multi-arch manifest called `«image-name»:«hash»` (note no `-«arch»`)
|
||||
1. Push the manifest to the hub
|
||||
1. Sign the manifest with your key
|
||||
|
||||
Each time you perform the manifest steps, it will find all of the images,
|
||||
including any that have been added since last time.
|
||||
The LinuxKit YAML files should consume the package as the multi-arch manifest:
|
||||
`linuxkit/<image>:<hash>`.
|
||||
|
||||
#### Everything at once
|
||||
|
||||
To perform _all_ of the steps at once - build and push out the image for whatever platform
|
||||
you are running on, and create and sign a manifest - do:
|
||||
|
||||
```
|
||||
linuxkit pkg push «path-to-package»
|
||||
```
|
||||
1. Push the manifest and all of the images to the hub
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
|
Reference in New Issue
Block a user