Instead of building the actual image, `build_config` will serialize a subset of
dockerfile ast into *runconfig.Config
Docker-DCO-1.1-Signed-off-by: Daniel, Dao Quang Minh <dqminh89@gmail.com> (github: dqminh)
Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
... | ... |
@@ -96,6 +96,11 @@ type Builder struct { |
96 | 96 |
ForceRemove bool |
97 | 97 |
Pull bool |
98 | 98 |
|
99 |
+ // set this to true if we want the builder to not commit between steps. |
|
100 |
+ // This is useful when we only want to use the evaluator table to generate |
|
101 |
+ // the final configs of the Dockerfile but dont want the layers |
|
102 |
+ disableCommit bool |
|
103 |
+ |
|
99 | 104 |
AuthConfig *registry.AuthConfig |
100 | 105 |
AuthConfigFile *registry.ConfigFile |
101 | 106 |
|
... | ... |
@@ -60,6 +60,9 @@ func (b *Builder) readContext(context io.Reader) error { |
60 | 60 |
} |
61 | 61 |
|
62 | 62 |
func (b *Builder) commit(id string, autoCmd []string, comment string) error { |
63 |
+ if b.disableCommit { |
|
64 |
+ return nil |
|
65 |
+ } |
|
63 | 66 |
if b.image == "" && !b.noBaseImage { |
64 | 67 |
return fmt.Errorf("Please provide a source image with `from` prior to commit") |
65 | 68 |
} |
... | ... |
@@ -1,12 +1,16 @@ |
1 | 1 |
package builder |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "bytes" |
|
5 |
+ "encoding/json" |
|
6 |
+ "fmt" |
|
4 | 7 |
"io" |
5 | 8 |
"io/ioutil" |
6 | 9 |
"os" |
7 | 10 |
"os/exec" |
8 | 11 |
|
9 | 12 |
"github.com/docker/docker/api" |
13 |
+ "github.com/docker/docker/builder/parser" |
|
10 | 14 |
"github.com/docker/docker/daemon" |
11 | 15 |
"github.com/docker/docker/engine" |
12 | 16 |
"github.com/docker/docker/graph" |
... | ... |
@@ -14,6 +18,7 @@ import ( |
14 | 14 |
"github.com/docker/docker/pkg/parsers" |
15 | 15 |
"github.com/docker/docker/pkg/urlutil" |
16 | 16 |
"github.com/docker/docker/registry" |
17 |
+ "github.com/docker/docker/runconfig" |
|
17 | 18 |
"github.com/docker/docker/utils" |
18 | 19 |
) |
19 | 20 |
|
... | ... |
@@ -24,6 +29,7 @@ type BuilderJob struct { |
24 | 24 |
|
25 | 25 |
func (b *BuilderJob) Install() { |
26 | 26 |
b.Engine.Register("build", b.CmdBuild) |
27 |
+ b.Engine.Register("build_config", b.CmdBuildConfig) |
|
27 | 28 |
} |
28 | 29 |
|
29 | 30 |
func (b *BuilderJob) CmdBuild(job *engine.Job) engine.Status { |
... | ... |
@@ -138,3 +144,58 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) engine.Status { |
138 | 138 |
} |
139 | 139 |
return engine.StatusOK |
140 | 140 |
} |
141 |
+ |
|
142 |
+func (b *BuilderJob) CmdBuildConfig(job *engine.Job) engine.Status { |
|
143 |
+ if len(job.Args) != 0 { |
|
144 |
+ return job.Errorf("Usage: %s\n", job.Name) |
|
145 |
+ } |
|
146 |
+ var ( |
|
147 |
+ validCmd = map[string]struct{}{ |
|
148 |
+ "entrypoint": {}, |
|
149 |
+ "cmd": {}, |
|
150 |
+ "user": {}, |
|
151 |
+ "workdir": {}, |
|
152 |
+ "env": {}, |
|
153 |
+ "volume": {}, |
|
154 |
+ "expose": {}, |
|
155 |
+ "onbuild": {}, |
|
156 |
+ } |
|
157 |
+ |
|
158 |
+ changes = job.Getenv("changes") |
|
159 |
+ newConfig runconfig.Config |
|
160 |
+ ) |
|
161 |
+ |
|
162 |
+ if err := job.GetenvJson("config", &newConfig); err != nil { |
|
163 |
+ return job.Error(err) |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ ast, err := parser.Parse(bytes.NewBufferString(changes)) |
|
167 |
+ if err != nil { |
|
168 |
+ return job.Error(err) |
|
169 |
+ } |
|
170 |
+ |
|
171 |
+ builder := &Builder{ |
|
172 |
+ Daemon: b.Daemon, |
|
173 |
+ Engine: b.Engine, |
|
174 |
+ Config: &newConfig, |
|
175 |
+ OutStream: ioutil.Discard, |
|
176 |
+ ErrStream: ioutil.Discard, |
|
177 |
+ disableCommit: true, |
|
178 |
+ } |
|
179 |
+ |
|
180 |
+ for i, n := range ast.Children { |
|
181 |
+ cmd := n.Value |
|
182 |
+ if _, ok := validCmd[cmd]; ok { |
|
183 |
+ if err := builder.dispatch(i, n); err != nil { |
|
184 |
+ return job.Error(err) |
|
185 |
+ } |
|
186 |
+ } else { |
|
187 |
+ fmt.Fprintf(builder.ErrStream, "# Skipping serialization of instruction %s\n", strings.ToUpper(cmd)) |
|
188 |
+ } |
|
189 |
+ } |
|
190 |
+ |
|
191 |
+ if err := json.NewEncoder(job.Stdout).Encode(builder.Config); err != nil { |
|
192 |
+ return job.Error(err) |
|
193 |
+ } |
|
194 |
+ return engine.StatusOK |
|
195 |
+} |