summaryrefslogtreecommitdiff
path: root/cmd/podman/build.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/build.go')
-rw-r--r--cmd/podman/build.go410
1 files changed, 158 insertions, 252 deletions
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 92823f72b..180b43cbc 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -1,270 +1,176 @@
package main
import (
- "fmt"
"os"
- "os/exec"
- "strconv"
+ "path/filepath"
+ "strings"
"github.com/pkg/errors"
+ "github.com/projectatomic/buildah/imagebuildah"
+ buildahcli "github.com/projectatomic/buildah/pkg/cli"
+ "github.com/projectatomic/buildah/pkg/parse"
+ "github.com/projectatomic/libpod/cmd/podman/libpodruntime"
+ "github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
- buildFlags = []cli.Flag{
- // The following flags are emulated from:
- // src/github.com/projectatomic/buildah/cmd/bud.go
- cli.StringFlag{
- Name: "authfile",
- Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
- },
- cli.StringSliceFlag{
- Name: "build-arg",
- Usage: "`argument=value` to supply to the builder",
- },
- cli.StringFlag{
- Name: "cert-dir",
- Value: "",
- Usage: "use certificates at the specified path to access the registry",
- },
- cli.StringFlag{
- Name: "creds",
- Value: "",
- Usage: "use `[username[:password]]` for accessing the registry",
- },
- cli.StringSliceFlag{
- Name: "file, f",
- Usage: "`pathname or URL` of a Dockerfile",
- },
- cli.StringFlag{
- Name: "format",
- Usage: "`format` of the built image's manifest and metadata",
- },
- cli.BoolFlag{
- Name: "pull-always",
- Usage: "pull the image, even if a version is present",
- },
- cli.BoolFlag{
- Name: "quiet, q",
- Usage: "refrain from announcing build instructions and image read/write progress",
- },
- cli.StringFlag{
- Name: "runtime",
- Usage: "`path` to an alternate runtime",
- },
- cli.StringSliceFlag{
- Name: "runtime-flag",
- Usage: "add global flags for the container runtime",
- },
- cli.StringFlag{
- Name: "signature-policy",
- Usage: "`pathname` of signature policy file (not usually used)",
- },
- cli.StringSliceFlag{
- Name: "tag, t",
- Usage: "`tag` to apply to the built image",
- },
- cli.BoolFlag{
- Name: "tls-verify",
- Usage: "require HTTPS and verify certificates when accessing the registry",
- },
- // The following flags are emulated from:
- // src/github.com/projectatomic/buildah/cmd/common.go fromAndBudFlags
- cli.StringSliceFlag{
- Name: "add-host",
- Usage: "add a custom host-to-IP mapping (host:ip) (default [])",
- },
- cli.StringFlag{
- Name: "cgroup-parent",
- Usage: "optional parent cgroup for the container",
- },
- cli.Uint64Flag{
- Name: "cpu-period",
- Usage: "limit the CPU CFS (Completely Fair Scheduler) period",
- },
- cli.Int64Flag{
- Name: "cpu-quota",
- Usage: "limit the CPU CFS (Completely Fair Scheduler) quota",
- },
- cli.Uint64Flag{
- Name: "cpu-shares",
- Usage: "CPU shares (relative weight)",
- },
- cli.StringFlag{
- Name: "cpuset-cpus",
- Usage: "CPUs in which to allow execution (0-3, 0,1)",
- },
- cli.StringFlag{
- Name: "cpuset-mems",
- Usage: "memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
- },
- cli.StringFlag{
- Name: "memory, m",
- Usage: "memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
- },
- cli.StringFlag{
- Name: "memory-swap",
- Usage: "swap limit equal to memory plus swap: '-1' to enable unlimited swap",
- },
- cli.StringSliceFlag{
- Name: "security-opt",
- Usage: "security Options (default [])",
- },
- cli.StringFlag{
- Name: "shm-size",
- Usage: "size of `/dev/shm`. The format is `<number><unit>`.",
- Value: "65536k",
- },
- cli.StringSliceFlag{
- Name: "ulimit",
- Usage: "ulimit options (default [])",
- },
- cli.StringSliceFlag{
- Name: "volume, v",
- Usage: "bind mount a volume into the container (default [])",
- },
- }
buildDescription = "podman build launches the Buildah command to build an OCI Image. Buildah must be installed for this command to work."
buildCommand = cli.Command{
- Name: "build",
- Usage: "Build an image using instructions in a Dockerfile",
- Description: buildDescription,
- Flags: buildFlags,
- Action: buildCmd,
- ArgsUsage: "CONTEXT-DIRECTORY | URL",
+ Name: "build",
+ Usage: "Build an image using instructions in a Dockerfile",
+ Description: buildDescription,
+ Flags: append(buildahcli.BudFlags, buildahcli.FromAndBudFlags...),
+ Action: buildCmd,
+ ArgsUsage: "CONTEXT-DIRECTORY | URL",
+ SkipArgReorder: true,
}
)
func buildCmd(c *cli.Context) error {
-
- budCmdArgs := []string{}
-
- // Handle Global Options
- logLevel := c.GlobalString("log-level")
- if logLevel == "debug" {
- budCmdArgs = append(budCmdArgs, "--debug")
- }
- if c.GlobalIsSet("root") {
- budCmdArgs = append(budCmdArgs, "--root", c.GlobalString("root"))
- }
- if c.GlobalIsSet("runroot") {
- budCmdArgs = append(budCmdArgs, "--runroot", c.GlobalString("runroot"))
- }
- if c.GlobalIsSet("storage-driver") {
- budCmdArgs = append(budCmdArgs, "--storage-driver", c.GlobalString("storage-driver"))
- }
- for _, storageOpt := range c.GlobalStringSlice("storage-opt") {
- budCmdArgs = append(budCmdArgs, "--storage-opt", storageOpt)
- }
-
- budCmdArgs = append(budCmdArgs, "bud")
-
- // Buildah bud specific options
- if c.IsSet("authfile") {
- budCmdArgs = append(budCmdArgs, "--authfile", c.String("authfile"))
- }
- for _, buildArg := range c.StringSlice("build-arg") {
- budCmdArgs = append(budCmdArgs, "--build-arg", buildArg)
- }
- if c.IsSet("cert-dir") {
- budCmdArgs = append(budCmdArgs, "--cert-dir", c.String("cert-dir"))
- }
- if c.IsSet("creds") {
- budCmdArgs = append(budCmdArgs, "--creds", c.String("creds"))
- }
- for _, fileName := range c.StringSlice("file") {
- budCmdArgs = append(budCmdArgs, "--file", fileName)
- }
+ // The following was taken directly from projectatomic/buildah/cmd/bud.go
+ // TODO Find a away to vendor more of this in rather than copy from bud
+ output := ""
+ tags := []string{}
+ if c.IsSet("tag") || c.IsSet("t") {
+ tags = c.StringSlice("tag")
+ if len(tags) > 0 {
+ output = tags[0]
+ tags = tags[1:]
+ }
+ }
+ pullPolicy := imagebuildah.PullNever
+ if c.BoolT("pull") {
+ pullPolicy = imagebuildah.PullIfMissing
+ }
+ if c.Bool("pull-always") {
+ pullPolicy = imagebuildah.PullAlways
+ }
+
+ args := make(map[string]string)
+ if c.IsSet("build-arg") {
+ for _, arg := range c.StringSlice("build-arg") {
+ av := strings.SplitN(arg, "=", 2)
+ if len(av) > 1 {
+ args[av[0]] = av[1]
+ } else {
+ delete(args, av[0])
+ }
+ }
+ }
+
+ dockerfiles := c.StringSlice("file")
+ format := "oci"
if c.IsSet("format") {
- budCmdArgs = append(budCmdArgs, "--format", c.String("format"))
- }
- if c.IsSet("pull-always") {
- budCmdArgs = append(budCmdArgs, "--pull-always")
- }
- if c.IsSet("quiet") {
- quietParam := "--quiet=" + strconv.FormatBool(c.Bool("quiet"))
- budCmdArgs = append(budCmdArgs, quietParam)
- }
- if c.IsSet("runtime") {
- budCmdArgs = append(budCmdArgs, "--runtime", c.String("runtime"))
- }
- for _, runtimeArg := range c.StringSlice("runtime-flag") {
- budCmdArgs = append(budCmdArgs, "--runtime-flag", runtimeArg)
- }
- if c.IsSet("signature-policy") {
- budCmdArgs = append(budCmdArgs, "--signature-policy", c.String("signature-policy"))
- }
- for _, tagArg := range c.StringSlice("tag") {
- budCmdArgs = append(budCmdArgs, "--tag", tagArg)
- }
- if c.IsSet("tls-verify") {
- tlsParam := "--tls-verify=" + strconv.FormatBool(c.Bool("tls-verify"))
- budCmdArgs = append(budCmdArgs, tlsParam)
- }
-
- // Buildah bud and from options from cmd/buildah/common.go
- for _, addHostArg := range c.StringSlice("add-host") {
- budCmdArgs = append(budCmdArgs, "--add-host", addHostArg)
- }
- if c.IsSet("cgroup-parent") {
- budCmdArgs = append(budCmdArgs, "--cgroup-parent", c.String("cgroup-parent"))
- }
- if c.IsSet("cpu-period") {
- budCmdArgs = append(budCmdArgs, "--cpu-period", fmt.Sprintf("%v", c.Int64("cpu-period")))
- }
- if c.IsSet("cpu-quota") {
- budCmdArgs = append(budCmdArgs, "--cpu-quota", fmt.Sprintf("%v", c.Uint64("cpu-quota")))
- }
- if c.IsSet("cpu-shares") {
- budCmdArgs = append(budCmdArgs, "--cpu-shares", fmt.Sprintf("%v", c.Uint64("cpu-shares")))
- }
- if c.IsSet("cpuset-cpus") {
- budCmdArgs = append(budCmdArgs, "--cpuset-cpus", c.String("cpuset-cpus"))
- }
- if c.IsSet("cpuset-mems") {
- budCmdArgs = append(budCmdArgs, "--cpuset-mems", c.String("cpuset-mems"))
- }
- if c.IsSet("memory") {
- budCmdArgs = append(budCmdArgs, "--memory", c.String("memory"))
- }
- if c.IsSet("memory-swap") {
- budCmdArgs = append(budCmdArgs, "--memory-swap", c.String("memory-swap"))
- }
- for _, securityOptArg := range c.StringSlice("security-opt") {
- budCmdArgs = append(budCmdArgs, "--security-opt", securityOptArg)
- }
- if c.IsSet("shm-size") {
- budCmdArgs = append(budCmdArgs, "--shm-size", c.String("shm-size"))
- }
- for _, ulimitArg := range c.StringSlice("ulimit") {
- budCmdArgs = append(budCmdArgs, "--ulimit", ulimitArg)
- }
- for _, volumeArg := range c.StringSlice("volume") {
- budCmdArgs = append(budCmdArgs, "--volume", volumeArg)
- }
-
- if len(c.Args()) > 0 {
- budCmdArgs = append(budCmdArgs, c.Args()...)
- }
-
- buildah := "buildah"
-
- if _, err := exec.LookPath(buildah); err != nil {
- return errors.Wrapf(err, "buildah not found in PATH")
- }
- if _, err := exec.Command(buildah).Output(); err != nil {
- return errors.Wrapf(err, "buildah is not operational on this server")
- }
-
- cmd := exec.Command(buildah, budCmdArgs...)
-
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
-
- if err := cmd.Run(); err != nil {
- return errors.Wrapf(err, "error running the buildah build-using-dockerfile (bud) command")
- }
-
- return nil
+ format = strings.ToLower(c.String("format"))
+ }
+ if strings.HasPrefix(format, "oci") {
+ format = imagebuildah.OCIv1ImageFormat
+ } else if strings.HasPrefix(format, "docker") {
+ format = imagebuildah.Dockerv2ImageFormat
+ } else {
+ return errors.Errorf("unrecognized image type %q", format)
+ }
+ contextDir := ""
+ cliArgs := c.Args()
+ if len(cliArgs) > 0 {
+ // The context directory could be a URL. Try to handle that.
+ tempDir, subDir, err := imagebuildah.TempDirForURL("", "buildah", cliArgs[0])
+ if err != nil {
+ return errors.Wrapf(err, "error prepping temporary context directory")
+ }
+ if tempDir != "" {
+ // We had to download it to a temporary directory.
+ // Delete it later.
+ defer func() {
+ if err = os.RemoveAll(tempDir); err != nil {
+ logrus.Errorf("error removing temporary directory %q: %v", contextDir, err)
+ }
+ }()
+ contextDir = filepath.Join(tempDir, subDir)
+ } else {
+ // Nope, it was local. Use it as is.
+ absDir, err := filepath.Abs(cliArgs[0])
+ if err != nil {
+ return errors.Wrapf(err, "error determining path to directory %q", cliArgs[0])
+ }
+ contextDir = absDir
+ }
+ cliArgs = cliArgs.Tail()
+ } else {
+ // No context directory or URL was specified. Try to use the
+ // home of the first locally-available Dockerfile.
+ for i := range dockerfiles {
+ if strings.HasPrefix(dockerfiles[i], "http://") ||
+ strings.HasPrefix(dockerfiles[i], "https://") ||
+ strings.HasPrefix(dockerfiles[i], "git://") ||
+ strings.HasPrefix(dockerfiles[i], "github.com/") {
+ continue
+ }
+ absFile, err := filepath.Abs(dockerfiles[i])
+ if err != nil {
+ return errors.Wrapf(err, "error determining path to file %q", dockerfiles[i])
+ }
+ contextDir = filepath.Dir(absFile)
+ dockerfiles[i], err = filepath.Rel(contextDir, absFile)
+ if err != nil {
+ return errors.Wrapf(err, "error determining path to file %q", dockerfiles[i])
+ }
+ break
+ }
+ }
+ if contextDir == "" {
+ return errors.Errorf("no context directory specified, and no dockerfile specified")
+ }
+ if len(dockerfiles) == 0 {
+ dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile"))
+ }
+ if err := parse.ValidateFlags(c, buildahcli.BudFlags); err != nil {
+ return err
+ }
+
+ runtimeFlags := []string{}
+ for _, arg := range c.StringSlice("runtime-flag") {
+ runtimeFlags = append(runtimeFlags, "--"+arg)
+ }
+ // end from buildah
+
+ runtime, err := libpodruntime.GetRuntime(c)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ systemContext, err := parse.SystemContextFromOptions(c)
+ if err != nil {
+ return errors.Wrapf(err, "error building system context")
+ }
+
+ commonOpts, err := parse.ParseCommonBuildOptions(c)
+ if err != nil {
+ return err
+ }
+
+ options := imagebuildah.BuildOptions{
+ ContextDirectory: contextDir,
+ PullPolicy: pullPolicy,
+ Compression: imagebuildah.Gzip,
+ Quiet: c.Bool("quiet"),
+ SignaturePolicyPath: c.String("signature-policy"),
+ Args: args,
+ Output: output,
+ AdditionalTags: tags,
+ Runtime: c.String("runtime"),
+ RuntimeArgs: runtimeFlags,
+ OutputFormat: format,
+ SystemContext: systemContext,
+ CommonBuildOpts: commonOpts,
+ DefaultMountsFilePath: c.GlobalString("default-mounts-file"),
+ }
+
+ if !c.Bool("quiet") {
+ options.ReportWriter = os.Stderr
+ }
+
+ return runtime.Build(getContext(), options, dockerfiles...)
}