diff options
author | baude <bbaude@redhat.com> | 2018-09-06 16:10:06 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-09-07 12:57:09 +0000 |
commit | d92650a922fa82852d6f3310eff24e6b8a93fb03 (patch) | |
tree | a4430220fe8529b7cfd29685c36472616b48db54 | |
parent | 782caea8015679e5d67d15b9562488da06cdfcd5 (diff) | |
download | podman-d92650a922fa82852d6f3310eff24e6b8a93fb03.tar.gz podman-d92650a922fa82852d6f3310eff24e6b8a93fb03.tar.bz2 podman-d92650a922fa82852d6f3310eff24e6b8a93fb03.zip |
use layer cache when building images
to more closely mimic docker default behavior, the --layers
cli option is set to true by default for podman. the buildah
environment variable of BUILDAH_LAYERS is still honored and will
override the command line input.
this should be considered in place of PR #1383.
Many thanks for Scott McCarty for inspiring this welcome change.
Signed-off-by: baude <bbaude@redhat.com>
Closes: #1422
Approved by: rhatdan
-rw-r--r-- | cmd/podman/build.go | 26 | ||||
-rw-r--r-- | vendor.conf | 2 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/bind/mount.go | 1 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/chroot/run.go | 70 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/chroot/seccomp.go | 2 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/config_noseccomp.go | 11 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/pkg/cli/common.go | 21 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/run.go | 41 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/seccomp.go (renamed from vendor/github.com/projectatomic/buildah/config_seccomp.go) | 2 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/seccomp_unsupported.go | 15 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/selinux.go | 12 | ||||
-rw-r--r-- | vendor/github.com/projectatomic/buildah/selinux_unsupported.go | 10 |
12 files changed, 172 insertions, 41 deletions
diff --git a/cmd/podman/build.go b/cmd/podman/build.go index d229cde03..0ca0b3d83 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -1,11 +1,6 @@ package main import ( - "io/ioutil" - "os" - "path/filepath" - "strings" - "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" @@ -15,16 +10,26 @@ import ( "github.com/projectatomic/buildah/pkg/parse" "github.com/sirupsen/logrus" "github.com/urfave/cli" + "io/ioutil" + "os" + "path/filepath" + "strings" ) var ( + layerFlags = []cli.Flag{ + cli.BoolTFlag{ + Name: "layers", + Usage: "cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. ", + }, + } buildDescription = "Builds an OCI or Docker image using instructions from one\n" + "or more Dockerfiles and a specified build context directory." buildCommand = cli.Command{ Name: "build", Usage: "Build an image using instructions from Dockerfiles", Description: buildDescription, - Flags: append(buildahcli.BudFlags, buildahcli.FromAndBudFlags...), + Flags: append(append(buildahcli.BudFlags, layerFlags...), buildahcli.FromAndBudFlags...), Action: buildCmd, ArgsUsage: "CONTEXT-DIRECTORY | URL", SkipArgReorder: true, @@ -84,6 +89,13 @@ func buildCmd(c *cli.Context) error { } contextDir := "" cliArgs := c.Args() + + layers := c.BoolT("layers") // layers for podman defaults to true + // Check to see if the BUILDAH_LAYERS environment variable is set and override command-line + if _, ok := os.LookupEnv("BUILDAH_LAYERS"); ok { + layers = buildahcli.UseLayers() + } + if len(cliArgs) > 0 { // The context directory could be a URL. Try to handle that. tempDir, subDir, err := imagebuildah.TempDirForURL("", "buildah", cliArgs[0]) @@ -215,7 +227,7 @@ func buildCmd(c *cli.Context) error { Squash: c.Bool("squash"), Labels: c.StringSlice("label"), Annotations: c.StringSlice("annotation"), - Layers: c.Bool("layers"), + Layers: layers, NoCache: c.Bool("no-cache"), RemoveIntermediateCtrs: c.BoolT("rm"), ForceRmIntermediateCtrs: c.Bool("force-rm"), diff --git a/vendor.conf b/vendor.conf index 9d5870cf8..682b597b9 100644 --- a/vendor.conf +++ b/vendor.conf @@ -90,7 +90,7 @@ k8s.io/kube-openapi 275e2ce91dec4c05a4094a7b1daee5560b555ac9 https://github.com/ k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e https://github.com/kubernetes/utils github.com/mrunalp/fileutils master github.com/varlink/go master -github.com/projectatomic/buildah 2423a90e23ced88c72e30664631af18c9af75148 +github.com/projectatomic/buildah 9c8c58c33b0b6e15f2fa780042ef46552a8a26d4 github.com/Nvveen/Gotty master github.com/fsouza/go-dockerclient master github.com/openshift/imagebuilder master diff --git a/vendor/github.com/projectatomic/buildah/bind/mount.go b/vendor/github.com/projectatomic/buildah/bind/mount.go index 9f55ae468..695bde554 100644 --- a/vendor/github.com/projectatomic/buildah/bind/mount.go +++ b/vendor/github.com/projectatomic/buildah/bind/mount.go @@ -133,6 +133,7 @@ func SetupIntermediateMountNamespace(spec *specs.Spec, bundlePath string) (unmou if err = unix.Mount(rootPath, rootfs, "", unix.MS_BIND|unix.MS_REC|unix.MS_PRIVATE, ""); err != nil { return unmountAll, errors.Wrapf(err, "error bind mounting root filesystem from %q to %q", rootPath, rootfs) } + logrus.Debugf("bind mounted %q to %q", rootPath, rootfs) unmount = append([]string{rootfs}, unmount...) spec.Root.Path = rootfs diff --git a/vendor/github.com/projectatomic/buildah/chroot/run.go b/vendor/github.com/projectatomic/buildah/chroot/run.go index 2cae5b9da..9a70e0f51 100644 --- a/vendor/github.com/projectatomic/buildah/chroot/run.go +++ b/vendor/github.com/projectatomic/buildah/chroot/run.go @@ -98,6 +98,7 @@ func RunUsingChroot(spec *specs.Spec, bundlePath string, stdin io.Reader, stdout if err = ioutils.AtomicWriteFile(filepath.Join(bundlePath, "config.json"), specbytes, 0600); err != nil { return errors.Wrapf(err, "error storing runtime configuration") } + logrus.Debugf("config = %v", string(specbytes)) // Run the grandparent subprocess in a user namespace that reuses the mappings that we have. uidmap, gidmap, err := util.GetHostIDMappings("") @@ -381,11 +382,15 @@ func runUsingChrootMain() { logrus.Error(what) return false } - for readFd := range relays { + for readFd, writeFd := range relays { if err := unix.SetNonblock(readFd, true); err != nil { logrus.Errorf("error setting descriptor %d (%s) non-blocking: %v", readFd, fdDesc[readFd], err) return } + if err := unix.SetNonblock(writeFd, false); err != nil { + logrus.Errorf("error setting descriptor %d (%s) blocking: %v", relays[writeFd], fdDesc[writeFd], err) + return + } } go func() { buffers := make(map[int]*bytes.Buffer) @@ -429,6 +434,26 @@ func runUsingChrootMain() { continue } } + // If this is the last of the data we'll be able to read + // from this descriptor, read as much as there is to read. + for rfd.Revents&unix.POLLHUP == unix.POLLHUP { + nr, err := unix.Read(int(rfd.Fd), b) + logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err)) + if nr <= 0 { + break + } + if wfd, ok := relays[int(rfd.Fd)]; ok { + nwritten, err := buffers[wfd].Write(b[:nr]) + if err != nil { + logrus.Debugf("buffer: %v", err) + break + } + if nwritten != nr { + logrus.Debugf("buffer: expected to buffer %d bytes, wrote %d", nr, nwritten) + break + } + } + } } if nread == 0 { removeFds[int(rfd.Fd)] = struct{}{} @@ -592,8 +617,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io // main() for parent subprocess. Its main job is to try to make our // environment look like the one described by the runtime configuration blob, -// and then launch the intended command as a child, since we can't exec() -// directly. +// and then launch the intended command as a child. func runUsingChrootExecMain() { args := os.Args[1:] var options runUsingChrootExecSubprocOptions @@ -630,6 +654,31 @@ func runUsingChrootExecMain() { } } + // Try to chroot into the root. Do this before we potentially block the syscall via the + // seccomp profile. + var oldst, newst unix.Stat_t + if err := unix.Stat(options.Spec.Root.Path, &oldst); err != nil { + fmt.Fprintf(os.Stderr, "error stat()ing intended root directory %q: %v\n", options.Spec.Root.Path, err) + os.Exit(1) + } + if err := unix.Chdir(options.Spec.Root.Path); err != nil { + fmt.Fprintf(os.Stderr, "error chdir()ing to intended root directory %q: %v\n", options.Spec.Root.Path, err) + os.Exit(1) + } + if err := unix.Chroot(options.Spec.Root.Path); err != nil { + fmt.Fprintf(os.Stderr, "error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err) + os.Exit(1) + } + if err := unix.Stat("/", &newst); err != nil { + fmt.Fprintf(os.Stderr, "error stat()ing current root directory: %v\n", err) + os.Exit(1) + } + if oldst.Dev != newst.Dev || oldst.Ino != newst.Ino { + fmt.Fprintf(os.Stderr, "unknown error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err) + os.Exit(1) + } + logrus.Debugf("chrooted into %q", options.Spec.Root.Path) + // not doing because it's still shared: creating devices // not doing because it's not applicable: setting annotations // not doing because it's still shared: setting sysctl settings @@ -663,20 +712,21 @@ func runUsingChrootExecMain() { os.Exit(1) } - // Try to chroot into the root. - if err := unix.Chroot(options.Spec.Root.Path); err != nil { - fmt.Fprintf(os.Stderr, "error chroot()ing into directory %q: %v\n", options.Spec.Root.Path, err) - os.Exit(1) - } + // Try to change to the directory. cwd := options.Spec.Process.Cwd if !filepath.IsAbs(cwd) { cwd = "/" + cwd } + cwd = filepath.Clean(cwd) + if err := unix.Chdir("/"); err != nil { + fmt.Fprintf(os.Stderr, "error chdir()ing into new root directory %q: %v\n", options.Spec.Root.Path, err) + os.Exit(1) + } if err := unix.Chdir(cwd); err != nil { - fmt.Fprintf(os.Stderr, "error chdir()ing into directory %q: %v\n", cwd, err) + fmt.Fprintf(os.Stderr, "error chdir()ing into directory %q under root %q: %v\n", cwd, options.Spec.Root.Path, err) os.Exit(1) } - logrus.Debugf("chrooted into %q, changed working directory to %q", options.Spec.Root.Path, cwd) + logrus.Debugf("changed working directory to %q", cwd) // Drop privileges. user := options.Spec.Process.User diff --git a/vendor/github.com/projectatomic/buildah/chroot/seccomp.go b/vendor/github.com/projectatomic/buildah/chroot/seccomp.go index d5c5842d4..f2c55017f 100644 --- a/vendor/github.com/projectatomic/buildah/chroot/seccomp.go +++ b/vendor/github.com/projectatomic/buildah/chroot/seccomp.go @@ -105,7 +105,7 @@ func setSeccomp(spec *specs.Spec) error { for _, name := range rule.Names { scnum, err := libseccomp.GetSyscallFromName(name) if err != nil { - logrus.Debugf("error mapping syscall %q to a syscall, ignoring %q rule for %q", name, rule.Action) + logrus.Debugf("error mapping syscall %q to a syscall, ignoring %q rule for %q", name, rule.Action, name) continue } scnames[scnum] = name diff --git a/vendor/github.com/projectatomic/buildah/config_noseccomp.go b/vendor/github.com/projectatomic/buildah/config_noseccomp.go deleted file mode 100644 index e8354cc55..000000000 --- a/vendor/github.com/projectatomic/buildah/config_noseccomp.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !seccomp - -package buildah - -import "github.com/opencontainers/runtime-spec/specs-go" - -func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error { - // If no seccomp is being used, the Seccomp profile in the Linux spec - // is not set - return nil -} diff --git a/vendor/github.com/projectatomic/buildah/pkg/cli/common.go b/vendor/github.com/projectatomic/buildah/pkg/cli/common.go index 0d035f471..a438daf6a 100644 --- a/vendor/github.com/projectatomic/buildah/pkg/cli/common.go +++ b/vendor/github.com/projectatomic/buildah/pkg/cli/common.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" "github.com/projectatomic/buildah" "github.com/projectatomic/buildah/util" "github.com/urfave/cli" @@ -68,6 +69,13 @@ var ( }, } + LayerFlags = []cli.Flag{ + cli.BoolFlag{ + Name: "layers", + Usage: fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default %t)", UseLayers()), + }, + } + BudFlags = []cli.Flag{ cli.StringSliceFlag{ Name: "annotation", @@ -130,10 +138,6 @@ var ( Usage: "Set metadata for an image (default [])", }, cli.BoolFlag{ - Name: "layers", - Usage: fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default %t)", UseLayers()), - }, - cli.BoolFlag{ Name: "no-cache", Usage: "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.", }, @@ -280,3 +284,12 @@ func DefaultIsolation() string { } return buildah.OCI } + +func VerifyFlagsArgsOrder(args []string) error { + for _, arg := range args { + if strings.HasPrefix(arg, "-") { + return errors.Errorf("No options (%s) can be specified after the image or container name", arg) + } + } + return nil +} diff --git a/vendor/github.com/projectatomic/buildah/run.go b/vendor/github.com/projectatomic/buildah/run.go index 71a76862e..12560de3c 100644 --- a/vendor/github.com/projectatomic/buildah/run.go +++ b/vendor/github.com/projectatomic/buildah/run.go @@ -973,8 +973,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { } else if b.WorkDir() != "" { g.SetProcessCwd(b.WorkDir()) } - g.SetProcessSelinuxLabel(b.ProcessLabel) - g.SetLinuxMountLabel(b.MountLabel) + setupSelinux(g, b.ProcessLabel, b.MountLabel) mountPoint, err := b.Mount(b.MountLabel) if err != nil { return err @@ -1017,6 +1016,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { if spec.Process.Cwd == "" { spec.Process.Cwd = DefaultWorkingDir } + logrus.Debugf("ensuring working directory %q exists", filepath.Join(mountPoint, spec.Process.Cwd)) if err = os.MkdirAll(filepath.Join(mountPoint, spec.Process.Cwd), 0755); err != nil { return errors.Wrapf(err, "error ensuring working directory %q exists", spec.Process.Cwd) } @@ -1760,11 +1760,14 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy writeDesc[unix.Stderr] = "stderr" } // Set our reading descriptors to non-blocking. - for fd := range relayMap { - if err := unix.SetNonblock(fd, true); err != nil { - logrus.Errorf("error setting %s to nonblocking: %v", readDesc[fd], err) + for rfd, wfd := range relayMap { + if err := unix.SetNonblock(rfd, true); err != nil { + logrus.Errorf("error setting %s to nonblocking: %v", readDesc[rfd], err) return } + if err := unix.SetNonblock(wfd, false); err != nil { + logrus.Errorf("error setting descriptor %d (%s) blocking: %v", wfd, writeDesc[wfd], err) + } } // A helper that returns false if err is an error that would cause us // to give up. @@ -1837,7 +1840,33 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy } if n > 0 { // Buffer the data in case we get blocked on where they need to go. - relayBuffer[writeFD].Write(buf[:n]) + nwritten, err := relayBuffer[writeFD].Write(buf[:n]) + if err != nil { + logrus.Debugf("buffer: %v", err) + continue + } + if nwritten != n { + logrus.Debugf("buffer: expected to buffer %d bytes, wrote %d", n, nwritten) + continue + } + // If this is the last of the data we'll be able to read from this + // descriptor, read all that there is to read. + for pollFd.Revents&unix.POLLHUP == unix.POLLHUP { + nr, err := unix.Read(readFD, buf) + logIfNotRetryable(err, fmt.Sprintf("read %s: %v", readDesc[readFD], err)) + if nr <= 0 { + break + } + nwritten, err := relayBuffer[writeFD].Write(buf[:nr]) + if err != nil { + logrus.Debugf("buffer: %v", err) + break + } + if nwritten != nr { + logrus.Debugf("buffer: expected to buffer %d bytes, wrote %d", nr, nwritten) + break + } + } } } } diff --git a/vendor/github.com/projectatomic/buildah/config_seccomp.go b/vendor/github.com/projectatomic/buildah/seccomp.go index a5bb010c0..a435b5f71 100644 --- a/vendor/github.com/projectatomic/buildah/config_seccomp.go +++ b/vendor/github.com/projectatomic/buildah/seccomp.go @@ -1,4 +1,4 @@ -// +build seccomp +// +build seccomp,linux package buildah diff --git a/vendor/github.com/projectatomic/buildah/seccomp_unsupported.go b/vendor/github.com/projectatomic/buildah/seccomp_unsupported.go new file mode 100644 index 000000000..cba8390c5 --- /dev/null +++ b/vendor/github.com/projectatomic/buildah/seccomp_unsupported.go @@ -0,0 +1,15 @@ +// +build !seccomp !linux + +package buildah + +import ( + "github.com/opencontainers/runtime-spec/specs-go" +) + +func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error { + if spec.Linux != nil { + // runtime-tools may have supplied us with a default filter + spec.Linux.Seccomp = nil + } + return nil +} diff --git a/vendor/github.com/projectatomic/buildah/selinux.go b/vendor/github.com/projectatomic/buildah/selinux.go new file mode 100644 index 000000000..2b850cf9f --- /dev/null +++ b/vendor/github.com/projectatomic/buildah/selinux.go @@ -0,0 +1,12 @@ +// +build selinux,linux + +package buildah + +import ( + "github.com/opencontainers/runtime-tools/generate" +) + +func setupSelinux(g *generate.Generator, processLabel, mountLabel string) { + g.SetProcessSelinuxLabel(processLabel) + g.SetLinuxMountLabel(mountLabel) +} diff --git a/vendor/github.com/projectatomic/buildah/selinux_unsupported.go b/vendor/github.com/projectatomic/buildah/selinux_unsupported.go new file mode 100644 index 000000000..0aa7c46e4 --- /dev/null +++ b/vendor/github.com/projectatomic/buildah/selinux_unsupported.go @@ -0,0 +1,10 @@ +// +build !selinux !linux + +package buildah + +import ( + "github.com/opencontainers/runtime-tools/generate" +) + +func setupSelinux(g *generate.Generator, processLabel, mountLabel string) { +} |