Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -148,7 +148,7 @@ func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error |
| 148 | 148 |
return d.builder.imageSources.Get(imageRefOrID, localOnly) |
| 149 | 149 |
} |
| 150 | 150 |
|
| 151 |
-// FROM imagename[:tag | @digest] [AS build-stage-name] |
|
| 151 |
+// FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name] |
|
| 152 | 152 |
// |
| 153 | 153 |
func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
| 154 | 154 |
d.builder.imageProber.Reset() |
| ... | ... |
@@ -357,10 +357,11 @@ type ShellCommand struct {
|
| 357 | 357 |
|
| 358 | 358 |
// Stage represents a single stage in a multi-stage build |
| 359 | 359 |
type Stage struct {
|
| 360 |
- Name string |
|
| 361 |
- Commands []Command |
|
| 362 |
- BaseName string |
|
| 363 |
- SourceCode string |
|
| 360 |
+ Name string |
|
| 361 |
+ Commands []Command |
|
| 362 |
+ BaseName string |
|
| 363 |
+ SourceCode string |
|
| 364 |
+ OperatingSystem string |
|
| 364 | 365 |
} |
| 365 | 366 |
|
| 366 | 367 |
// AddCommand to the stage |
| ... | ... |
@@ -3,6 +3,7 @@ package instructions // import "github.com/docker/docker/builder/dockerfile/inst |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"regexp" |
| 6 |
+ "runtime" |
|
| 6 | 7 |
"sort" |
| 7 | 8 |
"strconv" |
| 8 | 9 |
"strings" |
| ... | ... |
@@ -12,6 +13,7 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/api/types/strslice" |
| 13 | 13 |
"github.com/docker/docker/builder/dockerfile/command" |
| 14 | 14 |
"github.com/docker/docker/builder/dockerfile/parser" |
| 15 |
+ "github.com/docker/docker/pkg/system" |
|
| 15 | 16 |
"github.com/pkg/errors" |
| 16 | 17 |
) |
| 17 | 18 |
|
| ... | ... |
@@ -271,16 +273,31 @@ func parseFrom(req parseRequest) (*Stage, error) {
|
| 271 | 271 |
return nil, err |
| 272 | 272 |
} |
| 273 | 273 |
|
| 274 |
+ flPlatform := req.flags.AddString("platform", "")
|
|
| 274 | 275 |
if err := req.flags.Parse(); err != nil {
|
| 275 | 276 |
return nil, err |
| 276 | 277 |
} |
| 278 |
+ specPlatform := system.ParsePlatform(flPlatform.Value) |
|
| 279 |
+ if specPlatform.OS == "" {
|
|
| 280 |
+ specPlatform.OS = runtime.GOOS |
|
| 281 |
+ } |
|
| 282 |
+ if err := system.ValidatePlatform(specPlatform); err != nil {
|
|
| 283 |
+ return nil, fmt.Errorf("invalid platform %q on FROM", flPlatform.Value)
|
|
| 284 |
+ } |
|
| 285 |
+ if !system.IsOSSupported(specPlatform.OS) {
|
|
| 286 |
+ return nil, fmt.Errorf("unsupported platform %q on FROM", flPlatform.Value)
|
|
| 287 |
+ } |
|
| 288 |
+ if err != nil {
|
|
| 289 |
+ return nil, err |
|
| 290 |
+ } |
|
| 277 | 291 |
code := strings.TrimSpace(req.original) |
| 278 |
- |
|
| 292 |
+ fmt.Println("JJH", specPlatform.OS)
|
|
| 279 | 293 |
return &Stage{
|
| 280 |
- BaseName: req.args[0], |
|
| 281 |
- Name: stageName, |
|
| 282 |
- SourceCode: code, |
|
| 283 |
- Commands: []Command{},
|
|
| 294 |
+ BaseName: req.args[0], |
|
| 295 |
+ Name: stageName, |
|
| 296 |
+ SourceCode: code, |
|
| 297 |
+ Commands: []Command{},
|
|
| 298 |
+ OperatingSystem: specPlatform.OS, |
|
| 284 | 299 |
}, nil |
| 285 | 300 |
|
| 286 | 301 |
} |
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
package instructions // import "github.com/docker/docker/builder/dockerfile/instructions" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "fmt" |
|
| 5 |
+ "runtime" |
|
| 4 | 6 |
"strings" |
| 5 | 7 |
"testing" |
| 6 | 8 |
|
| ... | ... |
@@ -184,6 +186,16 @@ func TestErrorCases(t *testing.T) {
|
| 184 | 184 |
dockerfile: `foo bar`, |
| 185 | 185 |
expectedError: "unknown instruction: FOO", |
| 186 | 186 |
}, |
| 187 |
+ {
|
|
| 188 |
+ name: "Invalid platform", |
|
| 189 |
+ dockerfile: `FROM --platform=invalid busybox`, |
|
| 190 |
+ expectedError: `invalid platform "invalid"`, |
|
| 191 |
+ }, |
|
| 192 |
+ {
|
|
| 193 |
+ name: "Only OS", |
|
| 194 |
+ dockerfile: fmt.Sprintf(`FROM --platform=%s/%s busybox`, runtime.GOOS, runtime.GOARCH), |
|
| 195 |
+ expectedError: `invalid platform`, |
|
| 196 |
+ }, |
|
| 187 | 197 |
} |
| 188 | 198 |
for _, c := range cases {
|
| 189 | 199 |
r := strings.NewReader(c.dockerfile) |
| ... | ... |
@@ -196,5 +208,4 @@ func TestErrorCases(t *testing.T) {
|
| 196 | 196 |
_, err = ParseInstruction(n) |
| 197 | 197 |
testutil.ErrorContains(t, err, c.expectedError) |
| 198 | 198 |
} |
| 199 |
- |
|
| 200 | 199 |
} |