Browse code

bump remote api to 1.12 & add --force-rm to build

This adds a `--force-rm` flag to docker build which makes the Docker
daemon clean up all containers, even when the build has failed.

This new flag requires that we bump the remote API, so we also bump the
remote API version.

Docker-DCO-1.1-Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com> (github: unclejack)

unclejack authored on 2014/05/16 20:47:33
Showing 9 changed files
... ...
@@ -110,6 +110,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
110 110
 	suppressOutput := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the verbose output generated by the containers")
111 111
 	noCache := cmd.Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
112 112
 	rm := cmd.Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
113
+	forceRm := cmd.Bool([]string{"-force-rm"}, false, "Always remove intermediate containers, even after unsuccessful builds")
113 114
 	if err := cmd.Parse(args); err != nil {
114 115
 		return nil
115 116
 	}
... ...
@@ -199,6 +200,10 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
199 199
 		v.Set("rm", "1")
200 200
 	}
201 201
 
202
+	if *forceRm {
203
+		v.Set("forcerm", "1")
204
+	}
205
+
202 206
 	cli.LoadConfigFile()
203 207
 
204 208
 	headers := http.Header(make(map[string][]string))
... ...
@@ -11,7 +11,7 @@ import (
11 11
 )
12 12
 
13 13
 const (
14
-	APIVERSION        version.Version = "1.11"
14
+	APIVERSION        version.Version = "1.12"
15 15
 	DEFAULTHTTPHOST                   = "127.0.0.1"
16 16
 	DEFAULTUNIXSOCKET                 = "/var/run/docker.sock"
17 17
 )
... ...
@@ -903,12 +903,17 @@ func postBuild(eng *engine.Engine, version version.Version, w http.ResponseWrite
903 903
 	} else {
904 904
 		job.Stdout.Add(utils.NewWriteFlusher(w))
905 905
 	}
906
+	if r.FormValue("forcerm") == "1" && version.GreaterThanOrEqualTo("1.12") {
907
+		job.Setenv("rm", "1")
908
+	} else {
909
+		job.Setenv("rm", r.FormValue("rm"))
910
+	}
906 911
 	job.Stdin.Add(r.Body)
907 912
 	job.Setenv("remote", r.FormValue("remote"))
908 913
 	job.Setenv("t", r.FormValue("t"))
909 914
 	job.Setenv("q", r.FormValue("q"))
910 915
 	job.Setenv("nocache", r.FormValue("nocache"))
911
-	job.Setenv("rm", r.FormValue("rm"))
916
+	job.Setenv("forcerm", r.FormValue("forcerm"))
912 917
 	job.SetenvJson("authConfig", authConfig)
913 918
 	job.SetenvJson("configFile", configFile)
914 919
 
... ...
@@ -20,13 +20,23 @@ page_keywords: API, Docker, rcli, REST, documentation
20 20
 
21 21
 
22 22
 
23
-The current version of the API is v1.11
23
+The current version of the API is v1.12
24 24
 
25 25
 Calling /images/<name>/insert is the same as calling
26
-/v1.11/images/<name>/insert
26
+/v1.12/images/<name>/insert
27 27
 
28 28
 You can still call an old version of the api using
29
-/v1.11/images/<name>/insert
29
+/v1.12/images/<name>/insert
30
+
31
+## v1.12
32
+
33
+### Full Documentation
34
+
35
+[*Docker Remote API v1.12*](/reference/api/docker_remote_api_v1.12/)
36
+
37
+### What's new
38
+
39
+docker build now has support for the `forcerm` parameter to always remove containers
30 40
 
31 41
 ## v1.11
32 42
 
33 43
new file mode 100644
... ...
@@ -0,0 +1,1363 @@
0
+page_title: Remote API v1.12
1
+page_description: API Documentation for Docker
2
+page_keywords: API, Docker, rcli, REST, documentation
3
+
4
+# Docker Remote API v1.12
5
+
6
+## 1. Brief introduction
7
+
8
+ - The Remote API has replaced rcli
9
+ - The daemon listens on `unix:///var/run/docker.sock` but you can
10
+   [*Bind Docker to another host/port or a Unix socket*](
11
+   /use/basics/#bind-docker).
12
+ - The API tends to be REST, but for some complex commands, like `attach`
13
+   or `pull`, the HTTP connection is hijacked to transport `stdout, stdin`
14
+   and `stderr`
15
+
16
+# 2. Endpoints
17
+
18
+## 2.1 Containers
19
+
20
+### List containers
21
+
22
+`GET /containers/json`
23
+
24
+List containers
25
+
26
+    **Example request**:
27
+
28
+        GET /containers/json?all=1&before=8dfafdbc3a40&size=1 HTTP/1.1
29
+
30
+    **Example response**:
31
+
32
+        HTTP/1.1 200 OK
33
+        Content-Type: application/json
34
+
35
+        [
36
+             {
37
+                     "Id": "8dfafdbc3a40",
38
+                     "Image": "base:latest",
39
+                     "Command": "echo 1",
40
+                     "Created": 1367854155,
41
+                     "Status": "Exit 0",
42
+                     "Ports":[{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
43
+                     "SizeRw":12288,
44
+                     "SizeRootFs":0
45
+             },
46
+             {
47
+                     "Id": "9cd87474be90",
48
+                     "Image": "base:latest",
49
+                     "Command": "echo 222222",
50
+                     "Created": 1367854155,
51
+                     "Status": "Exit 0",
52
+                     "Ports":[],
53
+                     "SizeRw":12288,
54
+                     "SizeRootFs":0
55
+             },
56
+             {
57
+                     "Id": "3176a2479c92",
58
+                     "Image": "base:latest",
59
+                     "Command": "echo 3333333333333333",
60
+                     "Created": 1367854154,
61
+                     "Status": "Exit 0",
62
+                     "Ports":[],
63
+                     "SizeRw":12288,
64
+                     "SizeRootFs":0
65
+             },
66
+             {
67
+                     "Id": "4cb07b47f9fb",
68
+                     "Image": "base:latest",
69
+                     "Command": "echo 444444444444444444444444444444444",
70
+                     "Created": 1367854152,
71
+                     "Status": "Exit 0",
72
+                     "Ports":[],
73
+                     "SizeRw":12288,
74
+                     "SizeRootFs":0
75
+             }
76
+        ]
77
+
78
+    Query Parameters:
79
+
80
+     
81
+
82
+    -   **all** – 1/True/true or 0/False/false, Show all containers.
83
+        Only running containers are shown by default
84
+    -   **limit** – Show `limit` last created
85
+        containers, include non-running ones.
86
+    -   **since** – Show only containers created since Id, include
87
+        non-running ones.
88
+    -   **before** – Show only containers created before Id, include
89
+        non-running ones.
90
+    -   **size** – 1/True/true or 0/False/false, Show the containers
91
+        sizes
92
+
93
+    Status Codes:
94
+
95
+    -   **200** – no error
96
+    -   **400** – bad parameter
97
+    -   **500** – server error
98
+
99
+### Create a container
100
+
101
+`POST /containers/create`
102
+
103
+Create a container
104
+
105
+    **Example request**:
106
+
107
+        POST /containers/create HTTP/1.1
108
+        Content-Type: application/json
109
+
110
+        {
111
+             "Hostname":"",
112
+             "User":"",
113
+             "Memory":0,
114
+             "MemorySwap":0,
115
+             "AttachStdin":false,
116
+             "AttachStdout":true,
117
+             "AttachStderr":true,
118
+             "PortSpecs":null,
119
+             "Tty":false,
120
+             "OpenStdin":false,
121
+             "StdinOnce":false,
122
+             "Env":null,
123
+             "Cmd":[
124
+                     "date"
125
+             ],
126
+             "Dns":null,
127
+             "Image":"base",
128
+             "Volumes":{
129
+                     "/tmp": {}
130
+             },
131
+             "VolumesFrom":"",
132
+             "WorkingDir":"",
133
+             "DisableNetwork": false,
134
+             "ExposedPorts":{
135
+                     "22/tcp": {}
136
+             }
137
+        }
138
+
139
+    **Example response**:
140
+
141
+        HTTP/1.1 201 OK
142
+        Content-Type: application/json
143
+
144
+        {
145
+             "Id":"e90e34656806"
146
+             "Warnings":[]
147
+        }
148
+
149
+    Json Parameters:
150
+
151
+     
152
+
153
+    -   **config** – the container's configuration
154
+
155
+    Query Parameters:
156
+
157
+     
158
+
159
+    -   **name** – Assign the specified name to the container. Must
160
+        match `/?[a-zA-Z0-9_-]+`.
161
+
162
+    Status Codes:
163
+
164
+    -   **201** – no error
165
+    -   **404** – no such container
166
+    -   **406** – impossible to attach (container not running)
167
+    -   **500** – server error
168
+
169
+### Inspect a container
170
+
171
+`GET /containers/(id)/json`
172
+
173
+Return low-level information on the container `id`
174
+
175
+
176
+    **Example request**:
177
+
178
+        GET /containers/4fa6e0f0c678/json HTTP/1.1
179
+
180
+    **Example response**:
181
+
182
+        HTTP/1.1 200 OK
183
+        Content-Type: application/json
184
+
185
+        {
186
+                     "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
187
+                     "Created": "2013-05-07T14:51:42.041847+02:00",
188
+                     "Path": "date",
189
+                     "Args": [],
190
+                     "Config": {
191
+                             "Hostname": "4fa6e0f0c678",
192
+                             "User": "",
193
+                             "Memory": 0,
194
+                             "MemorySwap": 0,
195
+                             "AttachStdin": false,
196
+                             "AttachStdout": true,
197
+                             "AttachStderr": true,
198
+                             "PortSpecs": null,
199
+                             "Tty": false,
200
+                             "OpenStdin": false,
201
+                             "StdinOnce": false,
202
+                             "Env": null,
203
+                             "Cmd": [
204
+                                     "date"
205
+                             ],
206
+                             "Dns": null,
207
+                             "Image": "base",
208
+                             "Volumes": {},
209
+                             "VolumesFrom": "",
210
+                             "WorkingDir":""
211
+
212
+                     },
213
+                     "State": {
214
+                             "Running": false,
215
+                             "Pid": 0,
216
+                             "ExitCode": 0,
217
+                             "StartedAt": "2013-05-07T14:51:42.087658+02:01360",
218
+                             "Ghost": false
219
+                     },
220
+                     "Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
221
+                     "NetworkSettings": {
222
+                             "IpAddress": "",
223
+                             "IpPrefixLen": 0,
224
+                             "Gateway": "",
225
+                             "Bridge": "",
226
+                             "PortMapping": null
227
+                     },
228
+                     "SysInitPath": "/home/kitty/go/src/github.com/dotcloud/docker/bin/docker",
229
+                     "ResolvConfPath": "/etc/resolv.conf",
230
+                     "Volumes": {},
231
+                     "HostConfig": {
232
+                         "Binds": null,
233
+                         "ContainerIDFile": "",
234
+                         "LxcConf": [],
235
+                         "Privileged": false,
236
+                         "PortBindings": {
237
+                            "80/tcp": [
238
+                                {
239
+                                    "HostIp": "0.0.0.0",
240
+                                    "HostPort": "49153"
241
+                                }
242
+                            ]
243
+                         },
244
+                         "Links": null,
245
+                         "PublishAllPorts": false
246
+                     }
247
+        }
248
+
249
+    Status Codes:
250
+
251
+    -   **200** – no error
252
+    -   **404** – no such container
253
+    -   **500** – server error
254
+
255
+### List processes running inside a container
256
+
257
+`GET /containers/(id)/top`
258
+
259
+List processes running inside the container `id`
260
+
261
+    **Example request**:
262
+
263
+        GET /containers/4fa6e0f0c678/top HTTP/1.1
264
+
265
+    **Example response**:
266
+
267
+        HTTP/1.1 200 OK
268
+        Content-Type: application/json
269
+
270
+        {
271
+             "Titles":[
272
+                     "USER",
273
+                     "PID",
274
+                     "%CPU",
275
+                     "%MEM",
276
+                     "VSZ",
277
+                     "RSS",
278
+                     "TTY",
279
+                     "STAT",
280
+                     "START",
281
+                     "TIME",
282
+                     "COMMAND"
283
+                     ],
284
+             "Processes":[
285
+                     ["root","20147","0.0","0.1","18060","1864","pts/4","S","10:06","0:00","bash"],
286
+                     ["root","20271","0.0","0.0","4312","352","pts/4","S+","10:07","0:00","sleep","10"]
287
+             ]
288
+        }
289
+
290
+    Query Parameters:
291
+
292
+     
293
+
294
+    -   **ps_args** – ps arguments to use (eg. aux)
295
+
296
+    Status Codes:
297
+
298
+    -   **200** – no error
299
+    -   **404** – no such container
300
+    -   **500** – server error
301
+
302
+### Get container logs
303
+
304
+`GET /containers/(id)/logs`
305
+
306
+Get stdout and stderr logs from the container ``id``
307
+
308
+    **Example request**:
309
+
310
+       GET /containers/4fa6e0f0c678/logs?stderr=1&stdout=1&timestamps=1&follow=1 HTTP/1.1
311
+
312
+    **Example response**:
313
+
314
+       HTTP/1.1 200 OK
315
+       Content-Type: application/vnd.docker.raw-stream
316
+
317
+       {{ STREAM }}
318
+
319
+    Query Parameters:
320
+
321
+     
322
+
323
+    -   **follow** – 1/True/true or 0/False/false, return stream.
324
+        Default false
325
+    -   **stdout** – 1/True/true or 0/False/false, if logs=true, return
326
+        stdout log. Default false
327
+    -   **stderr** – 1/True/true or 0/False/false, if logs=true, return
328
+        stderr log. Default false
329
+    -   **timestamps** – 1/True/true or 0/False/false, if logs=true, print
330
+        timestamps for every log line. Default false
331
+
332
+    Status Codes:
333
+
334
+    -   **200** – no error
335
+    -   **404** – no such container
336
+    -   **500** – server error
337
+
338
+### Inspect changes on a container's filesystem
339
+
340
+`GET /containers/(id)/changes`
341
+
342
+Inspect changes on container `id`'s filesystem
343
+
344
+    **Example request**:
345
+
346
+        GET /containers/4fa6e0f0c678/changes HTTP/1.1
347
+
348
+    **Example response**:
349
+
350
+        HTTP/1.1 200 OK
351
+        Content-Type: application/json
352
+
353
+        [
354
+             {
355
+                     "Path":"/dev",
356
+                     "Kind":0
357
+             },
358
+             {
359
+                     "Path":"/dev/kmsg",
360
+                     "Kind":1
361
+             },
362
+             {
363
+                     "Path":"/test",
364
+                     "Kind":1
365
+             }
366
+        ]
367
+
368
+    Status Codes:
369
+
370
+    -   **200** – no error
371
+    -   **404** – no such container
372
+    -   **500** – server error
373
+
374
+### Export a container
375
+
376
+`GET /containers/(id)/export`
377
+
378
+Export the contents of container `id`
379
+
380
+    **Example request**:
381
+
382
+        GET /containers/4fa6e0f0c678/export HTTP/1.1
383
+
384
+    **Example response**:
385
+
386
+        HTTP/1.1 200 OK
387
+        Content-Type: application/octet-stream
388
+
389
+        {{ STREAM }}
390
+
391
+    Status Codes:
392
+
393
+    -   **200** – no error
394
+    -   **404** – no such container
395
+    -   **500** – server error
396
+
397
+### Start a container
398
+
399
+`POST /containers/(id)/start`
400
+
401
+Start the container `id`
402
+
403
+    **Example request**:
404
+
405
+        POST /containers/(id)/start HTTP/1.1
406
+        Content-Type: application/json
407
+
408
+        {
409
+             "Binds":["/tmp:/tmp"],
410
+             "LxcConf":{"lxc.utsname":"docker"},
411
+             "PortBindings":{ "22/tcp": [{ "HostPort": "11022" }] },
412
+             "PublishAllPorts":false,
413
+             "Privileged":false
414
+        }
415
+
416
+    **Example response**:
417
+
418
+        HTTP/1.1 204 No Content
419
+        Content-Type: text/plain
420
+
421
+    Json Parameters:
422
+
423
+     
424
+
425
+    -   **hostConfig** – the container's host configuration (optional)
426
+
427
+    Status Codes:
428
+
429
+    -   **204** – no error
430
+    -   **404** – no such container
431
+    -   **500** – server error
432
+
433
+### Stop a container
434
+
435
+`POST /containers/(id)/stop`
436
+
437
+Stop the container `id`
438
+
439
+    **Example request**:
440
+
441
+        POST /containers/e90e34656806/stop?t=5 HTTP/1.1
442
+
443
+    **Example response**:
444
+
445
+        HTTP/1.1 204 OK
446
+
447
+    Query Parameters:
448
+
449
+     
450
+
451
+    -   **t** – number of seconds to wait before killing the container
452
+
453
+    Status Codes:
454
+
455
+    -   **204** – no error
456
+    -   **404** – no such container
457
+    -   **500** – server error
458
+
459
+### Restart a container
460
+
461
+`POST /containers/(id)/restart`
462
+
463
+Restart the container `id`
464
+
465
+    **Example request**:
466
+
467
+        POST /containers/e90e34656806/restart?t=5 HTTP/1.1
468
+
469
+    **Example response**:
470
+
471
+        HTTP/1.1 204 OK
472
+
473
+    Query Parameters:
474
+
475
+     
476
+
477
+    -   **t** – number of seconds to wait before killing the container
478
+
479
+    Status Codes:
480
+
481
+    -   **204** – no error
482
+    -   **404** – no such container
483
+    -   **500** – server error
484
+
485
+### Kill a container
486
+
487
+`POST /containers/(id)/kill`
488
+
489
+Kill the container `id`
490
+
491
+    **Example request**:
492
+
493
+        POST /containers/e90e34656806/kill HTTP/1.1
494
+
495
+    **Example response**:
496
+
497
+        HTTP/1.1 204 OK
498
+
499
+    Query Parameters
500
+
501
+    -   **signal** - Signal to send to the container: integer or string like "SIGINT".
502
+        When not set, SIGKILL is assumed and the call will waits for the container to exit.
503
+
504
+    Status Codes:
505
+
506
+    -   **204** – no error
507
+    -   **404** – no such container
508
+    -   **500** – server error
509
+
510
+### Attach to a container
511
+
512
+`POST /containers/(id)/attach`
513
+
514
+Attach to the container `id`
515
+
516
+    **Example request**:
517
+
518
+        POST /containers/16253994b7c4/attach?logs=1&stream=0&stdout=1 HTTP/1.1
519
+
520
+    **Example response**:
521
+
522
+        HTTP/1.1 200 OK
523
+        Content-Type: application/vnd.docker.raw-stream
524
+
525
+        {{ STREAM }}
526
+
527
+    Query Parameters:
528
+
529
+     
530
+
531
+    -   **logs** – 1/True/true or 0/False/false, return logs. Default
532
+        false
533
+    -   **stream** – 1/True/true or 0/False/false, return stream.
534
+        Default false
535
+    -   **stdin** – 1/True/true or 0/False/false, if stream=true, attach
536
+        to stdin. Default false
537
+    -   **stdout** – 1/True/true or 0/False/false, if logs=true, return
538
+        stdout log, if stream=true, attach to stdout. Default false
539
+    -   **stderr** – 1/True/true or 0/False/false, if logs=true, return
540
+        stderr log, if stream=true, attach to stderr. Default false
541
+
542
+    Status Codes:
543
+
544
+    -   **200** – no error
545
+    -   **400** – bad parameter
546
+    -   **404** – no such container
547
+    -   **500** – server error
548
+
549
+    **Stream details**:
550
+
551
+    When using the TTY setting is enabled in
552
+    [`POST /containers/create`
553
+    ](../docker_remote_api_v1.9/#post--containers-create "POST /containers/create"),
554
+    the stream is the raw data from the process PTY and client's stdin.
555
+    When the TTY is disabled, then the stream is multiplexed to separate
556
+    stdout and stderr.
557
+
558
+    The format is a **Header** and a **Payload** (frame).
559
+
560
+    **HEADER**
561
+
562
+    The header will contain the information on which stream write the
563
+    stream (stdout or stderr). It also contain the size of the
564
+    associated frame encoded on the last 4 bytes (uint32).
565
+
566
+    It is encoded on the first 8 bytes like this:
567
+
568
+        header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
569
+
570
+    `STREAM_TYPE` can be:
571
+
572
+    -   0: stdin (will be writen on stdout)
573
+    -   1: stdout
574
+    -   2: stderr
575
+
576
+    `SIZE1, SIZE2, SIZE3, SIZE4` are the 4 bytes of
577
+    the uint32 size encoded as big endian.
578
+
579
+    **PAYLOAD**
580
+
581
+    The payload is the raw stream.
582
+
583
+    **IMPLEMENTATION**
584
+
585
+    The simplest way to implement the Attach protocol is the following:
586
+
587
+    1.  Read 8 bytes
588
+    2.  chose stdout or stderr depending on the first byte
589
+    3.  Extract the frame size from the last 4 byets
590
+    4.  Read the extracted size and output it on the correct output
591
+    5.  Goto 1)
592
+
593
+### Wait a container
594
+
595
+`POST /containers/(id)/wait`
596
+
597
+Block until container `id` stops, then returns the exit code
598
+
599
+    **Example request**:
600
+
601
+        POST /containers/16253994b7c4/wait HTTP/1.1
602
+
603
+    **Example response**:
604
+
605
+        HTTP/1.1 200 OK
606
+        Content-Type: application/json
607
+
608
+        {"StatusCode":0}
609
+
610
+    Status Codes:
611
+
612
+    -   **200** – no error
613
+    -   **404** – no such container
614
+    -   **500** – server error
615
+
616
+### Remove a container
617
+
618
+`DELETE /containers/(id)`
619
+
620
+Remove the container `id` from the filesystem
621
+
622
+    **Example request**:
623
+
624
+        DELETE /containers/16253994b7c4?v=1 HTTP/1.1
625
+
626
+    **Example response**:
627
+
628
+        HTTP/1.1 204 OK
629
+
630
+    Query Parameters:
631
+
632
+     
633
+
634
+    -   **v** – 1/True/true or 0/False/false, Remove the volumes
635
+        associated to the container. Default false
636
+    -   **force** – 1/True/true or 0/False/false, Removes the container
637
+        even if it was running. Default false
638
+
639
+    Status Codes:
640
+
641
+    -   **204** – no error
642
+    -   **400** – bad parameter
643
+    -   **404** – no such container
644
+    -   **500** – server error
645
+
646
+### Copy files or folders from a container
647
+
648
+`POST /containers/(id)/copy`
649
+
650
+Copy files or folders of container `id`
651
+
652
+    **Example request**:
653
+
654
+        POST /containers/4fa6e0f0c678/copy HTTP/1.1
655
+        Content-Type: application/json
656
+
657
+        {
658
+             "Resource":"test.txt"
659
+        }
660
+
661
+    **Example response**:
662
+
663
+        HTTP/1.1 200 OK
664
+        Content-Type: application/octet-stream
665
+
666
+        {{ STREAM }}
667
+
668
+    Status Codes:
669
+
670
+    -   **200** – no error
671
+    -   **404** – no such container
672
+    -   **500** – server error
673
+
674
+## 2.2 Images
675
+
676
+### List Images
677
+
678
+`GET /images/json`
679
+
680
+**Example request**:
681
+
682
+        GET /images/json?all=0 HTTP/1.1
683
+
684
+    **Example response**:
685
+
686
+        HTTP/1.1 200 OK
687
+        Content-Type: application/json
688
+
689
+        [
690
+          {
691
+             "RepoTags": [
692
+               "ubuntu:12.04",
693
+               "ubuntu:precise",
694
+               "ubuntu:latest"
695
+             ],
696
+             "Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
697
+             "Created": 1365714795,
698
+             "Size": 131506275,
699
+             "VirtualSize": 131506275
700
+          },
701
+          {
702
+             "RepoTags": [
703
+               "ubuntu:12.10",
704
+               "ubuntu:quantal"
705
+             ],
706
+             "ParentId": "27cf784147099545",
707
+             "Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
708
+             "Created": 1364102658,
709
+             "Size": 24653,
710
+             "VirtualSize": 180116135
711
+          }
712
+        ]
713
+
714
+### Create an image
715
+
716
+`POST /images/create`
717
+
718
+Create an image, either by pull it from the registry or by importing it
719
+
720
+    **Example request**:
721
+
722
+        POST /images/create?fromImage=base HTTP/1.1
723
+
724
+    **Example response**:
725
+
726
+        HTTP/1.1 200 OK
727
+        Content-Type: application/json
728
+
729
+        {"status":"Pulling..."}
730
+        {"status":"Pulling", "progress":"1 B/ 100 B", "progressDetail":{"current":1, "total":100}}
731
+        {"error":"Invalid..."}
732
+        ...
733
+
734
+    When using this endpoint to pull an image from the registry, the
735
+    `X-Registry-Auth` header can be used to include
736
+    a base64-encoded AuthConfig object.
737
+
738
+    Query Parameters:
739
+
740
+     
741
+
742
+    -   **fromImage** – name of the image to pull
743
+    -   **fromSrc** – source to import, - means stdin
744
+    -   **repo** – repository
745
+    -   **tag** – tag
746
+    -   **registry** – the registry to pull from
747
+
748
+    Request Headers:
749
+
750
+     
751
+
752
+    -   **X-Registry-Auth** – base64-encoded AuthConfig object
753
+
754
+    Status Codes:
755
+
756
+    -   **200** – no error
757
+    -   **500** – server error
758
+
759
+### Insert a file in an image
760
+
761
+`POST /images/(name)/insert`
762
+
763
+Insert a file from `url` in the image `name` at `path`
764
+
765
+    **Example request**:
766
+
767
+        POST /images/test/insert?path=/usr&url=myurl HTTP/1.1
768
+
769
+    **Example response**:
770
+
771
+        HTTP/1.1 200 OK
772
+        Content-Type: application/json
773
+
774
+        {"status":"Inserting..."}
775
+        {"status":"Inserting", "progress":"1/? (n/a)", "progressDetail":{"current":1}}
776
+        {"error":"Invalid..."}
777
+        ...
778
+
779
+    Status Codes:
780
+
781
+    -   **200** – no error
782
+    -   **500** – server error
783
+
784
+### Inspect an image
785
+
786
+`GET /images/(name)/json`
787
+
788
+Return low-level information on the image `name`
789
+
790
+    **Example request**:
791
+
792
+        GET /images/base/json HTTP/1.1
793
+
794
+    **Example response**:
795
+
796
+        HTTP/1.1 200 OK
797
+        Content-Type: application/json
798
+
799
+        {
800
+             "id":"b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
801
+             "parent":"27cf784147099545",
802
+             "created":"2013-03-23T22:24:18.818426-07:00",
803
+             "container":"3d67245a8d72ecf13f33dffac9f79dcdf70f75acb84d308770391510e0c23ad0",
804
+             "container_config":
805
+                     {
806
+                             "Hostname":"",
807
+                             "User":"",
808
+                             "Memory":0,
809
+                             "MemorySwap":0,
810
+                             "AttachStdin":false,
811
+                             "AttachStdout":false,
812
+                             "AttachStderr":false,
813
+                             "PortSpecs":null,
814
+                             "Tty":true,
815
+                             "OpenStdin":true,
816
+                             "StdinOnce":false,
817
+                             "Env":null,
818
+                             "Cmd": ["/bin/bash"]
819
+                             ,"Dns":null,
820
+                             "Image":"base",
821
+                             "Volumes":null,
822
+                             "VolumesFrom":"",
823
+                             "WorkingDir":""
824
+                     },
825
+             "Size": 6824592
826
+        }
827
+
828
+    Status Codes:
829
+
830
+    -   **200** – no error
831
+    -   **404** – no such image
832
+    -   **500** – server error
833
+
834
+### Get the history of an image
835
+
836
+`GET /images/(name)/history`
837
+
838
+Return the history of the image `name`
839
+
840
+    **Example request**:
841
+
842
+        GET /images/base/history HTTP/1.1
843
+
844
+    **Example response**:
845
+
846
+        HTTP/1.1 200 OK
847
+        Content-Type: application/json
848
+
849
+        [
850
+             {
851
+                     "Id":"b750fe79269d",
852
+                     "Created":1364102658,
853
+                     "CreatedBy":"/bin/bash"
854
+             },
855
+             {
856
+                     "Id":"27cf78414709",
857
+                     "Created":1364068391,
858
+                     "CreatedBy":""
859
+             }
860
+        ]
861
+
862
+    Status Codes:
863
+
864
+    -   **200** – no error
865
+    -   **404** – no such image
866
+    -   **500** – server error
867
+
868
+### Push an image on the registry
869
+
870
+`POST /images/(name)/push`
871
+
872
+Push the image `name` on the registry
873
+
874
+    **Example request**:
875
+
876
+        POST /images/test/push HTTP/1.1
877
+
878
+    **Example response**:
879
+
880
+        HTTP/1.1 200 OK
881
+        Content-Type: application/json
882
+
883
+        {"status":"Pushing..."}
884
+        {"status":"Pushing", "progress":"1/? (n/a)", "progressDetail":{"current":1}}}
885
+        {"error":"Invalid..."}
886
+        ...
887
+
888
+    Query Parameters:
889
+
890
+     
891
+
892
+    -   **registry** – the registry you wan to push, optional
893
+
894
+    Request Headers:
895
+
896
+     
897
+
898
+    -   **X-Registry-Auth** – include a base64-encoded AuthConfig
899
+        object.
900
+
901
+    Status Codes:
902
+
903
+    -   **200** – no error
904
+    -   **404** – no such image
905
+    -   **500** – server error
906
+
907
+### Tag an image into a repository
908
+
909
+`POST /images/(name)/tag`
910
+
911
+Tag the image `name` into a repository
912
+
913
+    **Example request**:
914
+
915
+        POST /images/test/tag?repo=myrepo&force=0 HTTP/1.1
916
+
917
+    **Example response**:
918
+
919
+        HTTP/1.1 201 OK
920
+
921
+    Query Parameters:
922
+
923
+     
924
+
925
+    -   **repo** – The repository to tag in
926
+    -   **force** – 1/True/true or 0/False/false, default false
927
+
928
+    Status Codes:
929
+
930
+    -   **201** – no error
931
+    -   **400** – bad parameter
932
+    -   **404** – no such image
933
+    -   **409** – conflict
934
+    -   **500** – server error
935
+
936
+### Remove an image
937
+
938
+`DELETE /images/(name)`
939
+
940
+Remove the image `name` from the filesystem
941
+
942
+    **Example request**:
943
+
944
+        DELETE /images/test HTTP/1.1
945
+
946
+    **Example response**:
947
+
948
+        HTTP/1.1 200 OK
949
+        Content-type: application/json
950
+
951
+        [
952
+         {"Untagged":"3e2f21a89f"},
953
+         {"Deleted":"3e2f21a89f"},
954
+         {"Deleted":"53b4f83ac9"}
955
+        ]
956
+
957
+    Query Parameters:
958
+
959
+     
960
+
961
+    -   **force** – 1/True/true or 0/False/false, default false
962
+    -   **noprune** – 1/True/true or 0/False/false, default false
963
+
964
+    Status Codes:
965
+
966
+    -   **200** – no error
967
+    -   **404** – no such image
968
+    -   **409** – conflict
969
+    -   **500** – server error
970
+
971
+### Search images
972
+
973
+`GET /images/search`
974
+
975
+Search for an image on [Docker.io](https://index.docker.io).
976
+
977
+> **Note**:
978
+> The response keys have changed from API v1.6 to reflect the JSON
979
+> sent by the registry server to the docker daemon's request.
980
+
981
+    **Example request**:
982
+
983
+        GET /images/search?term=sshd HTTP/1.1
984
+
985
+    **Example response**:
986
+
987
+        HTTP/1.1 200 OK
988
+        Content-Type: application/json
989
+
990
+        [
991
+                {
992
+                    "description": "",
993
+                    "is_official": false,
994
+                    "is_trusted": false,
995
+                    "name": "wma55/u1210sshd",
996
+                    "star_count": 0
997
+                },
998
+                {
999
+                    "description": "",
1000
+                    "is_official": false,
1001
+                    "is_trusted": false,
1002
+                    "name": "jdswinbank/sshd",
1003
+                    "star_count": 0
1004
+                },
1005
+                {
1006
+                    "description": "",
1007
+                    "is_official": false,
1008
+                    "is_trusted": false,
1009
+                    "name": "vgauthier/sshd",
1010
+                    "star_count": 0
1011
+                }
1012
+        ...
1013
+        ]
1014
+
1015
+    Query Parameters:
1016
+
1017
+     
1018
+
1019
+    -   **term** – term to search
1020
+
1021
+    Status Codes:
1022
+
1023
+    -   **200** – no error
1024
+    -   **500** – server error
1025
+
1026
+## 2.3 Misc
1027
+
1028
+### Build an image from Dockerfile via stdin
1029
+
1030
+`POST /build`
1031
+
1032
+Build an image from Dockerfile via stdin
1033
+
1034
+    **Example request**:
1035
+
1036
+        POST /build HTTP/1.1
1037
+
1038
+        {{ STREAM }}
1039
+
1040
+    **Example response**:
1041
+
1042
+        HTTP/1.1 200 OK
1043
+        Content-Type: application/json
1044
+
1045
+        {"stream":"Step 1..."}
1046
+        {"stream":"..."}
1047
+        {"error":"Error...", "errorDetail":{"code": 123, "message": "Error..."}}
1048
+
1049
+    The stream must be a tar archive compressed with one of the
1050
+    following algorithms: identity (no compression), gzip, bzip2, xz.
1051
+
1052
+    The archive must include a file called `Dockerfile`
1053
+    at its root. It may include any number of other files,
1054
+    which will be accessible in the build context (See the [*ADD build
1055
+    command*](/reference/builder/#dockerbuilder)).
1056
+
1057
+    Query Parameters:
1058
+
1059
+     
1060
+
1061
+    -   **t** – repository name (and optionally a tag) to be applied to
1062
+        the resulting image in case of success
1063
+    -   **q** – suppress verbose build output
1064
+    -   **nocache** – do not use the cache when building the image
1065
+    -   **rm** - remove intermediate containers after a successful build
1066
+    -   **forcerm - always remove intermediate containers (includes rm)
1067
+
1068
+    Request Headers:
1069
+
1070
+     
1071
+
1072
+    -   **Content-type** – should be set to
1073
+        `"application/tar"`.
1074
+    -   **X-Registry-Config** – base64-encoded ConfigFile object
1075
+
1076
+    Status Codes:
1077
+
1078
+    -   **200** – no error
1079
+    -   **500** – server error
1080
+
1081
+### Check auth configuration
1082
+
1083
+`POST /auth`
1084
+
1085
+Get the default username and email
1086
+
1087
+    **Example request**:
1088
+
1089
+        POST /auth HTTP/1.1
1090
+        Content-Type: application/json
1091
+
1092
+        {
1093
+             "username":"hannibal",
1094
+             "password:"xxxx",
1095
+             "email":"hannibal@a-team.com",
1096
+             "serveraddress":"https://index.docker.io/v1/"
1097
+        }
1098
+
1099
+    **Example response**:
1100
+
1101
+        HTTP/1.1 200 OK
1102
+
1103
+    Status Codes:
1104
+
1105
+    -   **200** – no error
1106
+    -   **204** – no error
1107
+    -   **500** – server error
1108
+
1109
+### Display system-wide information
1110
+
1111
+`GET /info`
1112
+
1113
+Display system-wide information
1114
+
1115
+    **Example request**:
1116
+
1117
+        GET /info HTTP/1.1
1118
+
1119
+    **Example response**:
1120
+
1121
+        HTTP/1.1 200 OK
1122
+        Content-Type: application/json
1123
+
1124
+        {
1125
+             "Containers":11,
1126
+             "Images":16,
1127
+             "Debug":false,
1128
+             "NFd": 11,
1129
+             "NGoroutines":21,
1130
+             "MemoryLimit":true,
1131
+             "SwapLimit":false,
1132
+             "IPv4Forwarding":true
1133
+        }
1134
+
1135
+    Status Codes:
1136
+
1137
+    -   **200** – no error
1138
+    -   **500** – server error
1139
+
1140
+### Show the docker version information
1141
+
1142
+`GET /version`
1143
+
1144
+Show the docker version information
1145
+
1146
+    **Example request**:
1147
+
1148
+        GET /version HTTP/1.1
1149
+
1150
+    **Example response**:
1151
+
1152
+        HTTP/1.1 200 OK
1153
+        Content-Type: application/json
1154
+
1155
+        {
1156
+             "Version":"0.2.2",
1157
+             "GitCommit":"5a2a5cc+CHANGES",
1158
+             "GoVersion":"go1.0.3"
1159
+        }
1160
+
1161
+    Status Codes:
1162
+
1163
+    -   **200** – no error
1164
+    -   **500** – server error
1165
+
1166
+### Ping the docker server
1167
+
1168
+`GET /_ping`
1169
+
1170
+Ping the docker server
1171
+
1172
+    **Example request**:
1173
+
1174
+        GET /_ping HTTP/1.1
1175
+
1176
+    **Example response**:
1177
+
1178
+        HTTP/1.1 200 OK
1179
+
1180
+        OK
1181
+
1182
+    Status Codes:
1183
+
1184
+    -   **200** - no error
1185
+    -   **500** - server error
1186
+
1187
+### Create a new image from a container's changes
1188
+
1189
+`POST /commit`
1190
+
1191
+Create a new image from a container's changes
1192
+
1193
+    **Example request**:
1194
+
1195
+        POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
1196
+        Content-Type: application/json
1197
+
1198
+        {
1199
+             "Hostname":"",
1200
+             "User":"",
1201
+             "Memory":0,
1202
+             "MemorySwap":0,
1203
+             "AttachStdin":false,
1204
+             "AttachStdout":true,
1205
+             "AttachStderr":true,
1206
+             "PortSpecs":null,
1207
+             "Tty":false,
1208
+             "OpenStdin":false,
1209
+             "StdinOnce":false,
1210
+             "Env":null,
1211
+             "Cmd":[
1212
+                     "date"
1213
+             ],
1214
+             "Volumes":{
1215
+                     "/tmp": {}
1216
+             },
1217
+             "WorkingDir":"",
1218
+             "DisableNetwork": false,
1219
+             "ExposedPorts":{
1220
+                     "22/tcp": {}
1221
+             }
1222
+        }
1223
+
1224
+    **Example response**:
1225
+
1226
+        HTTP/1.1 201 OK
1227
+            Content-Type: application/vnd.docker.raw-stream
1228
+
1229
+        {"Id":"596069db4bf5"}
1230
+
1231
+    Json Parameters:
1232
+
1233
+
1234
+
1235
+    -  **config** - the container's configuration
1236
+
1237
+    Query Parameters:
1238
+
1239
+     
1240
+
1241
+    -   **container** – source container
1242
+    -   **repo** – repository
1243
+    -   **tag** – tag
1244
+    -   **m** – commit message
1245
+    -   **author** – author (eg. "John Hannibal Smith
1246
+        <[hannibal@a-team.com](mailto:hannibal%40a-team.com)>")
1247
+
1248
+    Status Codes:
1249
+
1250
+    -   **201** – no error
1251
+    -   **404** – no such container
1252
+    -   **500** – server error
1253
+
1254
+### Monitor Docker's events
1255
+
1256
+`GET /events`
1257
+
1258
+Get events from docker, either in real time via streaming, or
1259
+via polling (using since)
1260
+
1261
+    **Example request**:
1262
+
1263
+        GET /events?since=1374067924
1264
+
1265
+    **Example response**:
1266
+
1267
+        HTTP/1.1 200 OK
1268
+        Content-Type: application/json
1269
+
1270
+        {"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
1271
+        {"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
1272
+        {"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966}
1273
+        {"status":"destroy","id":"dfdf82bd3881","from":"base:latest","time":1374067970}
1274
+
1275
+    Query Parameters:
1276
+
1277
+     
1278
+
1279
+    -   **since** – timestamp used for polling
1280
+    -   **until** – timestamp used for polling
1281
+
1282
+    Status Codes:
1283
+
1284
+    -   **200** – no error
1285
+    -   **500** – server error
1286
+
1287
+### Get a tarball containing all images and tags in a repository
1288
+
1289
+`GET /images/(name)/get`
1290
+
1291
+Get a tarball containing all images and metadata for the repository
1292
+specified by `name`.
1293
+
1294
+    **Example request**
1295
+
1296
+        GET /images/ubuntu/get
1297
+
1298
+    **Example response**:
1299
+
1300
+        HTTP/1.1 200 OK
1301
+        Content-Type: application/x-tar
1302
+
1303
+        Binary data stream
1304
+
1305
+    Status Codes:
1306
+
1307
+    -   **200** – no error
1308
+    -   **500** – server error
1309
+
1310
+### Load a tarball with a set of images and tags into docker
1311
+
1312
+`POST /images/load`
1313
+
1314
+Load a set of images and tags into the docker repository.
1315
+
1316
+    **Example request**
1317
+
1318
+        POST /images/load
1319
+
1320
+        Tarball in body
1321
+
1322
+    **Example response**:
1323
+
1324
+        HTTP/1.1 200 OK
1325
+
1326
+    Status Codes:
1327
+
1328
+    -   **200** – no error
1329
+    -   **500** – server error
1330
+
1331
+# 3. Going further
1332
+
1333
+## 3.1 Inside `docker run`
1334
+
1335
+Here are the steps of `docker run`:
1336
+
1337
+- Create the container
1338
+
1339
+- If the status code is 404, it means the image doesn't exists:
1340
+    - Try to pull it
1341
+    - Then retry to create the container
1342
+
1343
+- Start the container
1344
+
1345
+- If you are not in detached mode:
1346
+    - Attach to the container, using logs=1 (to have stdout and
1347
+      stderr from the container's start) and stream=1
1348
+
1349
+- If in detached mode or only stdin is attached:
1350
+    - Display the container's id
1351
+
1352
+## 3.2 Hijacking
1353
+
1354
+In this version of the API, /attach, uses hijacking to transport stdin,
1355
+stdout and stderr on the same socket. This might change in the future.
1356
+
1357
+## 3.3 CORS Requests
1358
+
1359
+To enable cross origin requests to the remote api add the flag
1360
+"–api-enable-cors" when running docker in daemon mode.
1361
+
1362
+    $ docker -d -H="192.168.1.9:4243" --api-enable-cors
... ...
@@ -192,6 +192,7 @@ To kill the container, use `docker kill`.
192 192
 
193 193
     Build a new container image from the source code at PATH
194 194
 
195
+      --force-rm=false     Always remove intermediate containers, even after unsuccessful builds
195 196
       --no-cache=false     Do not use cache when building the image
196 197
       -q, --quiet=false    Suppress the verbose output generated by the containers
197 198
       --rm=true            Remove intermediate containers after a successful build
... ...
@@ -394,7 +394,7 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u
394 394
 	}
395 395
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
396 396
 
397
-	buildfile := server.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
397
+	buildfile := server.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
398 398
 	id, err := buildfile.Build(context.Archive(dockerfile, t))
399 399
 	if err != nil {
400 400
 		return nil, err
... ...
@@ -828,7 +828,7 @@ func TestForbiddenContextPath(t *testing.T) {
828 828
 	}
829 829
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
830 830
 
831
-	buildfile := server.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
831
+	buildfile := server.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
832 832
 	_, err = buildfile.Build(context.Archive(dockerfile, t))
833 833
 
834 834
 	if err == nil {
... ...
@@ -874,7 +874,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
874 874
 	}
875 875
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
876 876
 
877
-	buildfile := server.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
877
+	buildfile := server.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
878 878
 	_, err = buildfile.Build(context.Archive(dockerfile, t))
879 879
 
880 880
 	if err == nil {
... ...
@@ -50,6 +50,7 @@ type buildFile struct {
50 50
 	verbose      bool
51 51
 	utilizeCache bool
52 52
 	rm           bool
53
+	forceRm      bool
53 54
 
54 55
 	authConfig *registry.AuthConfig
55 56
 	configFile *registry.ConfigFile
... ...
@@ -807,6 +808,9 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
807 807
 			continue
808 808
 		}
809 809
 		if err := b.BuildStep(fmt.Sprintf("%d", stepN), line); err != nil {
810
+			if b.forceRm {
811
+				b.clearTmp(b.tmpContainers)
812
+			}
810 813
 			return "", err
811 814
 		} else if b.rm {
812 815
 			b.clearTmp(b.tmpContainers)
... ...
@@ -859,7 +863,7 @@ func stripComments(raw []byte) string {
859 859
 	return strings.Join(out, "\n")
860 860
 }
861 861
 
862
-func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *registry.AuthConfig, authConfigFile *registry.ConfigFile) BuildFile {
862
+func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, forceRm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *registry.AuthConfig, authConfigFile *registry.ConfigFile) BuildFile {
863 863
 	return &buildFile{
864 864
 		daemon:        srv.daemon,
865 865
 		srv:           srv,
... ...
@@ -871,6 +875,7 @@ func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeC
871 871
 		verbose:       verbose,
872 872
 		utilizeCache:  utilizeCache,
873 873
 		rm:            rm,
874
+		forceRm:       forceRm,
874 875
 		sf:            sf,
875 876
 		authConfig:    auth,
876 877
 		configFile:    authConfigFile,
... ...
@@ -438,6 +438,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status {
438 438
 		suppressOutput = job.GetenvBool("q")
439 439
 		noCache        = job.GetenvBool("nocache")
440 440
 		rm             = job.GetenvBool("rm")
441
+		forceRm        = job.GetenvBool("forcerm")
441 442
 		authConfig     = &registry.AuthConfig{}
442 443
 		configFile     = &registry.ConfigFile{}
443 444
 		tag            string
... ...
@@ -496,7 +497,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status {
496 496
 			Writer:          job.Stdout,
497 497
 			StreamFormatter: sf,
498 498
 		},
499
-		!suppressOutput, !noCache, rm, job.Stdout, sf, authConfig, configFile)
499
+		!suppressOutput, !noCache, rm, forceRm, job.Stdout, sf, authConfig, configFile)
500 500
 	id, err := b.Build(context)
501 501
 	if err != nil {
502 502
 		return job.Error(err)