summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--cmd/podman/build.go128
-rw-r--r--cmd/podman/main.go1
-rw-r--r--completions/bash/podman43
-rw-r--r--docs/podman-build.1.md103
-rw-r--r--test/build/from-multiple-files/Dockerfile1.alpine2
-rw-r--r--test/build/from-multiple-files/Dockerfile1.scratch2
-rw-r--r--test/build/from-multiple-files/Dockerfile2.glob2
-rw-r--r--test/build/from-multiple-files/Dockerfile2.nofrom1
-rw-r--r--test/build/from-multiple-files/Dockerfile2.withfrom2
-rw-r--r--test/build/from-scratch/Dockerfile1
-rw-r--r--test/build/http-context-subdir/context.tarbin0 -> 10240 bytes
-rw-r--r--test/build/http-context/context.tarbin0 -> 10240 bytes
-rw-r--r--test/build/preserve-volumes/Dockerfile22
-rw-r--r--test/build/volume-perms/Dockerfile6
-rw-r--r--test/helpers.bash97
-rw-r--r--test/podman_build.bats265
-rw-r--r--test/test_podman_build.sh172
-rw-r--r--transfer.md2
19 files changed, 849 insertions, 1 deletions
diff --git a/README.md b/README.md
index d7d63d382..b42bd4fe1 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ libpod is currently in active development.
| :------------------------------------------------------- | :------------------------------------------------------------------------ | :----|
| [podman(1)](/docs/podman.1.md) | Simple management tool for pods and images ||
| [podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container ||
+| [podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles ||
| [podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container ||
| [podman-cp(1)](/docs/podman-cp.1.md) | Instead of providing a `podman cp` command, the man page `podman-cp` describes how to use the `podman mount` command to have even more flexibility and functionality||
| [podman-create(1)](/docs/podman-create.1.md) | Create a new container ||
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
new file mode 100644
index 000000000..0defb5e79
--- /dev/null
+++ b/cmd/podman/build.go
@@ -0,0 +1,128 @@
+package main
+
+import (
+ "os"
+ "os/exec"
+ "strconv"
+
+ "github.com/pkg/errors"
+ "github.com/urfave/cli"
+)
+
+var (
+ buildFlags = []cli.Flag{
+ cli.StringSliceFlag{
+ Name: "build-arg",
+ Usage: "`argument=value` to supply to the builder",
+ },
+ 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",
+ },
+ }
+ 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",
+ Aliases: []string{"build"},
+ Usage: "Build an image using instructions in a Dockerfile",
+ Description: buildDescription,
+ Flags: buildFlags,
+ Action: buildCmd,
+ ArgsUsage: "CONTEXT-DIRECTORY | URL",
+ }
+)
+
+func buildCmd(c *cli.Context) error {
+
+ budCmdArgs := []string{"bud"}
+
+ for _, buildArg := range c.StringSlice("build-arg") {
+ budCmdArgs = append(budCmdArgs, "--build-arg", buildArg)
+ }
+ for _, fileName := range c.StringSlice("file") {
+ budCmdArgs = append(budCmdArgs, "--file", fileName)
+ }
+ 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)
+ }
+
+ 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
+}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index d3cb86798..011303349 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -36,6 +36,7 @@ func main() {
app.Commands = []cli.Command{
attachCommand,
commitCommand,
+ buildCommand,
createCommand,
diffCommand,
execCommand,
diff --git a/completions/bash/podman b/completions/bash/podman
index 37f70e24a..abb629bc9 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -684,6 +684,48 @@ _podman_commit() {
esac
}
+_podman_build() {
+ local boolean_options="
+ --build
+ --help
+ -h
+ --pull
+ --pull-always
+ --quiet
+ -q
+ --tls-verify
+ "
+
+ local options_with_args="
+ --signature-policy
+ --runtime
+ --runtime-flag
+ --tag
+ -t
+ --file
+ -f
+ --build-arg
+ --format
+ "
+
+ local all_options="$options_with_args $boolean_options"
+
+ case "$prev" in
+ --runtime)
+ COMPREPLY=($(compgen -W 'runc runv' -- "$cur"))
+ ;;
+ $(__buildah_to_extglob "$options_with_args"))
+ return
+ ;;
+ esac
+
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
_podman_diff() {
local options_with_args="
--format
@@ -1481,6 +1523,7 @@ _podman_podman() {
"
commands="
attach
+ build
commit
create
diff
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
new file mode 100644
index 000000000..8b991e2cf
--- /dev/null
+++ b/docs/podman-build.1.md
@@ -0,0 +1,103 @@
+% podman(1) podman-build - Simple tool to build a container image
+% Tom Sweeney
+# podman-build "7" "December 2017" "podman"
+
+## NAME
+podman-build - Build a container image using a Dockerfile.
+
+## SYNOPSIS
+**podman** **build** [*options* [...]] [**context**]
+
+## DESCRIPTION
+**podman build** Builds an image using instructions from one or more Dockerfiles and a specified
+build context directory. The build context directory can be specified as the
+**http** or **https** URL of an archive which will be retrieved and extracted
+to a temporary location. This command passes the parameters entered in by the user to the
+**buildah bud** command https://github.com/projectatomic/buildah/blob/master/docs/buildah-bud.md
+to do the actual building.
+
+**podman [GLOBAL OPTIONS]**
+
+**podman build [GLOBAL OPTIONS]**
+
+**podman build [OPTIONS] NAME[:TAG|@DIGEST]**
+
+## OPTIONS
+
+**--build-arg** *arg=value*
+
+Specifies a build argument and its value, which will be interpolated in
+instructions read from the Dockerfiles in the same way that environment
+variables are, but which will not be added to environment variable list in the
+resulting image's configuration.
+
+**-f, --file** *Dockerfile*
+
+Specifies a Dockerfile which contains instructions for building the image,
+either a local file or an **http** or **https** URL. If more than one
+Dockerfile is specified, *FROM* instructions will only be accepted from the
+first specified file.
+
+If a build context is not specified, and at least one Dockerfile is a
+local file, the directory in which it resides will be used as the build
+context.
+
+**--format**
+
+Control the format for the built image's manifest and configuration data.
+Recognized formats include *oci* (OCI image-spec v1.0, the default) and
+*docker* (version 2, using schema format 2 for the manifest).
+
+**--pull-always**
+
+Pull the image even if a version of the image is already present.
+
+**--quiet**
+
+Suppress output messages which indicate which instruction is being processed,
+and of progress when pulling images from a registry, and when writing the
+output image.
+
+**--runtime** *path*
+
+The *path* to an alternate OCI-compatible runtime, which will be used to run
+commands specified by the **RUN** instruction.
+
+**--runtime-flag** *flag*
+
+Adds global flags for the container rutime.
+
+**--signature-policy** *signaturepolicy*
+
+Pathname of a signature policy file to use. It is not recommended that this
+option be used, as the default behavior of using the system-wide default policy
+(frequently */etc/containers/policy.json*) is most often preferred.
+
+**-t, --tag** *imageName*
+
+Specifies the name which will be assigned to the resulting image if the build
+process completes successfully.
+
+**--tls-verify** *bool-value*
+
+Require HTTPS and verify certificates when talking to container registries (defaults to true)
+
+## EXAMPLES
+
+podman build .
+
+podman build -f Dockerfile.simple .
+
+podman build -f Dockerfile.simple -f Dockerfile.notsosimple
+
+podman build -t imageName .
+
+podman build --tls-verify=true -t imageName -f Dockerfile.simple
+
+podman build --tls-verify=false -t imageName .
+
+## SEE ALSO
+podman(1), buildah(1)
+
+## HISTORY
+December 2017, Originally compiled by Tom Sweeney <tsweeney@redhat.com>
diff --git a/test/build/from-multiple-files/Dockerfile1.alpine b/test/build/from-multiple-files/Dockerfile1.alpine
new file mode 100644
index 000000000..c6e3fc405
--- /dev/null
+++ b/test/build/from-multiple-files/Dockerfile1.alpine
@@ -0,0 +1,2 @@
+FROM alpine
+COPY Dockerfile1.alpine /Dockerfile1
diff --git a/test/build/from-multiple-files/Dockerfile1.scratch b/test/build/from-multiple-files/Dockerfile1.scratch
new file mode 100644
index 000000000..4f9ab8a60
--- /dev/null
+++ b/test/build/from-multiple-files/Dockerfile1.scratch
@@ -0,0 +1,2 @@
+FROM scratch
+COPY Dockerfile1.scratch /Dockerfile1
diff --git a/test/build/from-multiple-files/Dockerfile2.glob b/test/build/from-multiple-files/Dockerfile2.glob
new file mode 100644
index 000000000..1d843ba07
--- /dev/null
+++ b/test/build/from-multiple-files/Dockerfile2.glob
@@ -0,0 +1,2 @@
+FROM alpine
+COPY Dockerfile* /
diff --git a/test/build/from-multiple-files/Dockerfile2.nofrom b/test/build/from-multiple-files/Dockerfile2.nofrom
new file mode 100644
index 000000000..0473c91d8
--- /dev/null
+++ b/test/build/from-multiple-files/Dockerfile2.nofrom
@@ -0,0 +1 @@
+COPY Dockerfile2.nofrom /
diff --git a/test/build/from-multiple-files/Dockerfile2.withfrom b/test/build/from-multiple-files/Dockerfile2.withfrom
new file mode 100644
index 000000000..fa3b96908
--- /dev/null
+++ b/test/build/from-multiple-files/Dockerfile2.withfrom
@@ -0,0 +1,2 @@
+FROM alpine
+COPY Dockerfile2.withfrom /
diff --git a/test/build/from-scratch/Dockerfile b/test/build/from-scratch/Dockerfile
new file mode 100644
index 000000000..c35f1b5f5
--- /dev/null
+++ b/test/build/from-scratch/Dockerfile
@@ -0,0 +1 @@
+FROM scratch
diff --git a/test/build/http-context-subdir/context.tar b/test/build/http-context-subdir/context.tar
new file mode 100644
index 000000000..533ae524e
--- /dev/null
+++ b/test/build/http-context-subdir/context.tar
Binary files differ
diff --git a/test/build/http-context/context.tar b/test/build/http-context/context.tar
new file mode 100644
index 000000000..2e5f3a515
--- /dev/null
+++ b/test/build/http-context/context.tar
Binary files differ
diff --git a/test/build/preserve-volumes/Dockerfile b/test/build/preserve-volumes/Dockerfile
new file mode 100644
index 000000000..922f565d7
--- /dev/null
+++ b/test/build/preserve-volumes/Dockerfile
@@ -0,0 +1,22 @@
+FROM alpine
+RUN mkdir -p /vol/subvol/subsubvol
+RUN dd if=/dev/zero bs=512 count=1 of=/vol/subvol/subsubvol/subsubvolfile
+VOLUME /vol/subvol
+# At this point, the contents below /vol/subvol should be frozen.
+RUN dd if=/dev/zero bs=512 count=1 of=/vol/subvol/subvolfile
+# In particular, /vol/subvol/subvolfile should be wiped out.
+RUN dd if=/dev/zero bs=512 count=1 of=/vol/volfile
+# However, /vol/volfile should exist.
+VOLUME /vol
+# And this should be redundant.
+VOLUME /vol/subvol
+# And now we've frozen /vol.
+RUN dd if=/dev/zero bs=512 count=1 of=/vol/anothervolfile
+# Which means that in the image we're about to commit, /vol/anothervolfile
+# shouldn't exist, either.
+
+# ADD files which should persist.
+ADD Dockerfile /vol/Dockerfile
+RUN stat /vol/Dockerfile
+ADD Dockerfile /vol/Dockerfile2
+RUN stat /vol/Dockerfile2
diff --git a/test/build/volume-perms/Dockerfile b/test/build/volume-perms/Dockerfile
new file mode 100644
index 000000000..4dced7738
--- /dev/null
+++ b/test/build/volume-perms/Dockerfile
@@ -0,0 +1,6 @@
+FROM alpine
+VOLUME /vol/subvol
+# At this point, the directory should exist, with default permissions 0755, the
+# contents below /vol/subvol should be frozen, and we shouldn't get an error
+# from trying to write to it because we it was created automatically.
+RUN dd if=/dev/zero bs=512 count=1 of=/vol/subvol/subvolfile
diff --git a/test/helpers.bash b/test/helpers.bash
index 2ac203027..16f3483f6 100644
--- a/test/helpers.bash
+++ b/test/helpers.bash
@@ -132,6 +132,57 @@ for key in ${!IMAGES[@]}; do
done
+###
+# Buildah related variables
+###
+BUILDAH_BINARY=${BUILDAH_BINARY:-$(dirname ${BASH_SOURCE})/../buildah}
+BUILDAH_IMGTYPE_BINARY=${BUILDAH_IMGTYPE_BINARY:-$(dirname ${BASH_SOURCE})/../imgtype}
+BUILDAH_TESTSDIR=${BUILDAH_TESTSDIR:-$(dirname ${BASH_SOURCE})}
+BUILDAH_STORAGE_DRIVER=${BUILDAH_STORAGE_DRIVER:-vfs}
+#BUILDAH_PATH=$(dirname ${BASH_SOURCE})/..:${BUILDAH_PATH}
+
+# Make sure we have a copy of the redis:alpine image.
+if ! [ -d "$ARTIFACTS_PATH"/redis-image ]; then
+ mkdir -p "$ARTIFACTS_PATH"/redis-image
+ if ! "$COPYIMG_BINARY" --import-from=docker://redis:alpine --export-to=dir:"$ARTIFACTS_PATH"/redis-image --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
+ echo "Error pulling docker://redis"
+ rm -fr "$ARTIFACTS_PATH"/redis-image
+ exit 1
+ fi
+fi
+
+# TODO: remove the code below for pulling redis:alpine using a canonical reference once
+# https://github.com/kubernetes-incubator/cri-o/issues/531 is complete and we can
+# pull the image using a tagged reference and then subsequently find the image without
+# having to explicitly record the canonical reference as one of the image's names
+if ! [ -d "$ARTIFACTS_PATH"/redis-image-digest ]; then
+ mkdir -p "$ARTIFACTS_PATH"/redis-image-digest
+ if ! "$COPYIMG_BINARY" --import-from=docker://redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b --export-to=dir:"$ARTIFACTS_PATH"/redis-image-digest --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
+ echo "Error pulling docker://redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b"
+ rm -fr "$ARTIFACTS_PATH"/redis-image-digest
+ exit 1
+ fi
+fi
+
+# Make sure we have a copy of the runcom/stderr-test image.
+if ! [ -d "$ARTIFACTS_PATH"/stderr-test ]; then
+ mkdir -p "$ARTIFACTS_PATH"/stderr-test
+ if ! "$COPYIMG_BINARY" --import-from=docker://runcom/stderr-test:latest --export-to=dir:"$ARTIFACTS_PATH"/stderr-test --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
+ echo "Error pulling docker://stderr-test"
+ rm -fr "$ARTIFACTS_PATH"/stderr-test
+ exit 1
+ fi
+fi
+
+# Make sure we have a copy of the busybox:latest image.
+if ! [ -d "$ARTIFACTS_PATH"/busybox-image ]; then
+ mkdir -p "$ARTIFACTS_PATH"/busybox-image
+ if ! "$COPYIMG_BINARY" --import-from=docker://busybox --export-to=dir:"$ARTIFACTS_PATH"/busybox-image --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
+ echo "Error pulling docker://busybox"
+ rm -fr "$ARTIFACTS_PATH"/busybox-image
+ exit 1
+ fi
+fi
# Communicate with Docker on the host machine.
# Should rarely use this.
@@ -260,3 +311,49 @@ function copy_images() {
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=${IMAGES[${key}]} --import-from=dir:"$ARTIFACTS_PATH"/${key} --add-name=${IMAGES[${key}]}
done
}
+
+###
+# Buildah Functions
+###
+function setup() {
+ suffix=$(dd if=/dev/urandom bs=12 count=1 status=none | base64 | tr +/ABCDEFGHIJKLMNOPQRSTUVWXYZ _.abcdefghijklmnopqrstuvwxyz)
+ TESTDIR=${BATS_TMPDIR}/tmp.${suffix}
+ rm -fr ${TESTDIR}
+ mkdir -p ${TESTDIR}/{root,runroot}
+}
+
+function starthttpd() {
+ pushd ${2:-${TESTDIR}} > /dev/null
+ cp ${BUILDAH_TESTSDIR}/serve.go .
+ go build serve.go
+ HTTP_SERVER_PORT=$((RANDOM+32768))
+ ./serve ${HTTP_SERVER_PORT} ${1:-${BATS_TMPDIR}} &
+ HTTP_SERVER_PID=$!
+ popd > /dev/null
+}
+
+function stophttpd() {
+ if test -n "$HTTP_SERVER_PID" ; then
+ kill -HUP ${HTTP_SERVER_PID}
+ unset HTTP_SERVER_PID
+ unset HTTP_SERVER_PORT
+ fi
+ true
+}
+
+function teardown() {
+ stophttpd
+ rm -fr ${TESTDIR}
+}
+
+function createrandom() {
+ dd if=/dev/urandom bs=1 count=${2:-256} of=${1:-${BATS_TMPDIR}/randomfile} status=none
+}
+
+function buildah() {
+ ${BUILDAH_BINARY} --debug --root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${BUILDAH_STORAGE_DRIVER} "$@"
+}
+
+function imgtype() {
+ ${BUILDAH_IMGTYPE_BINARY} -root ${TESTDIR}/root -runroot ${TESTDIR}/runroot -storage-driver ${BUILDAH_STORAGE_DRIVER} "$@"
+}
diff --git a/test/podman_build.bats b/test/podman_build.bats
new file mode 100644
index 000000000..159737019
--- /dev/null
+++ b/test/podman_build.bats
@@ -0,0 +1,265 @@
+#!/usr/bin/env bats
+
+load helpers
+
+@test "build-from-scratch" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} ${BUILDAH_TESTSDIR}/build/from-scratch
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+ [ "$status" -eq 0 ]
+}
+
+@test "build-from-multiple-files-one-from" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.scratch -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.nofrom
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ cmp $root/Dockerfile1 ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.scratch
+ cmp $root/Dockerfile2.nofrom ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.nofrom
+ run test -s $root/etc/passwd
+ [ "$status" -ne 0 ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$status" -eq 0 ]
+ [ "$output" = "" ]
+
+ target=alpine-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.alpine -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.nofrom
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ cmp $root/Dockerfile1 ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.alpine
+ cmp $root/Dockerfile2.nofrom ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.nofrom
+ run test -s $root/etc/passwd
+ [ "$status" -eq 0 ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$status" -eq 0 ]
+ [ "$output" = "" ]
+}
+
+@test "build-from-multiple-files-two-froms" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.scratch -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.withfrom
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ cmp $root/Dockerfile1 ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.scratch
+ cmp $root/Dockerfile2.withfrom ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.withfrom
+ run test -s $root/etc/passwd
+ [ "$status" -ne 0 ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$status" -eq 0 ]
+ [ "$output" = "" ]
+
+ target=alpine-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.alpine -f ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.withfrom
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ cmp $root/Dockerfile1 ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.alpine
+ cmp $root/Dockerfile2.withfrom ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.withfrom
+ run test -s $root/etc/passwd
+ [ "$status" -eq 0 ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$status" -eq 0 ]
+ [ "$output" = "" ]
+}
+
+@test "build-preserve-subvolumes" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ # This Dockerfile needs us to be able to handle a working RUN instruction.
+ if ! which runc ; then
+ skip
+ fi
+ target=volume-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} ${BUILDAH_TESTSDIR}/build/preserve-volumes
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ test -s $root/vol/subvol/subsubvol/subsubvolfile
+ run test -s $root/vol/subvol/subvolfile
+ [ "$status" -ne 0 ]
+ test -s $root/vol/volfile
+ test -s $root/vol/Dockerfile
+ test -s $root/vol/Dockerfile2
+ run test -s $root/vol/anothervolfile
+ [ "$status" -ne 0 ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-http-Dockerfile" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ starthttpd ${BUILDAH_TESTSDIR}/build/from-scratch
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f http://0.0.0.0:${HTTP_SERVER_PORT}/Dockerfile .
+ stophttpd
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-http-context-with-Dockerfile" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ starthttpd ${BUILDAH_TESTSDIR}/build/http-context
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} http://0.0.0.0:${HTTP_SERVER_PORT}/context.tar
+ stophttpd
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-http-context-dir-with-Dockerfile-pre" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ starthttpd ${BUILDAH_TESTSDIR}/build/http-context-subdir
+ target=scratch-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f context/Dockerfile http://0.0.0.0:${HTTP_SERVER_PORT}/context.tar
+ stophttpd
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-http-context-dir-with-Dockerfile-post" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ starthttpd ${BUILDAH_TESTSDIR}/build/http-context-subdir
+ target=scratch-image
+ kpod build http://0.0.0.0:${HTTP_SERVER_PORT}/context.tar --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f context/Dockerfile
+ stophttpd
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-git-context" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ # We need git and ssh to be around to handle cloning a repository.
+ if ! which git ; then
+ skip
+ fi
+ if ! which ssh ; then
+ skip
+ fi
+ target=giturl-image
+ # Any repo should do, but this one is small and is FROM: scratch.
+ gitrepo=git://github.com/projectatomic/nulecule-library
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} "${gitrepo}"
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-github-context" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=github-image
+ # Any repo should do, but this one is small and is FROM: scratch.
+ gitrepo=github.com/projectatomic/nulecule-library
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} "${gitrepo}"
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ buildah --debug=false images -q
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-additional-tags" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=scratch-image
+ target2=another-scratch-image
+ target3=so-many-scratch-images
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -t ${target2} -t ${target3} ${BUILDAH_TESTSDIR}/build/from-scratch
+ run buildah --debug=false images
+ cid=$(buildah from ${target})
+ kpod rm ${cid}
+ cid=$(buildah from library/${target2})
+ kpod rm ${cid}
+ cid=$(buildah from ${target3}:latest)
+ kpod rm ${cid}
+ kpod rmi -f $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-volume-perms" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ # This Dockerfile needs us to be able to handle a working RUN instruction.
+ if ! which runc ; then
+ skip
+ fi
+ target=volume-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} ${BUILDAH_TESTSDIR}/build/volume-perms
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ run test -s $root/vol/subvol/subvolfile
+ [ "$status" -ne 0 ]
+ run stat -c %f $root/vol/subvol
+ [ "$output" = 41ed ]
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
+
+@test "build-from-glob" {
+ if ! which buildah ; then
+ skip "Buildah not installed"
+ fi
+ target=alpine-image
+ kpod build --signature-policy ${BUILDAH_TESTSDIR}/policy.json -t ${target} -f Dockerfile2.glob ${BUILDAH_TESTSDIR}/build/from-multiple-files
+ cid=$(buildah from ${target})
+ root=$(buildah mount ${cid})
+ cmp $root/Dockerfile1.alpine ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile1.alpine
+ cmp $root/Dockerfile2.withfrom ${BUILDAH_TESTSDIR}/build/from-multiple-files/Dockerfile2.withfrom
+ kpod rm ${cid}
+ kpod rmi $(buildah --debug=false images -q)
+ run buildah --debug=false images -q
+ [ "$output" = "" ]
+}
diff --git a/test/test_podman_build.sh b/test/test_podman_build.sh
new file mode 100644
index 000000000..a595e52c0
--- /dev/null
+++ b/test/test_podman_build.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+#
+# test_podman_build.sh
+#
+# Used to test 'podman build' functionality "by hand"
+# until we're able to install Buildah in the Travis CI
+# test system.
+#
+# Requires podman and Buildah to be installed on the
+# system. This needs to be run from the libpod
+# directory after cloning the libpod repo.
+#
+# To run:
+# /bin/bash -v test_podman_build.sh
+#
+
+HOME=`pwd`
+
+########
+# test "build-from-scratch"
+########
+ TARGET=scratch-image
+ podman build -q=True -t $TARGET $HOME/test/build/from-scratch
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ podman build -q=False --build-arg HOME=/ --build-arg VERSION=0.1 -t $TARGET $HOME/test/build/from-scratch
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ podman build --quiet=True -t $TARGET $HOME/test/build/from-scratch
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ podman rmi -f $(podman images -q)
+ podman images -q
+
+
+########
+# test "build-preserve-subvolumes"
+########
+ TARGET=volume-image
+ podman build -t $TARGET $HOME/test/build/preserve-volumes
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ test -s $ROOT/vol/subvol/subsubvol/subsubvolfile
+ test -s $ROOT/vol/subvol/subvolfile
+ test -s $ROOT/vol/volfile
+ test -s $ROOT/vol/Dockerfile
+ test -s $ROOT/vol/Dockerfile2
+ test -s $ROOT/vol/anothervolfile
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ buildah --debug=false images -q
+
+########
+# test "build-git-context"
+########
+ TARGET=giturl-image
+ # Any repo should do, but this one is small and is FROM: scratch.
+ GITREPO=git://github.com/projectatomic/nulecule-library
+ podman build -t $TARGET "$GITREPO"
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ podman images -q
+
+
+########
+# test "build-github-context"
+########
+ TARGET=github-image
+ # Any repo should do, but this one is small and is FROM: scratch.
+ GITREPO=github.com/projectatomic/nulecule-library
+ podman build -t $TARGET "$GITREPO"
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ buildah --debug=false images -q
+ podman rmi $(buildah --debug=false images -q)
+ podman images -q
+
+
+########
+# test "build-additional-tags"
+########
+ TARGET=scratch-image
+ TARGET2=another-scratch-image
+ TARGET3=so-many-scratch-images
+ podman build -t $TARGET -t $TARGET2 -t $TARGET3 -f $HOME/test/build/from-scratch/Dockerfile
+ buildah --debug=false images
+ CID=$(buildah from $TARGET)
+ buildah rm $CID
+ CID=$(buildah from library/$TARGET2)
+ buildah rm $CID
+ CID=$(buildah from $TARGET3:latest)
+ buildah rm $CID
+ podman rmi -f $(buildah --debug=false images -q)
+ podman images -q
+
+
+########
+# test "build-volume-perms"
+########
+ TARGET=volume-image
+ podman build -t $TARGET $HOME/test/build/volume-perms
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ test -s $ROOT/vol/subvol/subvolfile
+ stat -c %f $ROOT/vol/subvol
+ #Output s/b 41ed
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ podman images -q
+
+
+########
+# test "build-from-glob"
+########
+ TARGET=alpine-image
+ podman build -t $TARGET -file Dockerfile2.glob $HOME/test/build/from-multiple-files
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ cmp $ROOT/Dockerfile1.alpine $HOME/test/build/from-multiple-files/Dockerfile1.alpine
+ cmp $ROOT/Dockerfile2.withfrom $HOME/test/build/from-multiple-files/Dockerfile2.withfrom
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ podman images -q
+
+
+########
+# test "build-from-multiple-files-one-from"
+########
+ TARGET=scratch-image
+ podman build -t $TARGET -file $HOME/test/build/from-multiple-files/Dockerfile1.scratch -file $HOME/test/build/from-multiple-files/Dockerfile2.nofrom
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ cmp $ROOT/Dockerfile1 $HOME/test/build/from-multiple-files/Dockerfile1.scratch
+ cmp $ROOT/Dockerfile2.nofrom $HOME/test/build/from-multiple-files/Dockerfile2.nofrom
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ buildah --debug=false images -q
+
+ TARGET=alpine-image
+ podman build -t $TARGET -file $HOME/test/build/from-multiple-files/Dockerfile1.alpine -file $HOME/test/build/from-multiple-files/Dockerfile2.nofrom
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ buildah --debug=false images -q
+
+
+########
+# test "build-from-multiple-files-two-froms"
+########
+ TARGET=scratch-image
+ podman build -t $TARGET -file $HOME/test/build/from-multiple-files/Dockerfile1.scratch -file $HOME/test/build/from-multiple-files/Dockerfile2.withfrom
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ cmp $ROOT/Dockerfile1 $HOME/test/build/from-multiple-files/Dockerfile1.scratch
+ cmp $ROOT/Dockerfile2.withfrom $HOME/test/build/from-multiple-files/Dockerfile2.withfrom
+ test -s $ROOT/etc/passwd
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ buildah --debug=false images -q
+
+ TARGET=alpine-image
+ podman build -t $TARGET -file $HOME/test/build/from-multiple-files/Dockerfile1.alpine -file $HOME/test/build/from-multiple-files/Dockerfile2.withfrom
+ CID=$(buildah from $TARGET)
+ ROOT=$(buildah mount $CID)
+ cmp $ROOT/Dockerfile1 $HOME/test/build/from-multiple-files/Dockerfile1.alpine
+ cmp $ROOT/Dockerfile2.withfrom $HOME/test/build/from-multiple-files/Dockerfile2.withfrom
+ test -s $ROOT/etc/passwd
+ buildah rm $CID
+ podman rmi $(buildah --debug=false images -q)
+ buildah --debug=false images -q
diff --git a/transfer.md b/transfer.md
index 1a2820cf3..101140905 100644
--- a/transfer.md
+++ b/transfer.md
@@ -39,7 +39,7 @@ There are other equivalents for these tools
| Existing Step | PODMAN (and friends) |
| :--- | :--- |
| `docker attach` | [`podman exec`](./docs/podman-attach.1.md)|
-| `docker build` | [`buildah bud`](https://github.com/projectatomic/buildah/blob/master/docs/buildah-bud.md) |
+| `docker build` | [`podman build`](./docs/podman-build.1.md) |
| `docker commit` | [`podman commit`](./docs/podman-commit.1.md)|
| `docker cp` | [`podman mount`](./docs/podman-cp.1.md) **** |
| `docker create` | [`podman create`](./docs/podman-create.1.md) |