ImageFromDockerfile inspects the contents of a provided Dockerfile and returns the image that will be used to run the container.
(dockerfileContent string, buildArgs map[string]string)
| 427 | // ImageFromDockerfile inspects the contents of a provided Dockerfile |
| 428 | // and returns the image that will be used to run the container. |
| 429 | func ImageFromDockerfile(dockerfileContent string, buildArgs map[string]string) (name.Reference, error) { |
| 430 | lexer := shell.NewLex('\\') |
| 431 | var args []string |
| 432 | var imageRef string |
| 433 | lines := strings.Split(dockerfileContent, "\n") |
| 434 | // Iterate over lines in reverse |
| 435 | for i := len(lines) - 1; i >= 0; i-- { |
| 436 | line := lines[i] |
| 437 | if arg, ok := strings.CutPrefix(line, "ARG "); ok { |
| 438 | arg = strings.TrimSpace(arg) |
| 439 | if key, val, ok := strings.Cut(arg, "="); ok { |
| 440 | key, _, err := lexer.ProcessWord(key, shell.EnvsFromSlice(args)) |
| 441 | if err != nil { |
| 442 | return nil, fmt.Errorf("processing %q: %w", line, err) |
| 443 | } |
| 444 | val, _, err := lexer.ProcessWord(val, shell.EnvsFromSlice(args)) |
| 445 | if err != nil { |
| 446 | return nil, fmt.Errorf("processing %q: %w", line, err) |
| 447 | } |
| 448 | // Allow buildArgs to override Dockerfile ARG defaults. |
| 449 | if override, has := buildArgs[key]; has { |
| 450 | val = override |
| 451 | } |
| 452 | args = append(args, key+"="+val) |
| 453 | } else { |
| 454 | // ARG without a default — look up in buildArgs. |
| 455 | if val, has := buildArgs[arg]; has { |
| 456 | args = append(args, arg+"="+val) |
| 457 | } |
| 458 | } |
| 459 | continue |
| 460 | } |
| 461 | if imageRef == "" { |
| 462 | if fromArgs, ok := strings.CutPrefix(line, "FROM "); ok { |
| 463 | imageRef = fromArgs |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | if imageRef == "" { |
| 468 | return nil, fmt.Errorf("no FROM directive found") |
| 469 | } |
| 470 | imageRef, _, err := lexer.ProcessWord(imageRef, shell.EnvsFromSlice(args)) |
| 471 | if err != nil { |
| 472 | return nil, fmt.Errorf("processing %q: %w", imageRef, err) |
| 473 | } |
| 474 | image, err := name.ParseReference(strings.TrimSpace(imageRef)) |
| 475 | if err != nil { |
| 476 | return nil, fmt.Errorf("parse image ref %q: %w", imageRef, err) |
| 477 | } |
| 478 | return image, nil |
| 479 | } |
| 480 | |
| 481 | // UserFromImage inspects the remote reference and returns the user |
| 482 | // that will be used to run the container. |
no outgoing calls