docker_cli_build_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. "time"
  10. )
  11. func checkSimpleBuild(t *testing.T, dockerfile, name, inspectFormat, expected string) {
  12. buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  13. buildCmd.Stdin = strings.NewReader(dockerfile)
  14. out, exitCode, err := runCommandWithOutput(buildCmd)
  15. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  16. if err != nil || exitCode != 0 {
  17. t.Fatal("failed to build the image")
  18. }
  19. inspectCmd := exec.Command(dockerBinary, "inspect", "-f", inspectFormat, name)
  20. out, exitCode, err = runCommandWithOutput(inspectCmd)
  21. if err != nil || exitCode != 0 {
  22. t.Fatalf("failed to inspect the image: %s", out)
  23. }
  24. out = strings.TrimSpace(out)
  25. if out != expected {
  26. t.Fatalf("From format %s expected %s, got %s", inspectFormat, expected, out)
  27. }
  28. }
  29. func TestBuildCacheADD(t *testing.T) {
  30. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "1")
  31. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcacheadd1", ".")
  32. buildCmd.Dir = buildDirectory
  33. exitCode, err := runCommand(buildCmd)
  34. errorOut(err, t, fmt.Sprintf("build failed to complete: %v", err))
  35. if err != nil || exitCode != 0 {
  36. t.Fatal("failed to build the image")
  37. }
  38. buildDirectory = filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "2")
  39. buildCmd = exec.Command(dockerBinary, "build", "-t", "testcacheadd2", ".")
  40. buildCmd.Dir = buildDirectory
  41. out, exitCode, err := runCommandWithOutput(buildCmd)
  42. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  43. if err != nil || exitCode != 0 {
  44. t.Fatal("failed to build the image")
  45. }
  46. if strings.Contains(out, "Using cache") {
  47. t.Fatal("2nd build used cache on ADD, it shouldn't")
  48. }
  49. deleteImages("testcacheadd1")
  50. deleteImages("testcacheadd2")
  51. logDone("build - build two images with ADD")
  52. }
  53. func TestBuildSixtySteps(t *testing.T) {
  54. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildSixtySteps")
  55. buildCmd := exec.Command(dockerBinary, "build", "-t", "foobuildsixtysteps", ".")
  56. buildCmd.Dir = buildDirectory
  57. out, exitCode, err := runCommandWithOutput(buildCmd)
  58. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  59. if err != nil || exitCode != 0 {
  60. t.Fatal("failed to build the image")
  61. }
  62. deleteImages("foobuildsixtysteps")
  63. logDone("build - build an image with sixty build steps")
  64. }
  65. func TestAddSingleFileToRoot(t *testing.T) {
  66. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "SingleFileToRoot")
  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. out, exitCode, err := runCommandWithOutput(buildCmd)
  75. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  76. if err != nil || exitCode != 0 {
  77. t.Fatal("failed to build the image")
  78. }
  79. deleteImages("testaddimg")
  80. logDone("build - add single file to root")
  81. }
  82. // Issue #3960: "ADD src ." hangs
  83. func TestAddSingleFileToWorkdir(t *testing.T) {
  84. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "SingleFileToWorkdir")
  85. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  86. if err != nil {
  87. t.Fatal(err)
  88. }
  89. f.Close()
  90. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", ".")
  91. buildCmd.Dir = buildDirectory
  92. done := make(chan error)
  93. go func() {
  94. out, exitCode, err := runCommandWithOutput(buildCmd)
  95. if err != nil || exitCode != 0 {
  96. done <- fmt.Errorf("build failed to complete: %s %v", out, err)
  97. return
  98. }
  99. done <- nil
  100. }()
  101. select {
  102. case <-time.After(5 * time.Second):
  103. if err := buildCmd.Process.Kill(); err != nil {
  104. fmt.Printf("could not kill build (pid=%d): %v\n", buildCmd.Process.Pid, err)
  105. }
  106. t.Fatal("build timed out")
  107. case err := <-done:
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. }
  112. deleteImages("testaddimg")
  113. logDone("build - add single file to workdir")
  114. }
  115. func TestAddSingleFileToExistDir(t *testing.T) {
  116. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  117. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToExistDir")
  118. buildCmd.Dir = buildDirectory
  119. out, exitCode, err := runCommandWithOutput(buildCmd)
  120. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  121. if err != nil || exitCode != 0 {
  122. t.Fatal("failed to build the image")
  123. }
  124. deleteImages("testaddimg")
  125. logDone("build - add single file to existing dir")
  126. }
  127. func TestAddSingleFileToNonExistDir(t *testing.T) {
  128. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  129. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToNonExistDir")
  130. buildCmd.Dir = buildDirectory
  131. out, exitCode, err := runCommandWithOutput(buildCmd)
  132. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  133. if err != nil || exitCode != 0 {
  134. t.Fatal("failed to build the image")
  135. }
  136. deleteImages("testaddimg")
  137. logDone("build - add single file to non-existing dir")
  138. }
  139. func TestAddDirContentToRoot(t *testing.T) {
  140. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  141. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToRoot")
  142. buildCmd.Dir = buildDirectory
  143. out, exitCode, err := runCommandWithOutput(buildCmd)
  144. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  145. if err != nil || exitCode != 0 {
  146. t.Fatal("failed to build the image")
  147. }
  148. deleteImages("testaddimg")
  149. logDone("build - add directory contents to root")
  150. }
  151. func TestAddDirContentToExistDir(t *testing.T) {
  152. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  153. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToExistDir")
  154. buildCmd.Dir = buildDirectory
  155. out, exitCode, err := runCommandWithOutput(buildCmd)
  156. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  157. if err != nil || exitCode != 0 {
  158. t.Fatal("failed to build the image")
  159. }
  160. deleteImages("testaddimg")
  161. logDone("build - add directory contents to existing dir")
  162. }
  163. func TestAddWholeDirToRoot(t *testing.T) {
  164. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd", "WholeDirToRoot")
  165. test_dir := filepath.Join(buildDirectory, "test_dir")
  166. if err := os.MkdirAll(test_dir, 0755); err != nil {
  167. t.Fatal(err)
  168. }
  169. f, err := os.OpenFile(filepath.Join(test_dir, "test_file"), os.O_CREATE, 0644)
  170. if err != nil {
  171. t.Fatal(err)
  172. }
  173. f.Close()
  174. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", ".")
  175. buildCmd.Dir = buildDirectory
  176. out, exitCode, err := runCommandWithOutput(buildCmd)
  177. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  178. if err != nil || exitCode != 0 {
  179. t.Fatal("failed to build the image")
  180. }
  181. deleteImages("testaddimg")
  182. logDone("build - add whole directory to root")
  183. }
  184. func TestAddEtcToRoot(t *testing.T) {
  185. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  186. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "EtcToRoot")
  187. buildCmd.Dir = buildDirectory
  188. out, exitCode, err := runCommandWithOutput(buildCmd)
  189. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  190. if err != nil || exitCode != 0 {
  191. t.Fatal("failed to build the image")
  192. }
  193. deleteImages("testaddimg")
  194. logDone("build - add etc directory to root")
  195. }
  196. func TestCopySingleFileToRoot(t *testing.T) {
  197. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "SingleFileToRoot")
  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. out, exitCode, err := runCommandWithOutput(buildCmd)
  206. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  207. if err != nil || exitCode != 0 {
  208. t.Fatal("failed to build the image")
  209. }
  210. deleteImages("testcopyimg")
  211. logDone("build - copy single file to root")
  212. }
  213. // Issue #3960: "ADD src ." hangs - adapted for COPY
  214. func TestCopySingleFileToWorkdir(t *testing.T) {
  215. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "SingleFileToWorkdir")
  216. f, err := os.OpenFile(filepath.Join(buildDirectory, "test_file"), os.O_CREATE, 0644)
  217. if err != nil {
  218. t.Fatal(err)
  219. }
  220. f.Close()
  221. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", ".")
  222. buildCmd.Dir = buildDirectory
  223. done := make(chan error)
  224. go func() {
  225. out, exitCode, err := runCommandWithOutput(buildCmd)
  226. if err != nil || exitCode != 0 {
  227. done <- fmt.Errorf("build failed to complete: %s %v", out, err)
  228. return
  229. }
  230. done <- nil
  231. }()
  232. select {
  233. case <-time.After(5 * time.Second):
  234. if err := buildCmd.Process.Kill(); err != nil {
  235. fmt.Printf("could not kill build (pid=%d): %v\n", buildCmd.Process.Pid, err)
  236. }
  237. t.Fatal("build timed out")
  238. case err := <-done:
  239. if err != nil {
  240. t.Fatal(err)
  241. }
  242. }
  243. deleteImages("testcopyimg")
  244. logDone("build - copy single file to workdir")
  245. }
  246. func TestCopySingleFileToExistDir(t *testing.T) {
  247. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  248. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "SingleFileToExistDir")
  249. buildCmd.Dir = buildDirectory
  250. out, exitCode, err := runCommandWithOutput(buildCmd)
  251. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  252. if err != nil || exitCode != 0 {
  253. t.Fatal("failed to build the image")
  254. }
  255. deleteImages("testcopyimg")
  256. logDone("build - add single file to existing dir")
  257. }
  258. func TestCopySingleFileToNonExistDir(t *testing.T) {
  259. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  260. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "SingleFileToNonExistDir")
  261. buildCmd.Dir = buildDirectory
  262. out, exitCode, err := runCommandWithOutput(buildCmd)
  263. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  264. if err != nil || exitCode != 0 {
  265. t.Fatal("failed to build the image")
  266. }
  267. deleteImages("testcopyimg")
  268. logDone("build - copy single file to non-existing dir")
  269. }
  270. func TestCopyDirContentToRoot(t *testing.T) {
  271. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  272. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DirContentToRoot")
  273. buildCmd.Dir = buildDirectory
  274. out, exitCode, err := runCommandWithOutput(buildCmd)
  275. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  276. if err != nil || exitCode != 0 {
  277. t.Fatal("failed to build the image")
  278. }
  279. deleteImages("testcopyimg")
  280. logDone("build - copy directory contents to root")
  281. }
  282. func TestCopyDirContentToExistDir(t *testing.T) {
  283. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  284. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DirContentToExistDir")
  285. buildCmd.Dir = buildDirectory
  286. out, exitCode, err := runCommandWithOutput(buildCmd)
  287. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  288. if err != nil || exitCode != 0 {
  289. t.Fatal("failed to build the image")
  290. }
  291. deleteImages("testcopyimg")
  292. logDone("build - copy directory contents to existing dir")
  293. }
  294. func TestCopyWholeDirToRoot(t *testing.T) {
  295. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy", "WholeDirToRoot")
  296. test_dir := filepath.Join(buildDirectory, "test_dir")
  297. if err := os.MkdirAll(test_dir, 0755); err != nil {
  298. t.Fatal(err)
  299. }
  300. f, err := os.OpenFile(filepath.Join(test_dir, "test_file"), os.O_CREATE, 0644)
  301. if err != nil {
  302. t.Fatal(err)
  303. }
  304. f.Close()
  305. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", ".")
  306. buildCmd.Dir = buildDirectory
  307. out, exitCode, err := runCommandWithOutput(buildCmd)
  308. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  309. if err != nil || exitCode != 0 {
  310. t.Fatal("failed to build the image")
  311. }
  312. deleteImages("testcopyimg")
  313. logDone("build - copy whole directory to root")
  314. }
  315. func TestCopyEtcToRoot(t *testing.T) {
  316. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  317. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "EtcToRoot")
  318. buildCmd.Dir = buildDirectory
  319. out, exitCode, err := runCommandWithOutput(buildCmd)
  320. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  321. if err != nil || exitCode != 0 {
  322. t.Fatal("failed to build the image")
  323. }
  324. deleteImages("testcopyimg")
  325. logDone("build - copy etc directory to root")
  326. }
  327. func TestCopyDisallowRemote(t *testing.T) {
  328. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestCopy")
  329. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcopyimg", "DisallowRemote")
  330. buildCmd.Dir = buildDirectory
  331. out, exitCode, err := runCommandWithOutput(buildCmd)
  332. if err == nil || exitCode == 0 {
  333. t.Fatalf("building the image should've failed; output: %s", out)
  334. }
  335. deleteImages("testcopyimg")
  336. logDone("build - copy - disallow copy from remote")
  337. }
  338. // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  339. // when we can't access files in the context.
  340. func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  341. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildWithInaccessibleFilesInContext")
  342. {
  343. // This is used to ensure we detect inaccessible files early during build in the cli client
  344. pathToInaccessibleFileBuildDirectory := filepath.Join(buildDirectory, "inaccessiblefile")
  345. pathToFileWithoutReadAccess := filepath.Join(pathToInaccessibleFileBuildDirectory, "fileWithoutReadAccess")
  346. err := os.Chown(pathToFileWithoutReadAccess, 0, 0)
  347. errorOut(err, t, fmt.Sprintf("failed to chown file to root: %s", err))
  348. err = os.Chmod(pathToFileWithoutReadAccess, 0700)
  349. errorOut(err, t, fmt.Sprintf("failed to chmod file to 700: %s", err))
  350. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  351. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  352. buildCmd.Dir = pathToInaccessibleFileBuildDirectory
  353. out, exitCode, err := runCommandWithOutput(buildCmd)
  354. if err == nil || exitCode == 0 {
  355. t.Fatalf("build should have failed: %s %s", err, out)
  356. }
  357. // check if we've detected the failure before we started building
  358. if !strings.Contains(out, "no permission to read from ") {
  359. t.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  360. }
  361. if !strings.Contains(out, "Error checking context is accessible") {
  362. t.Fatalf("output should've contained the string: Error checking context is accessible")
  363. }
  364. }
  365. {
  366. // This is used to ensure we detect inaccessible directories early during build in the cli client
  367. pathToInaccessibleDirectoryBuildDirectory := filepath.Join(buildDirectory, "inaccessibledirectory")
  368. pathToDirectoryWithoutReadAccess := filepath.Join(pathToInaccessibleDirectoryBuildDirectory, "directoryWeCantStat")
  369. pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  370. err := os.Chown(pathToDirectoryWithoutReadAccess, 0, 0)
  371. errorOut(err, t, fmt.Sprintf("failed to chown directory to root: %s", err))
  372. err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444)
  373. errorOut(err, t, fmt.Sprintf("failed to chmod directory to 755: %s", err))
  374. err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700)
  375. errorOut(err, t, fmt.Sprintf("failed to chmod file to 444: %s", err))
  376. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  377. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  378. buildCmd.Dir = pathToInaccessibleDirectoryBuildDirectory
  379. out, exitCode, err := runCommandWithOutput(buildCmd)
  380. if err == nil || exitCode == 0 {
  381. t.Fatalf("build should have failed: %s %s", err, out)
  382. }
  383. // check if we've detected the failure before we started building
  384. if !strings.Contains(out, "can't stat") {
  385. t.Fatalf("output should've contained the string: can't access %s", out)
  386. }
  387. if !strings.Contains(out, "Error checking context is accessible") {
  388. t.Fatalf("output should've contained the string: Error checking context is accessible")
  389. }
  390. }
  391. {
  392. // This is used to ensure we don't follow links when checking if everything in the context is accessible
  393. // This test doesn't require that we run commands as an unprivileged user
  394. pathToDirectoryWhichContainsLinks := filepath.Join(buildDirectory, "linksdirectory")
  395. buildCmd := exec.Command(dockerBinary, "build", "-t", "testlinksok", ".")
  396. buildCmd.Dir = pathToDirectoryWhichContainsLinks
  397. out, exitCode, err := runCommandWithOutput(buildCmd)
  398. if err != nil || exitCode != 0 {
  399. t.Fatalf("build should have worked: %s %s", err, out)
  400. }
  401. deleteImages("testlinksok")
  402. }
  403. deleteImages("inaccessiblefiles")
  404. logDone("build - ADD from context with inaccessible files must fail")
  405. logDone("build - ADD from context with accessible links must work")
  406. }
  407. func TestBuildForceRm(t *testing.T) {
  408. containerCountBefore, err := getContainerCount()
  409. if err != nil {
  410. t.Fatalf("failed to get the container count: %s", err)
  411. }
  412. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildForceRm")
  413. buildCmd := exec.Command(dockerBinary, "build", "--force-rm", ".")
  414. buildCmd.Dir = buildDirectory
  415. _, exitCode, err := runCommandWithOutput(buildCmd)
  416. if err == nil || exitCode == 0 {
  417. t.Fatal("failed to build the image")
  418. }
  419. containerCountAfter, err := getContainerCount()
  420. if err != nil {
  421. t.Fatalf("failed to get the container count: %s", err)
  422. }
  423. if containerCountBefore != containerCountAfter {
  424. t.Fatalf("--force-rm shouldn't have left containers behind")
  425. }
  426. logDone("build - ensure --force-rm doesn't leave containers behind")
  427. }
  428. func TestBuildRm(t *testing.T) {
  429. {
  430. containerCountBefore, err := getContainerCount()
  431. if err != nil {
  432. t.Fatalf("failed to get the container count: %s", err)
  433. }
  434. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  435. buildCmd := exec.Command(dockerBinary, "build", "--rm", "-t", "testbuildrm", ".")
  436. buildCmd.Dir = buildDirectory
  437. _, exitCode, err := runCommandWithOutput(buildCmd)
  438. if err != nil || exitCode != 0 {
  439. t.Fatal("failed to build the image")
  440. }
  441. containerCountAfter, err := getContainerCount()
  442. if err != nil {
  443. t.Fatalf("failed to get the container count: %s", err)
  444. }
  445. if containerCountBefore != containerCountAfter {
  446. t.Fatalf("-rm shouldn't have left containers behind")
  447. }
  448. deleteImages("testbuildrm")
  449. }
  450. {
  451. containerCountBefore, err := getContainerCount()
  452. if err != nil {
  453. t.Fatalf("failed to get the container count: %s", err)
  454. }
  455. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  456. buildCmd := exec.Command(dockerBinary, "build", "-t", "testbuildrm", ".")
  457. buildCmd.Dir = buildDirectory
  458. _, exitCode, err := runCommandWithOutput(buildCmd)
  459. if err != nil || exitCode != 0 {
  460. t.Fatal("failed to build the image")
  461. }
  462. containerCountAfter, err := getContainerCount()
  463. if err != nil {
  464. t.Fatalf("failed to get the container count: %s", err)
  465. }
  466. if containerCountBefore != containerCountAfter {
  467. t.Fatalf("--rm shouldn't have left containers behind")
  468. }
  469. deleteImages("testbuildrm")
  470. }
  471. {
  472. containerCountBefore, err := getContainerCount()
  473. if err != nil {
  474. t.Fatalf("failed to get the container count: %s", err)
  475. }
  476. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildRm")
  477. buildCmd := exec.Command(dockerBinary, "build", "--rm=false", "-t", "testbuildrm", ".")
  478. buildCmd.Dir = buildDirectory
  479. _, exitCode, err := runCommandWithOutput(buildCmd)
  480. if err != nil || exitCode != 0 {
  481. t.Fatal("failed to build the image")
  482. }
  483. containerCountAfter, err := getContainerCount()
  484. if err != nil {
  485. t.Fatalf("failed to get the container count: %s", err)
  486. }
  487. if containerCountBefore == containerCountAfter {
  488. t.Fatalf("--rm=false should have left containers behind")
  489. }
  490. deleteAllContainers()
  491. deleteImages("testbuildrm")
  492. }
  493. logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
  494. logDone("build - ensure --rm=false overrides the default")
  495. }
  496. func TestBuildWithVolume(t *testing.T) {
  497. checkSimpleBuild(t,
  498. `
  499. FROM scratch
  500. VOLUME /test
  501. `,
  502. "testbuildimg",
  503. "{{json .config.Volumes}}",
  504. `{"/test":{}}`)
  505. deleteImages("testbuildimg")
  506. logDone("build - with volume")
  507. }
  508. func TestBuildMaintainer(t *testing.T) {
  509. checkSimpleBuild(t,
  510. `
  511. FROM scratch
  512. MAINTAINER dockerio
  513. `,
  514. "testbuildimg",
  515. "{{json .author}}",
  516. `"dockerio"`)
  517. deleteImages("testbuildimg")
  518. logDone("build - maintainer")
  519. }
  520. func TestBuildUser(t *testing.T) {
  521. checkSimpleBuild(t,
  522. `
  523. FROM busybox
  524. RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  525. USER dockerio
  526. RUN [ $(whoami) = 'dockerio' ]
  527. `,
  528. "testbuildimg",
  529. "{{json .config.User}}",
  530. `"dockerio"`)
  531. deleteImages("testbuildimg")
  532. logDone("build - user")
  533. }
  534. func TestBuildRelativeWorkdir(t *testing.T) {
  535. checkSimpleBuild(t,
  536. `
  537. FROM busybox
  538. RUN [ "$PWD" = '/' ]
  539. WORKDIR test1
  540. RUN [ "$PWD" = '/test1' ]
  541. WORKDIR /test2
  542. RUN [ "$PWD" = '/test2' ]
  543. WORKDIR test3
  544. RUN [ "$PWD" = '/test2/test3' ]
  545. `,
  546. "testbuildimg",
  547. "{{json .config.WorkingDir}}",
  548. `"/test2/test3"`)
  549. deleteImages("testbuildimg")
  550. logDone("build - relative workdir")
  551. }
  552. func TestBuildEnv(t *testing.T) {
  553. checkSimpleBuild(t,
  554. `
  555. FROM busybox
  556. ENV PORT 4243
  557. RUN [ $(env | grep PORT) = 'PORT=4243' ]
  558. `,
  559. "testbuildimg",
  560. "{{json .config.Env}}",
  561. `["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PORT=4243"]`)
  562. deleteImages("testbuildimg")
  563. logDone("build - env")
  564. }
  565. func TestBuildCmd(t *testing.T) {
  566. checkSimpleBuild(t,
  567. `
  568. FROM scratch
  569. CMD ["/bin/echo", "Hello World"]
  570. `,
  571. "testbuildimg",
  572. "{{json .config.Cmd}}",
  573. `["/bin/echo","Hello World"]`)
  574. deleteImages("testbuildimg")
  575. logDone("build - cmd")
  576. }
  577. func TestBuildExpose(t *testing.T) {
  578. checkSimpleBuild(t,
  579. `
  580. FROM scratch
  581. EXPOSE 4243
  582. `,
  583. "testbuildimg",
  584. "{{json .config.ExposedPorts}}",
  585. `{"4243/tcp":{}}`)
  586. deleteImages("testbuildimg")
  587. logDone("build - expose")
  588. }
  589. func TestBuildEntrypoint(t *testing.T) {
  590. checkSimpleBuild(t,
  591. `
  592. FROM scratch
  593. ENTRYPOINT ["/bin/echo"]
  594. `,
  595. "testbuildimg",
  596. "{{json .config.Entrypoint}}",
  597. `["/bin/echo"]`)
  598. deleteImages("testbuildimg")
  599. logDone("build - entrypoint")
  600. }
  601. // TODO: TestCaching
  602. // TODO: TestADDCacheInvalidation