|
@@ -26,6 +26,7 @@ import (
|
|
|
|
|
|
"github.com/docker/docker/builder/dockerfile/command"
|
|
|
"github.com/docker/docker/builder/dockerfile/parser"
|
|
|
+ runconfigopts "github.com/docker/docker/runconfig/opts"
|
|
|
)
|
|
|
|
|
|
// Environment variable interpolation will happen on these statements only.
|
|
@@ -140,27 +141,9 @@ func (b *Builder) dispatch(stepN int, stepTotal int, ast *parser.Node) error {
|
|
|
msgList := make([]string, n)
|
|
|
|
|
|
var i int
|
|
|
- // Append the build-time args to config-environment.
|
|
|
- // This allows builder config to override the variables, making the behavior similar to
|
|
|
- // a shell script i.e. `ENV foo bar` overrides value of `foo` passed in build
|
|
|
- // context. But `ENV foo $foo` will use the value from build context if one
|
|
|
- // isn't already been defined by a previous ENV primitive.
|
|
|
- // Note, we get this behavior because we know that ProcessWord() will
|
|
|
- // stop on the first occurrence of a variable name and not notice
|
|
|
- // a subsequent one. So, putting the buildArgs list after the Config.Env
|
|
|
- // list, in 'envs', is safe.
|
|
|
- envs := b.runConfig.Env
|
|
|
- for key, val := range b.options.BuildArgs {
|
|
|
- if !b.isBuildArgAllowed(key) {
|
|
|
- // skip build-args that are not in allowed list, meaning they have
|
|
|
- // not been defined by an "ARG" Dockerfile command yet.
|
|
|
- // This is an error condition but only if there is no "ARG" in the entire
|
|
|
- // Dockerfile, so we'll generate any necessary errors after we parsed
|
|
|
- // the entire file (see 'leftoverArgs' processing in evaluator.go )
|
|
|
- continue
|
|
|
- }
|
|
|
- envs = append(envs, fmt.Sprintf("%s=%s", key, *val))
|
|
|
- }
|
|
|
+ // Append build args to runConfig environment variables
|
|
|
+ envs := append(b.runConfig.Env, b.buildArgsWithoutConfigEnv()...)
|
|
|
+
|
|
|
for ast.Next != nil {
|
|
|
ast = ast.Next
|
|
|
var str string
|
|
@@ -203,6 +186,28 @@ func (b *Builder) dispatch(stepN int, stepTotal int, ast *parser.Node) error {
|
|
|
return fmt.Errorf("Unknown instruction: %s", upperCasedCmd)
|
|
|
}
|
|
|
|
|
|
+// buildArgsWithoutConfigEnv returns a list of key=value pairs for all the build
|
|
|
+// args that are not overriden by runConfig environment variables.
|
|
|
+func (b *Builder) buildArgsWithoutConfigEnv() []string {
|
|
|
+ envs := []string{}
|
|
|
+ configEnv := runconfigopts.ConvertKVStringsToMap(b.runConfig.Env)
|
|
|
+
|
|
|
+ for key, val := range b.options.BuildArgs {
|
|
|
+ if !b.isBuildArgAllowed(key) {
|
|
|
+ // skip build-args that are not in allowed list, meaning they have
|
|
|
+ // not been defined by an "ARG" Dockerfile command yet.
|
|
|
+ // This is an error condition but only if there is no "ARG" in the entire
|
|
|
+ // Dockerfile, so we'll generate any necessary errors after we parsed
|
|
|
+ // the entire file (see 'leftoverArgs' processing in evaluator.go )
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if _, ok := configEnv[key]; !ok && val != nil {
|
|
|
+ envs = append(envs, fmt.Sprintf("%s=%s", key, *val))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return envs
|
|
|
+}
|
|
|
+
|
|
|
// checkDispatch does a simple check for syntax errors of the Dockerfile.
|
|
|
// Because some of the instructions can only be validated through runtime,
|
|
|
// arg, env, etc., this syntax check will not be complete and could not replace
|