Skip to content

Commit

Permalink
buildkit: add from field to bind and cache mounts so images can be us…
Browse files Browse the repository at this point in the history
…ed as source

Following commit adds buildkit like support for `from` field to `--mount=type=bind`
and `--mount=type=cache` so images and stage can be used as mount source.

Usage looks like
```dockerfile
RUN --mount=type=bind,source=.,from=<your-image>,target=/path ls /path
```
and
```dockerfile
RUN --mount=type=cache,from=<your-image>,target=/path ls /path
```

Signed-off-by: Aditya Rajan <[email protected]>
  • Loading branch information
flouthoc committed Jan 7, 2022
1 parent 7629cbe commit b934085
Show file tree
Hide file tree
Showing 25 changed files with 823 additions and 299 deletions.
9 changes: 8 additions & 1 deletion cmd/buildah/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,20 @@ func runCmd(c *cobra.Command, args []string, iopts runInputOptions) error {
}
}

mounts, err := parse.GetVolumes(iopts.volumes, iopts.mounts, iopts.contextDir)
systemContext, err := parse.SystemContextFromOptions(c)
if err != nil {
return errors.Wrapf(err, "error building system context")
}
mounts, mountedImages, err := parse.GetVolumes(systemContext, store, iopts.volumes, iopts.mounts, iopts.contextDir)
if err != nil {
return err
}
options.Mounts = mounts
// Run() will automatically clean them up.
options.ExternalImageMounts = mountedImages

runerr := builder.Run(args, options)

if runerr != nil {
logrus.Debugf("error running %v in container %q: %v", args, builder.Container, runerr)
}
Expand Down
6 changes: 5 additions & 1 deletion docs/Containerfile.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Current supported mount TYPES are bind, cache, secret and tmpfs.

Common Options:

· src, source: mount source spec for bind and volume. Mandatory for bind.
· src, source: mount source spec for bind and volume. Mandatory for bind. If `from` is specified, `src` is the subpath in the `from` field.

· dst, destination, target: mount destination spec.

Expand All @@ -126,6 +126,8 @@ Current supported mount TYPES are bind, cache, secret and tmpfs.

. bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.

· from: stage or image name for the root of the source. Defaults to the build context.

Options specific to tmpfs:

· tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
Expand All @@ -146,6 +148,8 @@ Current supported mount TYPES are bind, cache, secret and tmpfs.

· gid: gid for cache directory.

· from: stage name for the root of the source. Defaults to host cache directory.


**RUN Secrets**

Expand Down
6 changes: 5 additions & 1 deletion docs/buildah-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Current supported mount TYPES are bind, cache, secret and tmpfs. <sup>[[1]](#Foo

Common Options:

· src, source: mount source spec for bind and volume. Mandatory for bind.
· src, source: mount source spec for bind and volume. Mandatory for bind. If `from` is specified, `src` is the subpath in the `from` field.

· dst, destination, target: mount destination spec.

Expand All @@ -134,6 +134,8 @@ Current supported mount TYPES are bind, cache, secret and tmpfs. <sup>[[1]](#Foo

. bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.

· from: stage or image name for the root of the source. Defaults to the build context.

Options specific to tmpfs:

· tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
Expand All @@ -158,6 +160,8 @@ Current supported mount TYPES are bind, cache, secret and tmpfs. <sup>[[1]](#Foo

· gid: gid for cache directory.

· from: stage name for the root of the source. Defaults to host cache directory.

**--network**, **--net**=*mode*

Sets the configuration for the network namespace for the container.
Expand Down
48 changes: 48 additions & 0 deletions imagebuildah/stage_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,56 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
return nil
}

// Returns a map of StageName:StageMountpoint for RunOpts if any --mount with from is provided
// check if RUN contains `--mount` with `from`. If yes pre-mount stages from executor for Run.
// stages mounted here will we used be Run().
func (s *StageExecutor) runStageMountPoints(mountList []string) (map[string]string, error) {
stageMountPoints := make(map[string]string)
for _, flag := range mountList {
if strings.Contains(flag, "from") {
arr := strings.SplitN(flag, ",", 2)
if len(arr) < 2 {
return nil, errors.Errorf("Invalid --mount command: %s", flag)
}
tokens := strings.Split(arr[1], ",")
for _, val := range tokens {
kv := strings.SplitN(val, "=", 2)
switch kv[0] {
case "from":
if kv[1] == "" {
return nil, errors.Errorf("unable to resolve argument for `from=`: from points to an empty value")
}
from, fromErr := imagebuilder.ProcessWord(kv[1], s.stage.Builder.Arguments())
if fromErr != nil {
return nil, errors.Wrapf(fromErr, "unable to resolve argument %q", kv[1])
}
// If the source's name corresponds to the
// result of an earlier stage, wait for that
// stage to finish being built.
if isStage, err := s.executor.waitForStage(s.ctx, from, s.stages[:s.index]); isStage && err != nil {
return nil, err
}
if otherStage, ok := s.executor.stages[from]; ok && otherStage.index < s.index {
stageMountPoints[from] = otherStage.mountPoint
break
}
default:
continue
}
}
}
}
return stageMountPoints, nil
}

// Run executes a RUN instruction using the stage's current working container
// as a root directory.
func (s *StageExecutor) Run(run imagebuilder.Run, config docker.Config) error {
logrus.Debugf("RUN %#v, %#v", run, config)
stageMountPoints, err := s.runStageMountPoints(run.Mounts)
if err != nil {
return err
}
if s.builder == nil {
return errors.Errorf("no build container available")
}
Expand Down Expand Up @@ -451,6 +497,8 @@ func (s *StageExecutor) Run(run imagebuilder.Run, config docker.Config) error {
Secrets: s.executor.secrets,
SSHSources: s.executor.sshsources,
RunMounts: run.Mounts,
StageMountPoints: stageMountPoints,
SystemContext: s.executor.systemContext,
}
if config.NetworkDisabled {
options.ConfigureNetwork = buildah.NetworkDisabled
Expand Down
Loading

0 comments on commit b934085

Please sign in to comment.