|
@@ -176,69 +176,80 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
|
|
|
return b.runContextCommand(args, false, false, "COPY", im)
|
|
|
}
|
|
|
|
|
|
-// FROM imagename
|
|
|
-//
|
|
|
-// This sets the image the dockerfile will build on top of.
|
|
|
+// FROM imagename[:tag | @digest] [AS build-stage-name]
|
|
|
//
|
|
|
+// from sets the base image
|
|
|
func from(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
|
- ctxName := ""
|
|
|
- if len(args) == 3 && strings.EqualFold(args[1], "as") {
|
|
|
- ctxName = strings.ToLower(args[2])
|
|
|
- if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", ctxName); !ok {
|
|
|
- return errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", ctxName)
|
|
|
- }
|
|
|
- } else if len(args) != 1 {
|
|
|
- return errors.New("FROM requires either one or three arguments")
|
|
|
+ ctxName, err := parseBuildStageName(args)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
if err := b.flags.Parse(); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
-
|
|
|
- substituionArgs := []string{}
|
|
|
- for key, value := range b.buildArgs.GetAllMeta() {
|
|
|
- substituionArgs = append(substituionArgs, key+"="+value)
|
|
|
+ b.resetImageCache()
|
|
|
+ if _, err := b.imageContexts.add(ctxName); err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
- name, err := ProcessWord(args[0], substituionArgs, b.escapeToken)
|
|
|
+ image, err := b.getFromImage(args[0])
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
+ if image != nil {
|
|
|
+ b.imageContexts.update(image.ImageID(), image.RunConfig())
|
|
|
+ }
|
|
|
+ b.from = image
|
|
|
|
|
|
- var image builder.Image
|
|
|
+ b.buildArgs.ResetAllowed()
|
|
|
+ return b.processImageFrom(image)
|
|
|
+}
|
|
|
|
|
|
- b.resetImageCache()
|
|
|
- if _, err := b.imageContexts.new(ctxName, true); err != nil {
|
|
|
- return err
|
|
|
+func parseBuildStageName(args []string) (string, error) {
|
|
|
+ stageName := ""
|
|
|
+ switch {
|
|
|
+ case len(args) == 3 && strings.EqualFold(args[1], "as"):
|
|
|
+ stageName = strings.ToLower(args[2])
|
|
|
+ if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", stageName); !ok {
|
|
|
+ return "", errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", stageName)
|
|
|
+ }
|
|
|
+ case len(args) != 1:
|
|
|
+ return "", errors.New("FROM requires either one or three arguments")
|
|
|
+ }
|
|
|
+
|
|
|
+ return stageName, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (b *Builder) getFromImage(name string) (builder.Image, error) {
|
|
|
+ substitutionArgs := []string{}
|
|
|
+ for key, value := range b.buildArgs.GetAllMeta() {
|
|
|
+ substitutionArgs = append(substitutionArgs, key+"="+value)
|
|
|
+ }
|
|
|
+
|
|
|
+ name, err := ProcessWord(name, substitutionArgs, b.escapeToken)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
}
|
|
|
|
|
|
if im, ok := b.imageContexts.byName[name]; ok {
|
|
|
if len(im.ImageID()) > 0 {
|
|
|
- image = im
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Windows cannot support a container with no base image.
|
|
|
- if name == api.NoBaseImageSpecifier {
|
|
|
- if runtime.GOOS == "windows" {
|
|
|
- return errors.New("Windows does not support FROM scratch")
|
|
|
- }
|
|
|
- b.image = ""
|
|
|
- b.noBaseImage = true
|
|
|
- } else {
|
|
|
- var err error
|
|
|
- image, err = pullOrGetImage(b, name)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
+ return im, nil
|
|
|
}
|
|
|
+ // FROM scratch does not have an ImageID
|
|
|
+ return nil, nil
|
|
|
}
|
|
|
- if image != nil {
|
|
|
- b.imageContexts.update(image.ImageID(), image.RunConfig())
|
|
|
- }
|
|
|
- b.from = image
|
|
|
|
|
|
- b.buildArgs.ResetAllowed()
|
|
|
- return b.processImageFrom(image)
|
|
|
+ // Windows cannot support a container with no base image.
|
|
|
+ if name == api.NoBaseImageSpecifier {
|
|
|
+ if runtime.GOOS == "windows" {
|
|
|
+ return nil, errors.New("Windows does not support FROM scratch")
|
|
|
+ }
|
|
|
+ b.image = ""
|
|
|
+ b.noBaseImage = true
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+ return pullOrGetImage(b, name)
|
|
|
}
|
|
|
|
|
|
// ONBUILD RUN echo yo
|
|
@@ -835,11 +846,7 @@ func mountByRef(b *Builder, name string) (*imageMount, error) {
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- im, err := b.imageContexts.new("", false)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- im.id = image.ImageID()
|
|
|
+ im := b.imageContexts.newImageMount(image.ImageID())
|
|
|
return im, nil
|
|
|
}
|
|
|
|