docker_cli_build_test.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. "time"
  10. )
  11. func TestBuildCacheADD(t *testing.T) {
  12. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "1")
  13. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcacheadd1", ".")
  14. buildCmd.Dir = buildDirectory
  15. exitCode, err := runCommand(buildCmd)
  16. errorOut(err, t, fmt.Sprintf("build failed to complete: %v", err))
  17. if err != nil || exitCode != 0 {
  18. t.Fatal("failed to build the image")
  19. }
  20. buildDirectory = filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "2")
  21. buildCmd = exec.Command(dockerBinary, "build", "-t", "testcacheadd2", ".")
  22. buildCmd.Dir = buildDirectory
  23. out, exitCode, err := runCommandWithOutput(buildCmd)
  24. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  25. if err != nil || exitCode != 0 {
  26. t.Fatal("failed to build the image")
  27. }
  28. if strings.Contains(out, "Using cache") {
  29. t.Fatal("2nd build used cache on ADD, it shouldn't")
  30. }
  31. deleteImages("testcacheadd1")
  32. deleteImages("testcacheadd2")
  33. logDone("build - build two images with ADD")
  34. }
  35. func TestBuildSixtySteps(t *testing.T) {
  36. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildSixtySteps")
  37. buildCmd := exec.Command(dockerBinary, "build", "-t", "foobuildsixtysteps", ".")
  38. buildCmd.Dir = buildDirectory
  39. out, exitCode, err := runCommandWithOutput(buildCmd)
  40. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  41. if err != nil || exitCode != 0 {
  42. t.Fatal("failed to build the image")
  43. }
  44. deleteImages("foobuildsixtysteps")
  45. logDone("build - build an image with sixty build steps")
  46. }
  47. func TestAddSingleFileToRoot(t *testing.T) {
  48. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "SingleFileToRoot")
  49. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. f.Close()
  54. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", ".")
  55. buildCmd.Dir = buildDirectory
  56. out, exitCode, err := runCommandWithOutput(buildCmd)
  57. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  58. if err != nil || exitCode != 0 {
  59. t.Fatal("failed to build the image")
  60. }
  61. deleteImages("testaddimg")
  62. logDone("build - add single file to root")
  63. }
  64. // Issue #3960: "ADD src ." hangs
  65. func TestAddSingleFileToWorkdir(t *testing.T) {
  66. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "SingleFileToWorkdir")
  67. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. f.Close()
  72. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", ".")
  73. buildCmd.Dir = buildDirectory
  74. done := make(chan error)
  75. go func() {
  76. out, exitCode, err := runCommandWithOutput(buildCmd)
  77. if err != nil || exitCode != 0 {
  78. done <- fmt.Errorf("build failed to complete: %s %v", out, err)
  79. return
  80. }
  81. done <- nil
  82. }()
  83. select {
  84. case <-time.After(5 * time.Second):
  85. if err := buildCmd.Process.Kill(); err != nil {
  86. fmt.Printf("could not kill build (pid=%d): %v\n", buildCmd.Process.Pid, err)
  87. }
  88. t.Fatal("build timed out")
  89. case err := <-done:
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. }
  94. deleteImages("testaddimg")
  95. logDone("build - add single file to workdir")
  96. }
  97. func TestAddSingleFileToExistDir(t *testing.T) {
  98. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  99. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToExistDir")
  100. buildCmd.Dir = buildDirectory
  101. out, exitCode, err := runCommandWithOutput(buildCmd)
  102. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  103. if err != nil || exitCode != 0 {
  104. t.Fatal("failed to build the image")
  105. }
  106. deleteImages("testaddimg")
  107. logDone("build - add single file to existing dir")
  108. }
  109. func TestAddSingleFileToNonExistDir(t *testing.T) {
  110. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  111. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToNonExistDir")
  112. buildCmd.Dir = buildDirectory
  113. out, exitCode, err := runCommandWithOutput(buildCmd)
  114. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  115. if err != nil || exitCode != 0 {
  116. t.Fatal("failed to build the image")
  117. }
  118. deleteImages("testaddimg")
  119. logDone("build - add single file to non-existing dir")
  120. }
  121. func TestAddDirContentToRoot(t *testing.T) {
  122. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  123. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToRoot")
  124. buildCmd.Dir = buildDirectory
  125. out, exitCode, err := runCommandWithOutput(buildCmd)
  126. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  127. if err != nil || exitCode != 0 {
  128. t.Fatal("failed to build the image")
  129. }
  130. deleteImages("testaddimg")
  131. logDone("build - add directory contents to root")
  132. }
  133. func TestAddDirContentToExistDir(t *testing.T) {
  134. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  135. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToExistDir")
  136. buildCmd.Dir = buildDirectory
  137. out, exitCode, err := runCommandWithOutput(buildCmd)
  138. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  139. if err != nil || exitCode != 0 {
  140. t.Fatal("failed to build the image")
  141. }
  142. deleteImages("testaddimg")
  143. logDone("build - add directory contents to existing dir")
  144. }
  145. func TestAddWholeDirToRoot(t *testing.T) {
  146. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "WholeDirToRoot")
  147. test_dir := filepath.Join(buildDirectory, "test_dir")
  148. if err := os.MkdirAll(test_dir, 0755); err != nil {
  149. t.Fatal(err)
  150. }
  151. f, err := os.OpenFile(filepath.Join(test_dir, "test_file"), os.O_CREATE, 0644)
  152. if err != nil {
  153. t.Fatal(err)
  154. }
  155. f.Close()
  156. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", ".")
  157. buildCmd.Dir = buildDirectory
  158. out, exitCode, err := runCommandWithOutput(buildCmd)
  159. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  160. if err != nil || exitCode != 0 {
  161. t.Fatal("failed to build the image")
  162. }
  163. deleteImages("testaddimg")
  164. logDone("build - add whole directory to root")
  165. }
  166. func TestAddEtcToRoot(t *testing.T) {
  167. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  168. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "EtcToRoot")
  169. buildCmd.Dir = buildDirectory
  170. out, exitCode, err := runCommandWithOutput(buildCmd)
  171. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  172. if err != nil || exitCode != 0 {
  173. t.Fatal("failed to build the image")
  174. }
  175. deleteImages("testaddimg")
  176. logDone("build - add etc directory to root")
  177. }
  178. func TestCopySingleFileToRoot(t *testing.T) {
  179. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "SingleFileToRoot")
  180. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  181. if err != nil {
  182. t.Fatal(err)
  183. }
  184. f.Close()
  185. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", ".")
  186. buildCmd.Dir = buildDirectory
  187. out, exitCode, err := runCommandWithOutput(buildCmd)
  188. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  189. if err != nil || exitCode != 0 {
  190. t.Fatal("failed to build the image")
  191. }
  192. deleteImages("testcopyimg")
  193. logDone("build - copy single file to root")
  194. }
  195. // Issue #3960: "ADD src ." hangs - adapted for COPY
  196. func TestCopySingleFileToWorkdir(t *testing.T) {
  197. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "SingleFileToWorkdir")
  198. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  199. if err != nil {
  200. t.Fatal(err)
  201. }
  202. f.Close()
  203. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", ".")
  204. buildCmd.Dir = buildDirectory
  205. done := make(chan error)
  206. go func() {
  207. out, exitCode, err := runCommandWithOutput(buildCmd)
  208. if err != nil || exitCode != 0 {
  209. done <- fmt.Errorf("build failed to complete: %s %v", out, err)
  210. return
  211. }
  212. done <- nil
  213. }()
  214. select {
  215. case <-time.After(5 * time.Second):
  216. if err := buildCmd.Process.Kill(); err != nil {
  217. fmt.Printf("could not kill build (pid=%d): %v\n", buildCmd.Process.Pid, err)
  218. }
  219. t.Fatal("build timed out")
  220. case err := <-done:
  221. if err != nil {
  222. t.Fatal(err)
  223. }
  224. }
  225. deleteImages("testcopyimg")
  226. logDone("build - copy single file to workdir")
  227. }
  228. func TestCopySingleFileToExistDir(t *testing.T) {
  229. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  230. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "SingleFileToExistDir")
  231. buildCmd.Dir = buildDirectory
  232. out, exitCode, err := runCommandWithOutput(buildCmd)
  233. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  234. if err != nil || exitCode != 0 {
  235. t.Fatal("failed to build the image")
  236. }
  237. deleteImages("testcopyimg")
  238. logDone("build - add single file to existing dir")
  239. }
  240. func TestCopySingleFileToNonExistDir(t *testing.T) {
  241. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  242. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "SingleFileToNonExistDir")
  243. buildCmd.Dir = buildDirectory
  244. out, exitCode, err := runCommandWithOutput(buildCmd)
  245. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  246. if err != nil || exitCode != 0 {
  247. t.Fatal("failed to build the image")
  248. }
  249. deleteImages("testcopyimg")
  250. logDone("build - copy single file to non-existing dir")
  251. }
  252. func TestCopyDirContentToRoot(t *testing.T) {
  253. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  254. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DirContentToRoot")
  255. buildCmd.Dir = buildDirectory
  256. out, exitCode, err := runCommandWithOutput(buildCmd)
  257. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  258. if err != nil || exitCode != 0 {
  259. t.Fatal("failed to build the image")
  260. }
  261. deleteImages("testcopyimg")
  262. logDone("build - copy directory contents to root")
  263. }
  264. func TestCopyDirContentToExistDir(t *testing.T) {
  265. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  266. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DirContentToExistDir")
  267. buildCmd.Dir = buildDirectory
  268. out, exitCode, err := runCommandWithOutput(buildCmd)
  269. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  270. if err != nil || exitCode != 0 {
  271. t.Fatal("failed to build the image")
  272. }
  273. deleteImages("testcopyimg")
  274. logDone("build - copy directory contents to existing dir")
  275. }
  276. func TestCopyWholeDirToRoot(t *testing.T) {
  277. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "WholeDirToRoot")
  278. test_dir := filepath.Join(buildDirectory, "test_dir")
  279. if err := os.MkdirAll(test_dir, 0755); err != nil {
  280. t.Fatal(err)
  281. }
  282. f, err := os.OpenFile(filepath.Join(test_dir, "test_file"), os.O_CREATE, 0644)
  283. if err != nil {
  284. t.Fatal(err)
  285. }
  286. f.Close()
  287. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", ".")
  288. buildCmd.Dir = buildDirectory
  289. out, exitCode, err := runCommandWithOutput(buildCmd)
  290. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  291. if err != nil || exitCode != 0 {
  292. t.Fatal("failed to build the image")
  293. }
  294. deleteImages("testcopyimg")
  295. logDone("build - copy whole directory to root")
  296. }
  297. func TestCopyEtcToRoot(t *testing.T) {
  298. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  299. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "EtcToRoot")
  300. buildCmd.Dir = buildDirectory
  301. out, exitCode, err := runCommandWithOutput(buildCmd)
  302. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  303. if err != nil || exitCode != 0 {
  304. t.Fatal("failed to build the image")
  305. }
  306. deleteImages("testcopyimg")
  307. logDone("build - copy etc directory to root")
  308. }
  309. func TestCopyDisallowRemote(t *testing.T) {
  310. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  311. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DisallowRemote")
  312. buildCmd.Dir = buildDirectory
  313. out, exitCode, err := runCommandWithOutput(buildCmd)
  314. if err == nil || exitCode == 0 {
  315. t.Fatalf("building the image should've failed; output: %s", out)
  316. }
  317. deleteImages("testcopyimg")
  318. logDone("build - copy - disallow copy from remote")
  319. }
  320. // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  321. // when we can't access files in the context.
  322. func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  323. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildWithInaccessibleFilesInContext")
  324. {
  325. // This is used to ensure we detect inaccessible files early during build in the cli client
  326. pathToInaccessibleFileBuildDirectory := filepath.Join(buildDirectory, "inaccessiblefile")
  327. pathToFileWithoutReadAccess := filepath.Join(pathToInaccessibleFileBuildDirectory, "fileWithoutReadAccess")
  328. err := os.Chown(pathToFileWithoutReadAccess, 0, 0)
  329. errorOut(err, t, fmt.Sprintf("failed to chown file to root: %s", err))
  330. err = os.Chmod(pathToFileWithoutReadAccess, 0700)
  331. errorOut(err, t, fmt.Sprintf("failed to chmod file to 700: %s", err))
  332. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  333. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  334. buildCmd.Dir = pathToInaccessibleFileBuildDirectory
  335. out, exitCode, err := runCommandWithOutput(buildCmd)
  336. if err == nil || exitCode == 0 {
  337. t.Fatalf("build should have failed: %s %s", err, out)
  338. }
  339. // check if we've detected the failure before we started building
  340. if !strings.Contains(out, "no permission to read from ") {
  341. t.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  342. }
  343. if !strings.Contains(out, "Error checking context is accessible") {
  344. t.Fatalf("output should've contained the string: Error checking context is accessible")
  345. }
  346. }
  347. {
  348. // This is used to ensure we detect inaccessible directories early during build in the cli client
  349. pathToInaccessibleDirectoryBuildDirectory := filepath.Join(buildDirectory, "inaccessibledirectory")
  350. pathToDirectoryWithoutReadAccess := filepath.Join(pathToInaccessibleDirectoryBuildDirectory, "directoryWeCantStat")
  351. pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  352. err := os.Chown(pathToDirectoryWithoutReadAccess, 0, 0)
  353. errorOut(err, t, fmt.Sprintf("failed to chown directory to root: %s", err))
  354. err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444)
  355. errorOut(err, t, fmt.Sprintf("failed to chmod directory to 755: %s", err))
  356. err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700)
  357. errorOut(err, t, fmt.Sprintf("failed to chmod file to 444: %s", err))
  358. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  359. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  360. buildCmd.Dir = pathToInaccessibleDirectoryBuildDirectory
  361. out, exitCode, err := runCommandWithOutput(buildCmd)
  362. if err == nil || exitCode == 0 {
  363. t.Fatalf("build should have failed: %s %s", err, out)
  364. }
  365. // check if we've detected the failure before we started building
  366. if !strings.Contains(out, "can't stat") {
  367. t.Fatalf("output should've contained the string: can't access %s", out)
  368. }
  369. if !strings.Contains(out, "Error checking context is accessible") {
  370. t.Fatalf("output should've contained the string: Error checking context is accessible")
  371. }
  372. }
  373. {
  374. // This is used to ensure we don't follow links when checking if everything in the context is accessible
  375. // This test doesn't require that we run commands as an unprivileged user
  376. pathToDirectoryWhichContainsLinks := filepath.Join(buildDirectory, "linksdirectory")
  377. buildCmd := exec.Command(dockerBinary, "build", "-t", "testlinksok", ".")
  378. buildCmd.Dir = pathToDirectoryWhichContainsLinks
  379. out, exitCode, err := runCommandWithOutput(buildCmd)
  380. if err != nil || exitCode != 0 {
  381. t.Fatalf("build should have worked: %s %s", err, out)
  382. }
  383. deleteImages("testlinksok")
  384. }
  385. deleteImages("inaccessiblefiles")
  386. logDone("build - ADD from context with inaccessible files must fail")
  387. logDone("build - ADD from context with accessible links must work")
  388. }
  389. func TestBuildForceRm(t *testing.T) {
  390. containerCountBefore, err := getContainerCount()
  391. if err != nil {
  392. t.Fatalf("failed to get the container count: %s", err)
  393. }
  394. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildForceRm")
  395. buildCmd := exec.Command(dockerBinary, "build", "--force-rm", ".")
  396. buildCmd.Dir = buildDirectory
  397. _, exitCode, err := runCommandWithOutput(buildCmd)
  398. if err == nil || exitCode == 0 {
  399. t.Fatal("failed to build the image")
  400. }
  401. containerCountAfter, err := getContainerCount()
  402. if err != nil {
  403. t.Fatalf("failed to get the container count: %s", err)
  404. }
  405. if containerCountBefore != containerCountAfter {
  406. t.Fatalf("--force-rm shouldn't have left containers behind")
  407. }
  408. logDone("build - ensure --force-rm doesn't leave containers behind")
  409. }
  410. func TestBuildRm(t *testing.T) {
  411. {
  412. containerCountBefore, err := getContainerCount()
  413. if err != nil {
  414. t.Fatalf("failed to get the container count: %s", err)
  415. }
  416. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  417. buildCmd := exec.Command(dockerBinary, "build", "--rm", "-t", "testbuildrm", ".")
  418. buildCmd.Dir = buildDirectory
  419. _, exitCode, err := runCommandWithOutput(buildCmd)
  420. if err != nil || exitCode != 0 {
  421. t.Fatal("failed to build the image")
  422. }
  423. containerCountAfter, err := getContainerCount()
  424. if err != nil {
  425. t.Fatalf("failed to get the container count: %s", err)
  426. }
  427. if containerCountBefore != containerCountAfter {
  428. t.Fatalf("-rm shouldn't have left containers behind")
  429. }
  430. deleteImages("testbuildrm")
  431. }
  432. {
  433. containerCountBefore, err := getContainerCount()
  434. if err != nil {
  435. t.Fatalf("failed to get the container count: %s", err)
  436. }
  437. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  438. buildCmd := exec.Command(dockerBinary, "build", "-t", "testbuildrm", ".")
  439. buildCmd.Dir = buildDirectory
  440. _, exitCode, err := runCommandWithOutput(buildCmd)
  441. if err != nil || exitCode != 0 {
  442. t.Fatal("failed to build the image")
  443. }
  444. containerCountAfter, err := getContainerCount()
  445. if err != nil {
  446. t.Fatalf("failed to get the container count: %s", err)
  447. }
  448. if containerCountBefore != containerCountAfter {
  449. t.Fatalf("--rm shouldn't have left containers behind")
  450. }
  451. deleteImages("testbuildrm")
  452. }
  453. {
  454. containerCountBefore, err := getContainerCount()
  455. if err != nil {
  456. t.Fatalf("failed to get the container count: %s", err)
  457. }
  458. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  459. buildCmd := exec.Command(dockerBinary, "build", "--rm=false", "-t", "testbuildrm", ".")
  460. buildCmd.Dir = buildDirectory
  461. _, exitCode, err := runCommandWithOutput(buildCmd)
  462. if err != nil || exitCode != 0 {
  463. t.Fatal("failed to build the image")
  464. }
  465. containerCountAfter, err := getContainerCount()
  466. if err != nil {
  467. t.Fatalf("failed to get the container count: %s", err)
  468. }
  469. if containerCountBefore == containerCountAfter {
  470. t.Fatalf("--rm=false should have left containers behind")
  471. }
  472. deleteAllContainers()
  473. deleteImages("testbuildrm")
  474. }
  475. logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
  476. logDone("build - ensure --rm=false overrides the default")
  477. }
  478. func TestBuildWithVolumes(t *testing.T) {
  479. name := "testbuildvolumes"
  480. expected := "map[/test1:map[] /test2:map[]]"
  481. defer deleteImages(name)
  482. _, err := buildImage(name,
  483. `FROM scratch
  484. VOLUME /test1
  485. VOLUME /test2`,
  486. true)
  487. if err != nil {
  488. t.Fatal(err)
  489. }
  490. res, err := inspectField(name, "Config.Volumes")
  491. if err != nil {
  492. t.Fatal(err)
  493. }
  494. if res != expected {
  495. t.Fatalf("Volumes %s, expected %s", res, expected)
  496. }
  497. logDone("build - with volumes")
  498. }
  499. func TestBuildMaintainer(t *testing.T) {
  500. name := "testbuildmaintainer"
  501. expected := "dockerio"
  502. defer deleteImages(name)
  503. _, err := buildImage(name,
  504. `FROM scratch
  505. MAINTAINER dockerio`,
  506. true)
  507. if err != nil {
  508. t.Fatal(err)
  509. }
  510. res, err := inspectField(name, "Author")
  511. if err != nil {
  512. t.Fatal(err)
  513. }
  514. if res != expected {
  515. t.Fatalf("Maintainer %s, expected %s", res, expected)
  516. }
  517. logDone("build - maintainer")
  518. }
  519. func TestBuildUser(t *testing.T) {
  520. name := "testbuilduser"
  521. expected := "dockerio"
  522. defer deleteImages(name)
  523. _, err := buildImage(name,
  524. `FROM busybox
  525. RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  526. USER dockerio
  527. RUN [ $(whoami) = 'dockerio' ]`,
  528. true)
  529. if err != nil {
  530. t.Fatal(err)
  531. }
  532. res, err := inspectField(name, "Config.User")
  533. if err != nil {
  534. t.Fatal(err)
  535. }
  536. if res != expected {
  537. t.Fatalf("User %s, expected %s", res, expected)
  538. }
  539. logDone("build - user")
  540. }
  541. func TestBuildRelativeWorkdir(t *testing.T) {
  542. name := "testbuildrelativeworkdir"
  543. expected := "/test2/test3"
  544. defer deleteImages(name)
  545. _, err := buildImage(name,
  546. `FROM busybox
  547. RUN [ "$PWD" = '/' ]
  548. WORKDIR test1
  549. RUN [ "$PWD" = '/test1' ]
  550. WORKDIR /test2
  551. RUN [ "$PWD" = '/test2' ]
  552. WORKDIR test3
  553. RUN [ "$PWD" = '/test2/test3' ]`,
  554. true)
  555. if err != nil {
  556. t.Fatal(err)
  557. }
  558. res, err := inspectField(name, "Config.WorkingDir")
  559. if err != nil {
  560. t.Fatal(err)
  561. }
  562. if res != expected {
  563. t.Fatalf("Workdir %s, expected %s", res, expected)
  564. }
  565. logDone("build - relative workdir")
  566. }
  567. func TestBuildEnv(t *testing.T) {
  568. name := "testbuildenv"
  569. expected := "[HOME=/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  570. defer deleteImages(name)
  571. _, err := buildImage(name,
  572. `FROM busybox
  573. ENV PORT 2375
  574. RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  575. true)
  576. if err != nil {
  577. t.Fatal(err)
  578. }
  579. res, err := inspectField(name, "Config.Env")
  580. if err != nil {
  581. t.Fatal(err)
  582. }
  583. if res != expected {
  584. t.Fatalf("Env %s, expected %s", res, expected)
  585. }
  586. logDone("build - env")
  587. }
  588. func TestBuildCmd(t *testing.T) {
  589. name := "testbuildcmd"
  590. expected := "[/bin/echo Hello World]"
  591. defer deleteImages(name)
  592. _, err := buildImage(name,
  593. `FROM scratch
  594. CMD ["/bin/echo", "Hello World"]`,
  595. true)
  596. if err != nil {
  597. t.Fatal(err)
  598. }
  599. res, err := inspectField(name, "Config.Cmd")
  600. if err != nil {
  601. t.Fatal(err)
  602. }
  603. if res != expected {
  604. t.Fatalf("Cmd %s, expected %s", res, expected)
  605. }
  606. logDone("build - cmd")
  607. }
  608. func TestBuildExpose(t *testing.T) {
  609. name := "testbuildexpose"
  610. expected := "map[2375/tcp:map[]]"
  611. defer deleteImages(name)
  612. _, err := buildImage(name,
  613. `FROM scratch
  614. EXPOSE 2375`,
  615. true)
  616. if err != nil {
  617. t.Fatal(err)
  618. }
  619. res, err := inspectField(name, "Config.ExposedPorts")
  620. if err != nil {
  621. t.Fatal(err)
  622. }
  623. if res != expected {
  624. t.Fatalf("Exposed ports %s, expected %s", res, expected)
  625. }
  626. logDone("build - expose")
  627. }
  628. func TestBuildEntrypoint(t *testing.T) {
  629. name := "testbuildentrypoint"
  630. expected := "[/bin/echo]"
  631. defer deleteImages(name)
  632. _, err := buildImage(name,
  633. `FROM scratch
  634. ENTRYPOINT ["/bin/echo"]`,
  635. true)
  636. if err != nil {
  637. t.Fatal(err)
  638. }
  639. res, err := inspectField(name, "Config.Entrypoint")
  640. if err != nil {
  641. t.Fatal(err)
  642. }
  643. if res != expected {
  644. t.Fatalf("Entrypoint %s, expected %s", res, expected)
  645. }
  646. logDone("build - entrypoint")
  647. }
  648. func TestBuildWithCache(t *testing.T) {
  649. name := "testbuildwithcache"
  650. defer deleteImages(name)
  651. id1, err := buildImage(name,
  652. `FROM scratch
  653. MAINTAINER dockerio
  654. EXPOSE 5432
  655. ENTRYPOINT ["/bin/echo"]`,
  656. true)
  657. if err != nil {
  658. t.Fatal(err)
  659. }
  660. id2, err := buildImage(name,
  661. `FROM scratch
  662. MAINTAINER dockerio
  663. EXPOSE 5432
  664. ENTRYPOINT ["/bin/echo"]`,
  665. true)
  666. if err != nil {
  667. t.Fatal(err)
  668. }
  669. if id1 != id2 {
  670. t.Fatal("The cache should have been used but hasn't.")
  671. }
  672. logDone("build - with cache")
  673. }
  674. func TestBuildWithoutCache(t *testing.T) {
  675. name := "testbuildwithoutcache"
  676. defer deleteImages(name)
  677. id1, err := buildImage(name,
  678. `FROM scratch
  679. MAINTAINER dockerio
  680. EXPOSE 5432
  681. ENTRYPOINT ["/bin/echo"]`,
  682. true)
  683. if err != nil {
  684. t.Fatal(err)
  685. }
  686. id2, err := buildImage(name,
  687. `FROM scratch
  688. MAINTAINER dockerio
  689. EXPOSE 5432
  690. ENTRYPOINT ["/bin/echo"]`,
  691. false)
  692. if err != nil {
  693. t.Fatal(err)
  694. }
  695. if id1 == id2 {
  696. t.Fatal("The cache should have been invalided but hasn't.")
  697. }
  698. logDone("build - without cache")
  699. }
  700. func TestBuildADDLocalFileWithCache(t *testing.T) {
  701. name := "testbuildaddlocalfilewithcache"
  702. defer deleteImages(name)
  703. dockerfile := `
  704. FROM busybox
  705. MAINTAINER dockerio
  706. ADD foo /usr/lib/bla/bar
  707. RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  708. ctx, err := fakeContext(dockerfile, map[string]string{
  709. "foo": "hello",
  710. })
  711. defer ctx.Close()
  712. if err != nil {
  713. t.Fatal(err)
  714. }
  715. id1, err := buildImageFromContext(name, ctx, true)
  716. if err != nil {
  717. t.Fatal(err)
  718. }
  719. id2, err := buildImageFromContext(name, ctx, true)
  720. if err != nil {
  721. t.Fatal(err)
  722. }
  723. if id1 != id2 {
  724. t.Fatal("The cache should have been used but hasn't.")
  725. }
  726. logDone("build - add local file with cache")
  727. }
  728. func TestBuildADDLocalFileWithoutCache(t *testing.T) {
  729. name := "testbuildaddlocalfilewithoutcache"
  730. defer deleteImages(name)
  731. dockerfile := `
  732. FROM busybox
  733. MAINTAINER dockerio
  734. ADD foo /usr/lib/bla/bar
  735. RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  736. ctx, err := fakeContext(dockerfile, map[string]string{
  737. "foo": "hello",
  738. })
  739. defer ctx.Close()
  740. if err != nil {
  741. t.Fatal(err)
  742. }
  743. id1, err := buildImageFromContext(name, ctx, true)
  744. if err != nil {
  745. t.Fatal(err)
  746. }
  747. id2, err := buildImageFromContext(name, ctx, false)
  748. if err != nil {
  749. t.Fatal(err)
  750. }
  751. if id1 == id2 {
  752. t.Fatal("The cache should have been invalided but hasn't.")
  753. }
  754. logDone("build - add local file without cache")
  755. }
  756. func TestBuildADDCurrentDirWithCache(t *testing.T) {
  757. name := "testbuildaddcurrentdirwithcache"
  758. defer deleteImages(name)
  759. dockerfile := `
  760. FROM scratch
  761. MAINTAINER dockerio
  762. ADD . /usr/lib/bla`
  763. ctx, err := fakeContext(dockerfile, map[string]string{
  764. "foo": "hello",
  765. })
  766. defer ctx.Close()
  767. if err != nil {
  768. t.Fatal(err)
  769. }
  770. id1, err := buildImageFromContext(name, ctx, true)
  771. if err != nil {
  772. t.Fatal(err)
  773. }
  774. // Check that adding file invalidate cache of "ADD ."
  775. if err := ctx.Add("bar", "hello2"); err != nil {
  776. t.Fatal(err)
  777. }
  778. id2, err := buildImageFromContext(name, ctx, true)
  779. if err != nil {
  780. t.Fatal(err)
  781. }
  782. if id1 == id2 {
  783. t.Fatal("The cache should have been invalided but hasn't.")
  784. }
  785. // Check that changing file invalidate cache of "ADD ."
  786. if err := ctx.Add("foo", "hello1"); err != nil {
  787. t.Fatal(err)
  788. }
  789. id3, err := buildImageFromContext(name, ctx, true)
  790. if err != nil {
  791. t.Fatal(err)
  792. }
  793. if id2 == id3 {
  794. t.Fatal("The cache should have been invalided but hasn't.")
  795. }
  796. // Check that changing file to same content invalidate cache of "ADD ."
  797. time.Sleep(1 * time.Second) // wait second because of mtime precision
  798. if err := ctx.Add("foo", "hello1"); err != nil {
  799. t.Fatal(err)
  800. }
  801. id4, err := buildImageFromContext(name, ctx, true)
  802. if err != nil {
  803. t.Fatal(err)
  804. }
  805. if id3 == id4 {
  806. t.Fatal("The cache should have been invalided but hasn't.")
  807. }
  808. id5, err := buildImageFromContext(name, ctx, true)
  809. if err != nil {
  810. t.Fatal(err)
  811. }
  812. if id4 != id5 {
  813. t.Fatal("The cache should have been used but hasn't.")
  814. }
  815. logDone("build - add current directory with cache")
  816. }
  817. func TestBuildADDCurrentDirWithoutCache(t *testing.T) {
  818. name := "testbuildaddcurrentdirwithoutcache"
  819. defer deleteImages(name)
  820. dockerfile := `
  821. FROM scratch
  822. MAINTAINER dockerio
  823. ADD . /usr/lib/bla`
  824. ctx, err := fakeContext(dockerfile, map[string]string{
  825. "foo": "hello",
  826. })
  827. defer ctx.Close()
  828. if err != nil {
  829. t.Fatal(err)
  830. }
  831. id1, err := buildImageFromContext(name, ctx, true)
  832. if err != nil {
  833. t.Fatal(err)
  834. }
  835. id2, err := buildImageFromContext(name, ctx, false)
  836. if err != nil {
  837. t.Fatal(err)
  838. }
  839. if id1 == id2 {
  840. t.Fatal("The cache should have been invalided but hasn't.")
  841. }
  842. logDone("build - add current directory without cache")
  843. }
  844. func TestBuildADDRemoteFileWithCache(t *testing.T) {
  845. name := "testbuildaddremotefilewithcache"
  846. defer deleteImages(name)
  847. server, err := fakeStorage(map[string]string{
  848. "baz": "hello",
  849. })
  850. if err != nil {
  851. t.Fatal(err)
  852. }
  853. defer server.Close()
  854. id1, err := buildImage(name,
  855. fmt.Sprintf(`FROM scratch
  856. MAINTAINER dockerio
  857. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  858. true)
  859. if err != nil {
  860. t.Fatal(err)
  861. }
  862. id2, err := buildImage(name,
  863. fmt.Sprintf(`FROM scratch
  864. MAINTAINER dockerio
  865. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  866. true)
  867. if err != nil {
  868. t.Fatal(err)
  869. }
  870. if id1 != id2 {
  871. t.Fatal("The cache should have been used but hasn't.")
  872. }
  873. logDone("build - add remote file with cache")
  874. }
  875. func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
  876. name := "testbuildaddremotefilewithoutcache"
  877. defer deleteImages(name)
  878. server, err := fakeStorage(map[string]string{
  879. "baz": "hello",
  880. })
  881. if err != nil {
  882. t.Fatal(err)
  883. }
  884. defer server.Close()
  885. id1, err := buildImage(name,
  886. fmt.Sprintf(`FROM scratch
  887. MAINTAINER dockerio
  888. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  889. true)
  890. if err != nil {
  891. t.Fatal(err)
  892. }
  893. id2, err := buildImage(name,
  894. fmt.Sprintf(`FROM scratch
  895. MAINTAINER dockerio
  896. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  897. false)
  898. if err != nil {
  899. t.Fatal(err)
  900. }
  901. if id1 == id2 {
  902. t.Fatal("The cache should have been invalided but hasn't.")
  903. }
  904. logDone("build - add remote file without cache")
  905. }
  906. func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
  907. name := "testbuildaddlocalandremotefilewithcache"
  908. defer deleteImages(name)
  909. server, err := fakeStorage(map[string]string{
  910. "baz": "hello",
  911. })
  912. if err != nil {
  913. t.Fatal(err)
  914. }
  915. defer server.Close()
  916. ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  917. MAINTAINER dockerio
  918. ADD foo /usr/lib/bla/bar
  919. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  920. map[string]string{
  921. "foo": "hello world",
  922. })
  923. if err != nil {
  924. t.Fatal(err)
  925. }
  926. defer ctx.Close()
  927. id1, err := buildImageFromContext(name, ctx, true)
  928. if err != nil {
  929. t.Fatal(err)
  930. }
  931. id2, err := buildImageFromContext(name, ctx, true)
  932. if err != nil {
  933. t.Fatal(err)
  934. }
  935. if id1 != id2 {
  936. t.Fatal("The cache should have been used but hasn't.")
  937. }
  938. logDone("build - add local and remote file with cache")
  939. }
  940. // TODO: TestCaching
  941. func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
  942. name := "testbuildaddlocalandremotefilewithoutcache"
  943. defer deleteImages(name)
  944. server, err := fakeStorage(map[string]string{
  945. "baz": "hello",
  946. })
  947. if err != nil {
  948. t.Fatal(err)
  949. }
  950. defer server.Close()
  951. ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  952. MAINTAINER dockerio
  953. ADD foo /usr/lib/bla/bar
  954. ADD %s/baz /usr/lib/baz/quux`, server.URL),
  955. map[string]string{
  956. "foo": "hello world",
  957. })
  958. if err != nil {
  959. t.Fatal(err)
  960. }
  961. defer ctx.Close()
  962. id1, err := buildImageFromContext(name, ctx, true)
  963. if err != nil {
  964. t.Fatal(err)
  965. }
  966. id2, err := buildImageFromContext(name, ctx, false)
  967. if err != nil {
  968. t.Fatal(err)
  969. }
  970. if id1 == id2 {
  971. t.Fatal("The cache should have been invalided but hasn't.")
  972. }
  973. logDone("build - add local and remote file without cache")
  974. }
  975. func TestBuildWithVolumeOwnership(t *testing.T) {
  976. name := "testbuildimg"
  977. defer deleteImages(name)
  978. _, err := buildImage(name,
  979. `FROM busybox:latest
  980. RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  981. VOLUME /test`,
  982. true)
  983. if err != nil {
  984. t.Fatal(err)
  985. }
  986. cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  987. out, _, err := runCommandWithOutput(cmd)
  988. if err != nil {
  989. t.Fatal(err)
  990. }
  991. if expected := "drw-------"; !strings.Contains(out, expected) {
  992. t.Fatalf("expected %s received %s", expected, out)
  993. }
  994. if expected := "daemon daemon"; !strings.Contains(out, expected) {
  995. t.Fatalf("expected %s received %s", expected, out)
  996. }
  997. logDone("build - volume ownership")
  998. }
  999. // testing #1405 - config.Cmd does not get cleaned up if
  1000. // utilizing cache
  1001. func TestBuildEntrypointRunCleanup(t *testing.T) {
  1002. name := "testbuildcmdcleanup"
  1003. defer deleteImages(name)
  1004. if _, err := buildImage(name,
  1005. `FROM busybox
  1006. RUN echo "hello"`,
  1007. true); err != nil {
  1008. t.Fatal(err)
  1009. }
  1010. ctx, err := fakeContext(`FROM busybox
  1011. RUN echo "hello"
  1012. ADD foo /foo
  1013. ENTRYPOINT ["/bin/echo"]`,
  1014. map[string]string{
  1015. "foo": "hello",
  1016. })
  1017. defer ctx.Close()
  1018. if err != nil {
  1019. t.Fatal(err)
  1020. }
  1021. if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1022. t.Fatal(err)
  1023. }
  1024. res, err := inspectField(name, "Config.Cmd")
  1025. if err != nil {
  1026. t.Fatal(err)
  1027. }
  1028. // Cmd inherited from busybox, maybe will be fixed in #5147
  1029. if expected := "[/bin/sh]"; res != expected {
  1030. t.Fatalf("Cmd %s, expected %s", res, expected)
  1031. }
  1032. logDone("build - cleanup cmd after RUN")
  1033. }
  1034. func TestBuldForbiddenContextPath(t *testing.T) {
  1035. name := "testbuildforbidpath"
  1036. defer deleteImages(name)
  1037. ctx, err := fakeContext(`FROM scratch
  1038. ADD ../../ test/
  1039. `,
  1040. map[string]string{
  1041. "test.txt": "test1",
  1042. "other.txt": "other",
  1043. })
  1044. defer ctx.Close()
  1045. if err != nil {
  1046. t.Fatal(err)
  1047. }
  1048. if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1049. if !strings.Contains(err.Error(), "Forbidden path outside the build context: ../../ (/)") {
  1050. t.Fatal("Wrong error, must be about forbidden ../../ path")
  1051. }
  1052. } else {
  1053. t.Fatal("Error must not be nil")
  1054. }
  1055. logDone("build - forbidden context path")
  1056. }
  1057. func TestBuildADDFileNotFound(t *testing.T) {
  1058. name := "testbuildaddnotfound"
  1059. defer deleteImages(name)
  1060. ctx, err := fakeContext(`FROM scratch
  1061. ADD foo /usr/local/bar`,
  1062. map[string]string{"bar": "hello"})
  1063. defer ctx.Close()
  1064. if err != nil {
  1065. t.Fatal(err)
  1066. }
  1067. if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1068. if !strings.Contains(err.Error(), "foo: no such file or directory") {
  1069. t.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  1070. }
  1071. } else {
  1072. t.Fatal("Error must not be nil")
  1073. }
  1074. logDone("build - add file not found")
  1075. }
  1076. func TestBuildInheritance(t *testing.T) {
  1077. name := "testbuildinheritance"
  1078. defer deleteImages(name)
  1079. _, err := buildImage(name,
  1080. `FROM scratch
  1081. EXPOSE 2375`,
  1082. true)
  1083. if err != nil {
  1084. t.Fatal(err)
  1085. }
  1086. ports1, err := inspectField(name, "Config.ExposedPorts")
  1087. if err != nil {
  1088. t.Fatal(err)
  1089. }
  1090. _, err = buildImage(name,
  1091. fmt.Sprintf(`FROM %s
  1092. ENTRYPOINT ["/bin/echo"]`, name),
  1093. true)
  1094. if err != nil {
  1095. t.Fatal(err)
  1096. }
  1097. res, err := inspectField(name, "Config.Entrypoint")
  1098. if err != nil {
  1099. t.Fatal(err)
  1100. }
  1101. if expected := "[/bin/echo]"; res != expected {
  1102. t.Fatalf("Entrypoint %s, expected %s", res, expected)
  1103. }
  1104. ports2, err := inspectField(name, "Config.ExposedPorts")
  1105. if err != nil {
  1106. t.Fatal(err)
  1107. }
  1108. if ports1 != ports2 {
  1109. t.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  1110. }
  1111. logDone("build - inheritance")
  1112. }
  1113. func TestBuildFails(t *testing.T) {
  1114. name := "testbuildfails"
  1115. defer deleteImages(name)
  1116. _, err := buildImage(name,
  1117. `FROM busybox
  1118. RUN sh -c "exit 23"`,
  1119. true)
  1120. if err != nil {
  1121. if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  1122. t.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  1123. }
  1124. } else {
  1125. t.Fatal("Error must not be nil")
  1126. }
  1127. logDone("build - fails")
  1128. }