docker_cli_build_test.go 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  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. }