docker_cli_build_test.go 34 KB

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