mirror of
https://github.com/containers/podman.git
synced 2025-05-20 00:27:03 +08:00
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
This commit is contained in:
@ -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"),
|
||||
|
@ -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
|
||||
|
1
vendor/github.com/projectatomic/buildah/bind/mount.go
generated
vendored
1
vendor/github.com/projectatomic/buildah/bind/mount.go
generated
vendored
@ -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
|
||||
|
||||
|
72
vendor/github.com/projectatomic/buildah/chroot/run.go
generated
vendored
72
vendor/github.com/projectatomic/buildah/chroot/run.go
generated
vendored
@ -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
|
||||
}
|
||||
if err := unix.Chdir(cwd); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error chdir()ing into directory %q: %v\n", cwd, err)
|
||||
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)
|
||||
}
|
||||
logrus.Debugf("chrooted into %q, changed working directory to %q", options.Spec.Root.Path, cwd)
|
||||
if err := unix.Chdir(cwd); err != nil {
|
||||
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("changed working directory to %q", cwd)
|
||||
|
||||
// Drop privileges.
|
||||
user := options.Spec.Process.User
|
||||
|
2
vendor/github.com/projectatomic/buildah/chroot/seccomp.go
generated
vendored
2
vendor/github.com/projectatomic/buildah/chroot/seccomp.go
generated
vendored
@ -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
|
||||
|
11
vendor/github.com/projectatomic/buildah/config_noseccomp.go
generated
vendored
11
vendor/github.com/projectatomic/buildah/config_noseccomp.go
generated
vendored
@ -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
|
||||
}
|
21
vendor/github.com/projectatomic/buildah/pkg/cli/common.go
generated
vendored
21
vendor/github.com/projectatomic/buildah/pkg/cli/common.go
generated
vendored
@ -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",
|
||||
@ -129,10 +137,6 @@ var (
|
||||
Name: "label",
|
||||
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
|
||||
}
|
||||
|
41
vendor/github.com/projectatomic/buildah/run.go
generated
vendored
41
vendor/github.com/projectatomic/buildah/run.go
generated
vendored
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// +build seccomp
|
||||
// +build seccomp,linux
|
||||
|
||||
package buildah
|
||||
|
15
vendor/github.com/projectatomic/buildah/seccomp_unsupported.go
generated
vendored
Normal file
15
vendor/github.com/projectatomic/buildah/seccomp_unsupported.go
generated
vendored
Normal file
@ -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
|
||||
}
|
12
vendor/github.com/projectatomic/buildah/selinux.go
generated
vendored
Normal file
12
vendor/github.com/projectatomic/buildah/selinux.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
10
vendor/github.com/projectatomic/buildah/selinux_unsupported.go
generated
vendored
Normal file
10
vendor/github.com/projectatomic/buildah/selinux_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// +build !selinux !linux
|
||||
|
||||
package buildah
|
||||
|
||||
import (
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
)
|
||||
|
||||
func setupSelinux(g *generate.Generator, processLabel, mountLabel string) {
|
||||
}
|
Reference in New Issue
Block a user