1
0
mirror of https://github.com/containers/buildah.git synced 2025-07-31 15:24:26 +03:00

Allow users to set OS and architecture on bud

When building images we now allow the architecture and operating system
to be overwritten via the new `--os` and `--arch` flags. This allows the
use case of packing pre-built or cross-compiled binaries into container
images with specifying the correct environment. The `--platform` flag
now takes the `os/arch` format into account as well.

Signed-off-by: Sascha Grunert <sgrunert@suse.com>

Closes: #2097
Approved by: rhatdan
This commit is contained in:
Sascha Grunert
2020-01-20 12:31:09 +01:00
committed by Atomic Bot
parent 0c3234f226
commit 6417a9a074
10 changed files with 131 additions and 5 deletions

View File

@ -301,6 +301,11 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budOptions) error {
capabilities := defaultContainerConfig.Capabilities("", iopts.CapAdd, iopts.CapDrop)
os, arch, err := parse.PlatformFromOptions(c)
if err != nil {
return err
}
options := imagebuildah.BuildOptions{
ContextDirectory: contextDir,
PullPolicy: pullPolicy,
@ -341,6 +346,8 @@ func budCmd(c *cobra.Command, inputArgs []string, iopts budOptions) error {
Devices: devices,
DefaultEnv: defaultContainerConfig.GetDefaultEnv(),
SignBy: iopts.SignBy,
Architecture: arch,
OS: os,
}
if iopts.Quiet {

View File

@ -300,6 +300,14 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
case archive.Gzip:
systemContext.DirForceCompress = true
}
if systemContext.ArchitectureChoice != b.Architecture() {
systemContext.ArchitectureChoice = b.Architecture()
}
if systemContext.OSChoice != b.OS() {
systemContext.OSChoice = b.OS()
}
var manifestBytes []byte
if manifestBytes, err = cp.Image(ctx, policyContext, maybeCachedDest, maybeCachedSrc, getCopyOptions(b.store, options.ReportWriter, nil, systemContext, "", false, options.SignBy)); err != nil {
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)

View File

@ -375,6 +375,7 @@ return 1
"
local options_with_args="
--arch
--add-host
--annotation
--authfile
@ -410,6 +411,7 @@ return 1
--net
--network
--no-pivot
--os
--pid
--platform
--runtime

View File

@ -42,6 +42,10 @@ Add an image *annotation* (e.g. annotation=*value*) to the image metadata. Can b
Note: this information is not present in Docker image formats, so it is discarded when writing images in Docker formats.
**--arch**="ARCH"
Set the ARCH instead of the architecture of the current machine in the image manifest and config.
**--authfile** *path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `buildah login`.
@ -327,6 +331,10 @@ another process.
Do not use existing cached images for the container build. Build from the start with a new set of cached layers.
**--os**="OS"
Set the OS instead of the current operating system of the machine in the image manifest and config.
**--pid** *how*
Sets the configuration for PID namespaces when handling `RUN` instructions.
@ -336,11 +344,11 @@ that the PID namespace in which `buildah` itself is being run should be reused,
or it can be the path to a PID namespace which is already in use by another
process.
**--platform**="Linux"
**--platform**="OS/ARCH"
This option has no effect on the build. Other container engines use this option
to control the execution platform for the build (e.g., Windows, Linux) which is
not required for Buildah as it supports only Linux.
Set the OS/ARCH instead of the current operating system and architecture of the
machine in the image manifest and config (for example `linux/arm`). If
`--platform` is set, then the values of `--arch` and `--os` will be overwritten.
**--pull**

View File

@ -160,6 +160,10 @@ type BuildOptions struct {
DefaultEnv []string
// SignBy is the fingerprint of a GPG key to use for signing images.
SignBy string
// Architecture specifies the target architecture of the image to be built.
Architecture string
// OS is the specifies the operating system of the image to be built.
OS string
}
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be

View File

@ -94,6 +94,8 @@ type Executor struct {
capabilities []string
devices []configs.Device
signBy string
architecture string
os string
}
// NewExecutor creates a new instance of the imagebuilder.Executor interface.
@ -151,6 +153,8 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
capabilities: options.Capabilities,
devices: options.Devices,
signBy: options.SignBy,
architecture: options.Architecture,
os: options.OS,
}
if exec.err == nil {
exec.err = os.Stderr

View File

@ -1132,6 +1132,8 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
}
s.builder.SetHostname(config.Hostname)
s.builder.SetDomainname(config.Domainname)
s.builder.SetArchitecture(s.executor.architecture)
s.builder.SetOS(s.executor.os)
s.builder.SetUser(config.User)
s.builder.ClearPorts()
for p := range config.ExposedPorts {

View File

@ -11,6 +11,7 @@ import (
"strings"
"github.com/containers/buildah"
"github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util"
"github.com/containers/common/pkg/config"
"github.com/opencontainers/runtime-spec/specs-go"
@ -46,6 +47,7 @@ type NameSpaceResults struct {
// BudResults represents the results for Bud flags
type BudResults struct {
Annotation []string
Arch string
Authfile string
BuildArg []string
CacheFrom string
@ -61,6 +63,7 @@ type BudResults struct {
Logfile string
Loglevel int
NoCache bool
OS string
Platform string
Pull bool
PullAlways bool
@ -145,6 +148,7 @@ func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
// GetBudFlags returns common bud flags
func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs := pflag.FlagSet{}
fs.StringVar(&flags.Arch, "arch", runtime.GOARCH, "set the ARCH instead of the architecture of the current machine in the image manifest and config")
fs.StringArrayVar(&flags.Annotation, "annotation", []string{}, "Set metadata for an image (default [])")
fs.StringVar(&flags.Authfile, "authfile", GetDefaultAuthFile(), "path of the authentication file.")
fs.StringArrayVar(&flags.BuildArg, "build-arg", []string{}, "`argument=value` to supply to the builder")
@ -161,7 +165,8 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.BoolVar(&flags.NoCache, "no-cache", false, "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.")
fs.StringVar(&flags.Logfile, "logfile", "", "log to `file` instead of stdout/stderr")
fs.IntVar(&flags.Loglevel, "loglevel", 0, "adjust logging level (range from -2 to 3)")
fs.StringVar(&flags.Platform, "platform", "", "CLI compatibility: no action or effect")
fs.StringVar(&flags.OS, "os", runtime.GOOS, "set the OS instead of the current operating system of the machine in the image manifest and config")
fs.StringVar(&flags.Platform, "platform", parse.DefaultPlatform(), "set the OS/ARCH instead of the current operating system and architecture of the machine in the image manifest and config (for example `linux/arm`)")
fs.BoolVar(&flags.Pull, "pull", true, "pull the image from the registry if newer or not present in store, if false, only pull the image if not present")
fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image even if the named image is present in store")
fs.BoolVar(&flags.PullNever, "pull-never", false, "do not pull the image, use the image present in store if available")

View File

@ -9,6 +9,7 @@ import (
"net"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"unicode"
@ -606,6 +607,46 @@ func getAuthFile(authfile string) string {
return os.Getenv("REGISTRY_AUTH_FILE")
}
// PlatformFromOptions parses the operating system (os) and architecture (arch)
// from the provided command line options.
func PlatformFromOptions(c *cobra.Command) (os, arch string, err error) {
os = runtime.GOOS
arch = runtime.GOARCH
if selectedOS, err := c.Flags().GetString("os"); err == nil && selectedOS != runtime.GOOS {
os = selectedOS
}
if selectedArch, err := c.Flags().GetString("arch"); err == nil && selectedArch != runtime.GOARCH {
arch = selectedArch
}
if pf, err := c.Flags().GetString("platform"); err == nil && pf != DefaultPlatform() {
selectedOS, selectedArch, err := parsePlatform(pf)
if err != nil {
return "", "", errors.Wrap(err, "unable to parse platform")
}
arch = selectedArch
os = selectedOS
}
return os, arch, nil
}
const platformSep = "/"
// DefaultPlatform returns the standard platform for the current system
func DefaultPlatform() string {
return runtime.GOOS + platformSep + runtime.GOARCH
}
func parsePlatform(platform string) (os, arch string, err error) {
split := strings.Split(platform, platformSep)
if len(split) != 2 {
return "", "", errors.Errorf("invalid platform syntax for %q (use OS/ARCH)", platform)
}
return split[0], split[1], nil
}
func parseCreds(creds string) (string, string) {
if creds == "" {
return "", ""

View File

@ -1750,3 +1750,48 @@ EOM
run_buildah run testctr-working-container ls /file-0.0.1.txt
run_buildah rm -a
}
@test "bud with custom arch" {
run_buildah bud --signature-policy ${TESTSDIR}/policy.json \
-f ${TESTSDIR}/bud/from-scratch/Dockerfile \
-t arch-test \
--arch=arm
run_buildah inspect --format "{{ .Docker.Architecture }}" arch-test
expect_output arm
run_buildah inspect --format "{{ .OCIv1.Architecture }}" arch-test
expect_output arm
}
@test "bud with custom os" {
run_buildah bud --signature-policy ${TESTSDIR}/policy.json \
-f ${TESTSDIR}/bud/from-scratch/Dockerfile \
-t os-test \
--os=windows
run_buildah inspect --format "{{ .Docker.OS }}" os-test
expect_output windows
run_buildah inspect --format "{{ .OCIv1.OS }}" os-test
expect_output windows
}
@test "bud with custom platform" {
run_buildah bud --signature-policy ${TESTSDIR}/policy.json \
-f ${TESTSDIR}/bud/from-scratch/Dockerfile \
-t platform-test \
--platform=windows/arm
run_buildah inspect --format "{{ .Docker.OS }}" platform-test
expect_output windows
run_buildah inspect --format "{{ .OCIv1.OS }}" platform-test
expect_output windows
run_buildah inspect --format "{{ .Docker.Architecture }}" platform-test
expect_output arm
run_buildah inspect --format "{{ .OCIv1.Architecture }}" platform-test
expect_output arm
}