aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-09-06 16:10:06 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-09-07 12:57:09 +0000
commitd92650a922fa82852d6f3310eff24e6b8a93fb03 (patch)
treea4430220fe8529b7cfd29685c36472616b48db54
parent782caea8015679e5d67d15b9562488da06cdfcd5 (diff)
downloadpodman-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.go26
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/projectatomic/buildah/bind/mount.go1
-rw-r--r--vendor/github.com/projectatomic/buildah/chroot/run.go70
-rw-r--r--vendor/github.com/projectatomic/buildah/chroot/seccomp.go2
-rw-r--r--vendor/github.com/projectatomic/buildah/config_noseccomp.go11
-rw-r--r--vendor/github.com/projectatomic/buildah/pkg/cli/common.go21
-rw-r--r--vendor/github.com/projectatomic/buildah/run.go41
-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.go15
-rw-r--r--vendor/github.com/projectatomic/buildah/selinux.go12
-rw-r--r--vendor/github.com/projectatomic/buildah/selinux_unsupported.go10
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) {
+}