docker_cli_run_test.go 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "reflect"
  10. "regexp"
  11. "sort"
  12. "strings"
  13. "sync"
  14. "testing"
  15. "time"
  16. "github.com/docker/docker/pkg/mount"
  17. "github.com/docker/docker/pkg/networkfs/resolvconf"
  18. )
  19. // "test123" should be printed by docker run
  20. func TestDockerRunEchoStdout(t *testing.T) {
  21. runCmd := exec.Command(dockerBinary, "run", "busybox", "echo", "test123")
  22. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  23. errorOut(err, t, out)
  24. if out != "test123\n" {
  25. t.Errorf("container should've printed 'test123'")
  26. }
  27. deleteAllContainers()
  28. logDone("run - echo test123")
  29. }
  30. // "test" should be printed
  31. func TestDockerRunEchoStdoutWithMemoryLimit(t *testing.T) {
  32. runCmd := exec.Command(dockerBinary, "run", "-m", "2786432", "busybox", "echo", "test")
  33. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  34. errorOut(err, t, out)
  35. if out != "test\n" {
  36. t.Errorf("container should've printed 'test'")
  37. }
  38. deleteAllContainers()
  39. logDone("run - echo with memory limit")
  40. }
  41. // "test" should be printed
  42. func TestDockerRunEchoStdoutWitCPULimit(t *testing.T) {
  43. runCmd := exec.Command(dockerBinary, "run", "-c", "1000", "busybox", "echo", "test")
  44. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  45. errorOut(err, t, out)
  46. if out != "test\n" {
  47. t.Errorf("container should've printed 'test'")
  48. }
  49. deleteAllContainers()
  50. logDone("run - echo with CPU limit")
  51. }
  52. // "test" should be printed
  53. func TestDockerRunEchoStdoutWithCPUAndMemoryLimit(t *testing.T) {
  54. runCmd := exec.Command(dockerBinary, "run", "-c", "1000", "-m", "2786432", "busybox", "echo", "test")
  55. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  56. errorOut(err, t, out)
  57. if out != "test\n" {
  58. t.Errorf("container should've printed 'test'")
  59. }
  60. deleteAllContainers()
  61. logDone("run - echo with CPU and memory limit")
  62. }
  63. // "test" should be printed
  64. func TestDockerRunEchoNamedContainer(t *testing.T) {
  65. runCmd := exec.Command(dockerBinary, "run", "--name", "testfoonamedcontainer", "busybox", "echo", "test")
  66. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  67. errorOut(err, t, out)
  68. if out != "test\n" {
  69. t.Errorf("container should've printed 'test'")
  70. }
  71. if err := deleteContainer("testfoonamedcontainer"); err != nil {
  72. t.Errorf("failed to remove the named container: %v", err)
  73. }
  74. deleteAllContainers()
  75. logDone("run - echo with named container")
  76. }
  77. // docker run should not leak file descriptors
  78. func TestDockerRunLeakyFileDescriptors(t *testing.T) {
  79. runCmd := exec.Command(dockerBinary, "run", "busybox", "ls", "-C", "/proc/self/fd")
  80. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  81. errorOut(err, t, out)
  82. // normally, we should only get 0, 1, and 2, but 3 gets created by "ls" when it does "opendir" on the "fd" directory
  83. if out != "0 1 2 3\n" {
  84. t.Errorf("container should've printed '0 1 2 3', not: %s", out)
  85. }
  86. deleteAllContainers()
  87. logDone("run - check file descriptor leakage")
  88. }
  89. // it should be possible to ping Google DNS resolver
  90. // this will fail when Internet access is unavailable
  91. func TestDockerRunPingGoogle(t *testing.T) {
  92. runCmd := exec.Command(dockerBinary, "run", "busybox", "ping", "-c", "1", "8.8.8.8")
  93. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  94. errorOut(err, t, out)
  95. errorOut(err, t, "container should've been able to ping 8.8.8.8")
  96. deleteAllContainers()
  97. logDone("run - ping 8.8.8.8")
  98. }
  99. // the exit code should be 0
  100. // some versions of lxc might make this test fail
  101. func TestDockerRunExitCodeZero(t *testing.T) {
  102. runCmd := exec.Command(dockerBinary, "run", "busybox", "true")
  103. exitCode, err := runCommand(runCmd)
  104. errorOut(err, t, fmt.Sprintf("%s", err))
  105. if exitCode != 0 {
  106. t.Errorf("container should've exited with exit code 0")
  107. }
  108. deleteAllContainers()
  109. logDone("run - exit with 0")
  110. }
  111. // the exit code should be 1
  112. // some versions of lxc might make this test fail
  113. func TestDockerRunExitCodeOne(t *testing.T) {
  114. runCmd := exec.Command(dockerBinary, "run", "busybox", "false")
  115. exitCode, err := runCommand(runCmd)
  116. if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) {
  117. t.Fatal(err)
  118. }
  119. if exitCode != 1 {
  120. t.Errorf("container should've exited with exit code 1")
  121. }
  122. deleteAllContainers()
  123. logDone("run - exit with 1")
  124. }
  125. // it should be possible to pipe in data via stdin to a process running in a container
  126. // some versions of lxc might make this test fail
  127. func TestRunStdinPipe(t *testing.T) {
  128. runCmd := exec.Command("bash", "-c", `echo "blahblah" | docker run -i -a stdin busybox cat`)
  129. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  130. errorOut(err, t, out)
  131. out = stripTrailingCharacters(out)
  132. inspectCmd := exec.Command(dockerBinary, "inspect", out)
  133. inspectOut, _, err := runCommandWithOutput(inspectCmd)
  134. errorOut(err, t, fmt.Sprintf("out should've been a container id: %s %s", out, inspectOut))
  135. waitCmd := exec.Command(dockerBinary, "wait", out)
  136. _, _, err = runCommandWithOutput(waitCmd)
  137. errorOut(err, t, fmt.Sprintf("error thrown while waiting for container: %s", out))
  138. logsCmd := exec.Command(dockerBinary, "logs", out)
  139. containerLogs, _, err := runCommandWithOutput(logsCmd)
  140. errorOut(err, t, fmt.Sprintf("error thrown while trying to get container logs: %s", err))
  141. containerLogs = stripTrailingCharacters(containerLogs)
  142. if containerLogs != "blahblah" {
  143. t.Errorf("logs didn't print the container's logs %s", containerLogs)
  144. }
  145. rmCmd := exec.Command(dockerBinary, "rm", out)
  146. _, _, err = runCommandWithOutput(rmCmd)
  147. errorOut(err, t, fmt.Sprintf("rm failed to remove container %s", err))
  148. deleteAllContainers()
  149. logDone("run - pipe in with -i -a stdin")
  150. }
  151. // the container's ID should be printed when starting a container in detached mode
  152. func TestDockerRunDetachedContainerIDPrinting(t *testing.T) {
  153. runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
  154. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  155. errorOut(err, t, out)
  156. out = stripTrailingCharacters(out)
  157. inspectCmd := exec.Command(dockerBinary, "inspect", out)
  158. inspectOut, _, err := runCommandWithOutput(inspectCmd)
  159. errorOut(err, t, fmt.Sprintf("out should've been a container id: %s %s", out, inspectOut))
  160. waitCmd := exec.Command(dockerBinary, "wait", out)
  161. _, _, err = runCommandWithOutput(waitCmd)
  162. errorOut(err, t, fmt.Sprintf("error thrown while waiting for container: %s", out))
  163. rmCmd := exec.Command(dockerBinary, "rm", out)
  164. rmOut, _, err := runCommandWithOutput(rmCmd)
  165. errorOut(err, t, "rm failed to remove container")
  166. rmOut = stripTrailingCharacters(rmOut)
  167. if rmOut != out {
  168. t.Errorf("rm didn't print the container ID %s %s", out, rmOut)
  169. }
  170. deleteAllContainers()
  171. logDone("run - print container ID in detached mode")
  172. }
  173. // the working directory should be set correctly
  174. func TestDockerRunWorkingDirectory(t *testing.T) {
  175. runCmd := exec.Command(dockerBinary, "run", "-w", "/root", "busybox", "pwd")
  176. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  177. errorOut(err, t, out)
  178. out = stripTrailingCharacters(out)
  179. if out != "/root" {
  180. t.Errorf("-w failed to set working directory")
  181. }
  182. runCmd = exec.Command(dockerBinary, "run", "--workdir", "/root", "busybox", "pwd")
  183. out, _, _, err = runCommandWithStdoutStderr(runCmd)
  184. errorOut(err, t, out)
  185. out = stripTrailingCharacters(out)
  186. if out != "/root" {
  187. t.Errorf("--workdir failed to set working directory")
  188. }
  189. deleteAllContainers()
  190. logDone("run - run with working directory set by -w")
  191. logDone("run - run with working directory set by --workdir")
  192. }
  193. // pinging Google's DNS resolver should fail when we disable the networking
  194. func TestDockerRunWithoutNetworking(t *testing.T) {
  195. runCmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ping", "-c", "1", "8.8.8.8")
  196. out, _, exitCode, err := runCommandWithStdoutStderr(runCmd)
  197. if err != nil && exitCode != 1 {
  198. t.Fatal(out, err)
  199. }
  200. if exitCode != 1 {
  201. t.Errorf("--net=none should've disabled the network; the container shouldn't have been able to ping 8.8.8.8")
  202. }
  203. runCmd = exec.Command(dockerBinary, "run", "-n=false", "busybox", "ping", "-c", "1", "8.8.8.8")
  204. out, _, exitCode, err = runCommandWithStdoutStderr(runCmd)
  205. if err != nil && exitCode != 1 {
  206. t.Fatal(out, err)
  207. }
  208. if exitCode != 1 {
  209. t.Errorf("-n=false should've disabled the network; the container shouldn't have been able to ping 8.8.8.8")
  210. }
  211. deleteAllContainers()
  212. logDone("run - disable networking with --net=none")
  213. logDone("run - disable networking with -n=false")
  214. }
  215. // Regression test for #4741
  216. func TestDockerRunWithVolumesAsFiles(t *testing.T) {
  217. runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", "/etc/hosts:/target-file", "busybox", "true")
  218. out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd)
  219. if err != nil && exitCode != 0 {
  220. t.Fatal("1", out, stderr, err)
  221. }
  222. runCmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-data", "busybox", "cat", "/target-file")
  223. out, stderr, exitCode, err = runCommandWithStdoutStderr(runCmd)
  224. if err != nil && exitCode != 0 {
  225. t.Fatal("2", out, stderr, err)
  226. }
  227. deleteAllContainers()
  228. logDone("run - regression test for #4741 - volumes from as files")
  229. }
  230. // Regression test for #4979
  231. func TestDockerRunWithVolumesFromExited(t *testing.T) {
  232. runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file")
  233. out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd)
  234. if err != nil && exitCode != 0 {
  235. t.Fatal("1", out, stderr, err)
  236. }
  237. runCmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file")
  238. out, stderr, exitCode, err = runCommandWithStdoutStderr(runCmd)
  239. if err != nil && exitCode != 0 {
  240. t.Fatal("2", out, stderr, err)
  241. }
  242. deleteAllContainers()
  243. logDone("run - regression test for #4979 - volumes-from on exited container")
  244. }
  245. // Regression test for #4830
  246. func TestDockerRunWithRelativePath(t *testing.T) {
  247. runCmd := exec.Command(dockerBinary, "run", "-v", "tmp:/other-tmp", "busybox", "true")
  248. if _, _, _, err := runCommandWithStdoutStderr(runCmd); err == nil {
  249. t.Fatalf("relative path should result in an error")
  250. }
  251. deleteAllContainers()
  252. logDone("run - volume with relative path")
  253. }
  254. func TestVolumesMountedAsReadonly(t *testing.T) {
  255. cmd := exec.Command(dockerBinary, "run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile")
  256. if code, err := runCommand(cmd); err == nil || code == 0 {
  257. t.Fatalf("run should fail because volume is ro: exit code %d", code)
  258. }
  259. deleteAllContainers()
  260. logDone("run - volumes as readonly mount")
  261. }
  262. func TestVolumesFromInReadonlyMode(t *testing.T) {
  263. cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true")
  264. if _, err := runCommand(cmd); err != nil {
  265. t.Fatal(err)
  266. }
  267. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:ro", "busybox", "touch", "/test/file")
  268. if code, err := runCommand(cmd); err == nil || code == 0 {
  269. t.Fatalf("run should fail because volume is ro: exit code %d", code)
  270. }
  271. deleteAllContainers()
  272. logDone("run - volumes from as readonly mount")
  273. }
  274. // Regression test for #1201
  275. func TestVolumesFromInReadWriteMode(t *testing.T) {
  276. cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true")
  277. if _, err := runCommand(cmd); err != nil {
  278. t.Fatal(err)
  279. }
  280. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "busybox", "touch", "/test/file")
  281. if _, err := runCommand(cmd); err != nil {
  282. t.Fatal(err)
  283. }
  284. deleteAllContainers()
  285. logDone("run - volumes from as read write mount")
  286. }
  287. func TestVolumesFromInheritsReadOnly(t *testing.T) {
  288. cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true")
  289. if _, err := runCommand(cmd); err != nil {
  290. t.Fatal(err)
  291. }
  292. // Expect this "rw" mode to be be ignored since the inheritted volume is "ro"
  293. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file")
  294. if _, err := runCommand(cmd); err == nil {
  295. t.Fatal("Expected to inherit read-only volume even when passing in `rw`")
  296. }
  297. deleteAllContainers()
  298. logDone("run - volumes from ignores `rw` if inherrited volume is `ro`")
  299. }
  300. // Test for #1351
  301. func TestApplyVolumesFromBeforeVolumes(t *testing.T) {
  302. cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "touch", "/test/foo")
  303. if _, err := runCommand(cmd); err != nil {
  304. t.Fatal(err)
  305. }
  306. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "-v", "/test", "busybox", "cat", "/test/foo")
  307. if _, err := runCommand(cmd); err != nil {
  308. t.Fatal(err)
  309. }
  310. deleteAllContainers()
  311. logDone("run - volumes from mounted first")
  312. }
  313. func TestMultipleVolumesFrom(t *testing.T) {
  314. cmd := exec.Command(dockerBinary, "run", "--name", "parent1", "-v", "/test", "busybox", "touch", "/test/foo")
  315. if _, err := runCommand(cmd); err != nil {
  316. t.Fatal(err)
  317. }
  318. cmd = exec.Command(dockerBinary, "run", "--name", "parent2", "-v", "/other", "busybox", "touch", "/other/bar")
  319. if _, err := runCommand(cmd); err != nil {
  320. t.Fatal(err)
  321. }
  322. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent1", "--volumes-from", "parent2",
  323. "busybox", "sh", "-c", "cat /test/foo && cat /other/bar")
  324. if _, err := runCommand(cmd); err != nil {
  325. t.Fatal(err)
  326. }
  327. deleteAllContainers()
  328. logDone("run - multiple volumes from")
  329. }
  330. // this tests verifies the ID format for the container
  331. func TestVerifyContainerID(t *testing.T) {
  332. cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
  333. out, exit, err := runCommandWithOutput(cmd)
  334. if err != nil {
  335. t.Fatal(err)
  336. }
  337. if exit != 0 {
  338. t.Fatalf("expected exit code 0 received %d", exit)
  339. }
  340. match, err := regexp.MatchString("^[0-9a-f]{64}$", strings.TrimSuffix(out, "\n"))
  341. if err != nil {
  342. t.Fatal(err)
  343. }
  344. if !match {
  345. t.Fatalf("Invalid container ID: %s", out)
  346. }
  347. deleteAllContainers()
  348. logDone("run - verify container ID")
  349. }
  350. // Test that creating a container with a volume doesn't crash. Regression test for #995.
  351. func TestCreateVolume(t *testing.T) {
  352. cmd := exec.Command(dockerBinary, "run", "-v", "/var/lib/data", "busybox", "true")
  353. if _, err := runCommand(cmd); err != nil {
  354. t.Fatal(err)
  355. }
  356. deleteAllContainers()
  357. logDone("run - create docker managed volume")
  358. }
  359. // Test that creating a volume with a symlink in its path works correctly. Test for #5152.
  360. // Note that this bug happens only with symlinks with a target that starts with '/'.
  361. func TestCreateVolumeWithSymlink(t *testing.T) {
  362. buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-createvolumewithsymlink", "-")
  363. buildCmd.Stdin = strings.NewReader(`FROM busybox
  364. RUN mkdir /foo && ln -s /foo /bar`)
  365. buildCmd.Dir = workingDirectory
  366. err := buildCmd.Run()
  367. if err != nil {
  368. t.Fatalf("could not build 'docker-test-createvolumewithsymlink': %v", err)
  369. }
  370. cmd := exec.Command(dockerBinary, "run", "-v", "/bar/foo", "--name", "test-createvolumewithsymlink", "docker-test-createvolumewithsymlink", "sh", "-c", "mount | grep -q /foo/foo")
  371. exitCode, err := runCommand(cmd)
  372. if err != nil || exitCode != 0 {
  373. t.Fatalf("[run] err: %v, exitcode: %d", err, exitCode)
  374. }
  375. var volPath string
  376. cmd = exec.Command(dockerBinary, "inspect", "-f", "{{range .Volumes}}{{.}}{{end}}", "test-createvolumewithsymlink")
  377. volPath, exitCode, err = runCommandWithOutput(cmd)
  378. if err != nil || exitCode != 0 {
  379. t.Fatalf("[inspect] err: %v, exitcode: %d", err, exitCode)
  380. }
  381. cmd = exec.Command(dockerBinary, "rm", "-v", "test-createvolumewithsymlink")
  382. exitCode, err = runCommand(cmd)
  383. if err != nil || exitCode != 0 {
  384. t.Fatalf("[rm] err: %v, exitcode: %d", err, exitCode)
  385. }
  386. f, err := os.Open(volPath)
  387. defer f.Close()
  388. if !os.IsNotExist(err) {
  389. t.Fatalf("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath)
  390. }
  391. deleteImages("docker-test-createvolumewithsymlink")
  392. deleteAllContainers()
  393. logDone("run - create volume with symlink")
  394. }
  395. // Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`.
  396. func TestVolumesFromSymlinkPath(t *testing.T) {
  397. buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-volumesfromsymlinkpath", "-")
  398. buildCmd.Stdin = strings.NewReader(`FROM busybox
  399. RUN mkdir /baz && ln -s /baz /foo
  400. VOLUME ["/foo/bar"]`)
  401. buildCmd.Dir = workingDirectory
  402. err := buildCmd.Run()
  403. if err != nil {
  404. t.Fatalf("could not build 'docker-test-volumesfromsymlinkpath': %v", err)
  405. }
  406. cmd := exec.Command(dockerBinary, "run", "--name", "test-volumesfromsymlinkpath", "docker-test-volumesfromsymlinkpath")
  407. exitCode, err := runCommand(cmd)
  408. if err != nil || exitCode != 0 {
  409. t.Fatalf("[run] (volume) err: %v, exitcode: %d", err, exitCode)
  410. }
  411. cmd = exec.Command(dockerBinary, "run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls /foo | grep -q bar")
  412. exitCode, err = runCommand(cmd)
  413. if err != nil || exitCode != 0 {
  414. t.Fatalf("[run] err: %v, exitcode: %d", err, exitCode)
  415. }
  416. deleteImages("docker-test-volumesfromsymlinkpath")
  417. deleteAllContainers()
  418. logDone("run - volumes-from symlink path")
  419. }
  420. func TestExitCode(t *testing.T) {
  421. cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72")
  422. exit, err := runCommand(cmd)
  423. if err == nil {
  424. t.Fatal("should not have a non nil error")
  425. }
  426. if exit != 72 {
  427. t.Fatalf("expected exit code 72 received %d", exit)
  428. }
  429. deleteAllContainers()
  430. logDone("run - correct exit code")
  431. }
  432. func TestUserDefaultsToRoot(t *testing.T) {
  433. cmd := exec.Command(dockerBinary, "run", "busybox", "id")
  434. out, _, err := runCommandWithOutput(cmd)
  435. if err != nil {
  436. t.Fatal(err, out)
  437. }
  438. if !strings.Contains(out, "uid=0(root) gid=0(root)") {
  439. t.Fatalf("expected root user got %s", out)
  440. }
  441. deleteAllContainers()
  442. logDone("run - default user")
  443. }
  444. func TestUserByName(t *testing.T) {
  445. cmd := exec.Command(dockerBinary, "run", "-u", "root", "busybox", "id")
  446. out, _, err := runCommandWithOutput(cmd)
  447. if err != nil {
  448. t.Fatal(err, out)
  449. }
  450. if !strings.Contains(out, "uid=0(root) gid=0(root)") {
  451. t.Fatalf("expected root user got %s", out)
  452. }
  453. deleteAllContainers()
  454. logDone("run - user by name")
  455. }
  456. func TestUserByID(t *testing.T) {
  457. cmd := exec.Command(dockerBinary, "run", "-u", "1", "busybox", "id")
  458. out, _, err := runCommandWithOutput(cmd)
  459. if err != nil {
  460. t.Fatal(err, out)
  461. }
  462. if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") {
  463. t.Fatalf("expected daemon user got %s", out)
  464. }
  465. deleteAllContainers()
  466. logDone("run - user by id")
  467. }
  468. func TestUserByIDBig(t *testing.T) {
  469. cmd := exec.Command(dockerBinary, "run", "-u", "2147483648", "busybox", "id")
  470. out, _, err := runCommandWithOutput(cmd)
  471. if err == nil {
  472. t.Fatal("No error, but must be.", out)
  473. }
  474. if !strings.Contains(out, "Uids and gids must be in range") {
  475. t.Fatalf("expected error about uids range, got %s", out)
  476. }
  477. deleteAllContainers()
  478. logDone("run - user by id, id too big")
  479. }
  480. func TestUserByIDNegative(t *testing.T) {
  481. cmd := exec.Command(dockerBinary, "run", "-u", "-1", "busybox", "id")
  482. out, _, err := runCommandWithOutput(cmd)
  483. if err == nil {
  484. t.Fatal("No error, but must be.", out)
  485. }
  486. if !strings.Contains(out, "Uids and gids must be in range") {
  487. t.Fatalf("expected error about uids range, got %s", out)
  488. }
  489. deleteAllContainers()
  490. logDone("run - user by id, id negative")
  491. }
  492. func TestUserByIDZero(t *testing.T) {
  493. cmd := exec.Command(dockerBinary, "run", "-u", "0", "busybox", "id")
  494. out, _, err := runCommandWithOutput(cmd)
  495. if err != nil {
  496. t.Fatal(err, out)
  497. }
  498. if !strings.Contains(out, "uid=0(root) gid=0(root) groups=10(wheel)") {
  499. t.Fatalf("expected daemon user got %s", out)
  500. }
  501. deleteAllContainers()
  502. logDone("run - user by id, zero uid")
  503. }
  504. func TestUserNotFound(t *testing.T) {
  505. cmd := exec.Command(dockerBinary, "run", "-u", "notme", "busybox", "id")
  506. _, err := runCommand(cmd)
  507. if err == nil {
  508. t.Fatal("unknown user should cause container to fail")
  509. }
  510. deleteAllContainers()
  511. logDone("run - user not found")
  512. }
  513. func TestRunTwoConcurrentContainers(t *testing.T) {
  514. group := sync.WaitGroup{}
  515. group.Add(2)
  516. for i := 0; i < 2; i++ {
  517. go func() {
  518. defer group.Done()
  519. cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2")
  520. if _, err := runCommand(cmd); err != nil {
  521. t.Fatal(err)
  522. }
  523. }()
  524. }
  525. group.Wait()
  526. deleteAllContainers()
  527. logDone("run - two concurrent containers")
  528. }
  529. func TestEnvironment(t *testing.T) {
  530. cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env")
  531. cmd.Env = append(os.Environ(),
  532. "TRUE=false",
  533. "TRICKY=tri\ncky\n",
  534. )
  535. out, _, err := runCommandWithOutput(cmd)
  536. if err != nil {
  537. t.Fatal(err, out)
  538. }
  539. actualEnv := strings.Split(out, "\n")
  540. if actualEnv[len(actualEnv)-1] == "" {
  541. actualEnv = actualEnv[:len(actualEnv)-1]
  542. }
  543. sort.Strings(actualEnv)
  544. goodEnv := []string{
  545. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  546. "HOSTNAME=testing",
  547. "FALSE=true",
  548. "TRUE=false",
  549. "TRICKY=tri",
  550. "cky",
  551. "",
  552. "HOME=/root",
  553. }
  554. sort.Strings(goodEnv)
  555. if len(goodEnv) != len(actualEnv) {
  556. t.Fatalf("Wrong environment: should be %d variables, not: '%s'\n", len(goodEnv), strings.Join(actualEnv, ", "))
  557. }
  558. for i := range goodEnv {
  559. if actualEnv[i] != goodEnv[i] {
  560. t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
  561. }
  562. }
  563. deleteAllContainers()
  564. logDone("run - verify environment")
  565. }
  566. func TestContainerNetwork(t *testing.T) {
  567. cmd := exec.Command(dockerBinary, "run", "busybox", "ping", "-c", "1", "127.0.0.1")
  568. if _, err := runCommand(cmd); err != nil {
  569. t.Fatal(err)
  570. }
  571. deleteAllContainers()
  572. logDone("run - test container network via ping")
  573. }
  574. // Issue #4681
  575. func TestLoopbackWhenNetworkDisabled(t *testing.T) {
  576. cmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ping", "-c", "1", "127.0.0.1")
  577. if _, err := runCommand(cmd); err != nil {
  578. t.Fatal(err)
  579. }
  580. deleteAllContainers()
  581. logDone("run - test container loopback when networking disabled")
  582. }
  583. func TestNetHostNotAllowedWithLinks(t *testing.T) {
  584. _, _, err := cmd(t, "run", "--name", "linked", "busybox", "true")
  585. cmd := exec.Command(dockerBinary, "run", "--net=host", "--link", "linked:linked", "busybox", "true")
  586. _, _, err = runCommandWithOutput(cmd)
  587. if err == nil {
  588. t.Fatal("Expected error")
  589. }
  590. deleteAllContainers()
  591. logDone("run - don't allow --net=host to be used with links")
  592. }
  593. func TestLoopbackOnlyExistsWhenNetworkingDisabled(t *testing.T) {
  594. cmd := exec.Command(dockerBinary, "run", "--net=none", "busybox", "ip", "-o", "-4", "a", "show", "up")
  595. out, _, err := runCommandWithOutput(cmd)
  596. if err != nil {
  597. t.Fatal(err, out)
  598. }
  599. var (
  600. count = 0
  601. parts = strings.Split(out, "\n")
  602. )
  603. for _, l := range parts {
  604. if l != "" {
  605. count++
  606. }
  607. }
  608. if count != 1 {
  609. t.Fatalf("Wrong interface count in container %d", count)
  610. }
  611. if !strings.HasPrefix(out, "1: lo") {
  612. t.Fatalf("Wrong interface in test container: expected [1: lo], got %s", out)
  613. }
  614. deleteAllContainers()
  615. logDone("run - test loopback only exists when networking disabled")
  616. }
  617. func TestPrivilegedCanMknod(t *testing.T) {
  618. cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  619. out, _, err := runCommandWithOutput(cmd)
  620. if err != nil {
  621. t.Fatal(err)
  622. }
  623. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  624. t.Fatalf("expected output ok received %s", actual)
  625. }
  626. deleteAllContainers()
  627. logDone("run - test privileged can mknod")
  628. }
  629. func TestUnPrivilegedCanMknod(t *testing.T) {
  630. cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  631. out, _, err := runCommandWithOutput(cmd)
  632. if err != nil {
  633. t.Fatal(err)
  634. }
  635. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  636. t.Fatalf("expected output ok received %s", actual)
  637. }
  638. deleteAllContainers()
  639. logDone("run - test un-privileged can mknod")
  640. }
  641. func TestCapDropInvalid(t *testing.T) {
  642. cmd := exec.Command(dockerBinary, "run", "--cap-drop=CHPASS", "busybox", "ls")
  643. out, _, err := runCommandWithOutput(cmd)
  644. if err == nil {
  645. t.Fatal(err, out)
  646. }
  647. logDone("run - test --cap-drop=CHPASS invalid")
  648. }
  649. func TestCapDropCannotMknod(t *testing.T) {
  650. cmd := exec.Command(dockerBinary, "run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  651. out, _, err := runCommandWithOutput(cmd)
  652. if err == nil {
  653. t.Fatal(err, out)
  654. }
  655. if actual := strings.Trim(out, "\r\n"); actual == "ok" {
  656. t.Fatalf("expected output not ok received %s", actual)
  657. }
  658. deleteAllContainers()
  659. logDone("run - test --cap-drop=MKNOD cannot mknod")
  660. }
  661. func TestCapDropCannotMknodLowerCase(t *testing.T) {
  662. cmd := exec.Command(dockerBinary, "run", "--cap-drop=mknod", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  663. out, _, err := runCommandWithOutput(cmd)
  664. if err == nil {
  665. t.Fatal(err, out)
  666. }
  667. if actual := strings.Trim(out, "\r\n"); actual == "ok" {
  668. t.Fatalf("expected output not ok received %s", actual)
  669. }
  670. deleteAllContainers()
  671. logDone("run - test --cap-drop=mknod cannot mknod lowercase")
  672. }
  673. func TestCapDropALLCannotMknod(t *testing.T) {
  674. cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  675. out, _, err := runCommandWithOutput(cmd)
  676. if err == nil {
  677. t.Fatal(err, out)
  678. }
  679. if actual := strings.Trim(out, "\r\n"); actual == "ok" {
  680. t.Fatalf("expected output not ok received %s", actual)
  681. }
  682. deleteAllContainers()
  683. logDone("run - test --cap-drop=ALL cannot mknod")
  684. }
  685. func TestCapDropALLAddMknodCannotMknod(t *testing.T) {
  686. cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
  687. out, _, err := runCommandWithOutput(cmd)
  688. if err != nil {
  689. t.Fatal(err, out)
  690. }
  691. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  692. t.Fatalf("expected output ok received %s", actual)
  693. }
  694. deleteAllContainers()
  695. logDone("run - test --cap-drop=ALL --cap-add=MKNOD can mknod")
  696. }
  697. func TestCapAddInvalid(t *testing.T) {
  698. cmd := exec.Command(dockerBinary, "run", "--cap-add=CHPASS", "busybox", "ls")
  699. out, _, err := runCommandWithOutput(cmd)
  700. if err == nil {
  701. t.Fatal(err, out)
  702. }
  703. logDone("run - test --cap-add=CHPASS invalid")
  704. }
  705. func TestCapAddCanDownInterface(t *testing.T) {
  706. cmd := exec.Command(dockerBinary, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
  707. out, _, err := runCommandWithOutput(cmd)
  708. if err != nil {
  709. t.Fatal(err, out)
  710. }
  711. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  712. t.Fatalf("expected output ok received %s", actual)
  713. }
  714. deleteAllContainers()
  715. logDone("run - test --cap-add=NET_ADMIN can set eth0 down")
  716. }
  717. func TestCapAddALLCanDownInterface(t *testing.T) {
  718. cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
  719. out, _, err := runCommandWithOutput(cmd)
  720. if err != nil {
  721. t.Fatal(err, out)
  722. }
  723. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  724. t.Fatalf("expected output ok received %s", actual)
  725. }
  726. deleteAllContainers()
  727. logDone("run - test --cap-add=ALL can set eth0 down")
  728. }
  729. func TestCapAddALLDropNetAdminCanDownInterface(t *testing.T) {
  730. cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
  731. out, _, err := runCommandWithOutput(cmd)
  732. if err == nil {
  733. t.Fatal(err, out)
  734. }
  735. if actual := strings.Trim(out, "\r\n"); actual == "ok" {
  736. t.Fatalf("expected output not ok received %s", actual)
  737. }
  738. deleteAllContainers()
  739. logDone("run - test --cap-add=ALL --cap-drop=NET_ADMIN cannot set eth0 down")
  740. }
  741. func TestPrivilegedCanMount(t *testing.T) {
  742. cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
  743. out, _, err := runCommandWithOutput(cmd)
  744. if err != nil {
  745. t.Fatal(err)
  746. }
  747. if actual := strings.Trim(out, "\r\n"); actual != "ok" {
  748. t.Fatalf("expected output ok received %s", actual)
  749. }
  750. deleteAllContainers()
  751. logDone("run - test privileged can mount")
  752. }
  753. func TestUnPrivilegedCannotMount(t *testing.T) {
  754. cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
  755. out, _, err := runCommandWithOutput(cmd)
  756. if err == nil {
  757. t.Fatal(err, out)
  758. }
  759. if actual := strings.Trim(out, "\r\n"); actual == "ok" {
  760. t.Fatalf("expected output not ok received %s", actual)
  761. }
  762. deleteAllContainers()
  763. logDone("run - test un-privileged cannot mount")
  764. }
  765. func TestSysNotWritableInNonPrivilegedContainers(t *testing.T) {
  766. cmd := exec.Command(dockerBinary, "run", "busybox", "touch", "/sys/kernel/profiling")
  767. if code, err := runCommand(cmd); err == nil || code == 0 {
  768. t.Fatal("sys should not be writable in a non privileged container")
  769. }
  770. deleteAllContainers()
  771. logDone("run - sys not writable in non privileged container")
  772. }
  773. func TestSysWritableInPrivilegedContainers(t *testing.T) {
  774. cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "touch", "/sys/kernel/profiling")
  775. if code, err := runCommand(cmd); err != nil || code != 0 {
  776. t.Fatalf("sys should be writable in privileged container")
  777. }
  778. deleteAllContainers()
  779. logDone("run - sys writable in privileged container")
  780. }
  781. func TestProcNotWritableInNonPrivilegedContainers(t *testing.T) {
  782. cmd := exec.Command(dockerBinary, "run", "busybox", "touch", "/proc/sysrq-trigger")
  783. if code, err := runCommand(cmd); err == nil || code == 0 {
  784. t.Fatal("proc should not be writable in a non privileged container")
  785. }
  786. deleteAllContainers()
  787. logDone("run - proc not writable in non privileged container")
  788. }
  789. func TestProcWritableInPrivilegedContainers(t *testing.T) {
  790. cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "touch", "/proc/sysrq-trigger")
  791. if code, err := runCommand(cmd); err != nil || code != 0 {
  792. t.Fatalf("proc should be writable in privileged container")
  793. }
  794. deleteAllContainers()
  795. logDone("run - proc writable in privileged container")
  796. }
  797. func TestRunWithCpuset(t *testing.T) {
  798. cmd := exec.Command(dockerBinary, "run", "--cpuset", "0", "busybox", "true")
  799. if code, err := runCommand(cmd); err != nil || code != 0 {
  800. t.Fatalf("container should run successfuly with cpuset of 0: %s", err)
  801. }
  802. deleteAllContainers()
  803. logDone("run - cpuset 0")
  804. }
  805. func TestDeviceNumbers(t *testing.T) {
  806. cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "ls -l /dev/null")
  807. out, _, err := runCommandWithOutput(cmd)
  808. if err != nil {
  809. t.Fatal(err, out)
  810. }
  811. deviceLineFields := strings.Fields(out)
  812. deviceLineFields[6] = ""
  813. deviceLineFields[7] = ""
  814. deviceLineFields[8] = ""
  815. expected := []string{"crw-rw-rw-", "1", "root", "root", "1,", "3", "", "", "", "/dev/null"}
  816. if !(reflect.DeepEqual(deviceLineFields, expected)) {
  817. t.Fatalf("expected output\ncrw-rw-rw- 1 root root 1, 3 May 24 13:29 /dev/null\n received\n %s\n", out)
  818. }
  819. deleteAllContainers()
  820. logDone("run - test device numbers")
  821. }
  822. func TestThatCharacterDevicesActLikeCharacterDevices(t *testing.T) {
  823. cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "dd if=/dev/zero of=/zero bs=1k count=5 2> /dev/null ; du -h /zero")
  824. out, _, err := runCommandWithOutput(cmd)
  825. if err != nil {
  826. t.Fatal(err, out)
  827. }
  828. if actual := strings.Trim(out, "\r\n"); actual[0] == '0' {
  829. t.Fatalf("expected a new file called /zero to be create that is greater than 0 bytes long, but du says: %s", actual)
  830. }
  831. deleteAllContainers()
  832. logDone("run - test that character devices work.")
  833. }
  834. func TestRunUnprivilegedWithChroot(t *testing.T) {
  835. cmd := exec.Command(dockerBinary, "run", "busybox", "chroot", "/", "true")
  836. if _, err := runCommand(cmd); err != nil {
  837. t.Fatal(err)
  838. }
  839. deleteAllContainers()
  840. logDone("run - unprivileged with chroot")
  841. }
  842. func TestAddingOptionalDevices(t *testing.T) {
  843. cmd := exec.Command(dockerBinary, "run", "--device", "/dev/zero:/dev/nulo", "busybox", "sh", "-c", "ls /dev/nulo")
  844. out, _, err := runCommandWithOutput(cmd)
  845. if err != nil {
  846. t.Fatal(err, out)
  847. }
  848. if actual := strings.Trim(out, "\r\n"); actual != "/dev/nulo" {
  849. t.Fatalf("expected output /dev/nulo, received %s", actual)
  850. }
  851. deleteAllContainers()
  852. logDone("run - test --device argument")
  853. }
  854. func TestModeHostname(t *testing.T) {
  855. cmd := exec.Command(dockerBinary, "run", "-h=testhostname", "busybox", "cat", "/etc/hostname")
  856. out, _, err := runCommandWithOutput(cmd)
  857. if err != nil {
  858. t.Fatal(err, out)
  859. }
  860. if actual := strings.Trim(out, "\r\n"); actual != "testhostname" {
  861. t.Fatalf("expected 'testhostname', but says: '%s'", actual)
  862. }
  863. cmd = exec.Command(dockerBinary, "run", "--net=host", "busybox", "cat", "/etc/hostname")
  864. out, _, err = runCommandWithOutput(cmd)
  865. if err != nil {
  866. t.Fatal(err, out)
  867. }
  868. hostname, err := os.Hostname()
  869. if err != nil {
  870. t.Fatal(err)
  871. }
  872. if actual := strings.Trim(out, "\r\n"); actual != hostname {
  873. t.Fatalf("expected '%s', but says: '%s'", hostname, actual)
  874. }
  875. deleteAllContainers()
  876. logDone("run - hostname and several network modes")
  877. }
  878. func TestRootWorkdir(t *testing.T) {
  879. s, _, err := cmd(t, "run", "--workdir", "/", "busybox", "pwd")
  880. if err != nil {
  881. t.Fatal(s, err)
  882. }
  883. if s != "/\n" {
  884. t.Fatalf("pwd returned '%s' (expected /\\n)", s)
  885. }
  886. deleteAllContainers()
  887. logDone("run - workdir /")
  888. }
  889. func TestAllowBindMountingRoot(t *testing.T) {
  890. s, _, err := cmd(t, "run", "-v", "/:/host", "busybox", "ls", "/host")
  891. if err != nil {
  892. t.Fatal(s, err)
  893. }
  894. deleteAllContainers()
  895. logDone("run - bind mount / as volume")
  896. }
  897. func TestDisallowBindMountingRootToRoot(t *testing.T) {
  898. cmd := exec.Command(dockerBinary, "run", "-v", "/:/", "busybox", "ls", "/host")
  899. out, _, err := runCommandWithOutput(cmd)
  900. if err == nil {
  901. t.Fatal(out, err)
  902. }
  903. deleteAllContainers()
  904. logDone("run - bind mount /:/ as volume should fail")
  905. }
  906. // Test recursive bind mount works by default
  907. func TestDockerRunWithVolumesIsRecursive(t *testing.T) {
  908. tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test")
  909. if err != nil {
  910. t.Fatal(err)
  911. }
  912. defer os.RemoveAll(tmpDir)
  913. // Create a temporary tmpfs mount.
  914. tmpfsDir := filepath.Join(tmpDir, "tmpfs")
  915. if err := os.MkdirAll(tmpfsDir, 0777); err != nil {
  916. t.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err)
  917. }
  918. if err := mount.Mount("tmpfs", tmpfsDir, "tmpfs", ""); err != nil {
  919. t.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err)
  920. }
  921. f, err := ioutil.TempFile(tmpfsDir, "touch-me")
  922. if err != nil {
  923. t.Fatal(err)
  924. }
  925. defer f.Close()
  926. runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox:latest", "ls", "/tmp/tmpfs")
  927. out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd)
  928. if err != nil && exitCode != 0 {
  929. t.Fatal(out, stderr, err)
  930. }
  931. if !strings.Contains(out, filepath.Base(f.Name())) {
  932. t.Fatal("Recursive bind mount test failed. Expected file not found")
  933. }
  934. deleteAllContainers()
  935. logDone("run - volumes are bind mounted recursively")
  936. }
  937. func TestDnsDefaultOptions(t *testing.T) {
  938. cmd := exec.Command(dockerBinary, "run", "busybox", "cat", "/etc/resolv.conf")
  939. actual, _, err := runCommandWithOutput(cmd)
  940. if err != nil {
  941. t.Fatal(err, actual)
  942. }
  943. resolvConf, err := ioutil.ReadFile("/etc/resolv.conf")
  944. if os.IsNotExist(err) {
  945. t.Fatalf("/etc/resolv.conf does not exist")
  946. }
  947. if actual != string(resolvConf) {
  948. t.Fatalf("expected resolv.conf is not the same of actual")
  949. }
  950. deleteAllContainers()
  951. logDone("run - dns default options")
  952. }
  953. func TestDnsOptions(t *testing.T) {
  954. cmd := exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf")
  955. out, _, err := runCommandWithOutput(cmd)
  956. if err != nil {
  957. t.Fatal(err, out)
  958. }
  959. actual := strings.Replace(strings.Trim(out, "\r\n"), "\n", " ", -1)
  960. if actual != "nameserver 127.0.0.1 search mydomain" {
  961. t.Fatalf("expected 'nameserver 127.0.0.1 search mydomain', but says: '%s'", actual)
  962. }
  963. cmd = exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "--dns-search=.", "busybox", "cat", "/etc/resolv.conf")
  964. out, _, err = runCommandWithOutput(cmd)
  965. if err != nil {
  966. t.Fatal(err, out)
  967. }
  968. actual = strings.Replace(strings.Trim(strings.Trim(out, "\r\n"), " "), "\n", " ", -1)
  969. if actual != "nameserver 127.0.0.1" {
  970. t.Fatalf("expected 'nameserver 127.0.0.1', but says: '%s'", actual)
  971. }
  972. logDone("run - dns options")
  973. }
  974. func TestDnsOptionsBasedOnHostResolvConf(t *testing.T) {
  975. resolvConf, err := ioutil.ReadFile("/etc/resolv.conf")
  976. if os.IsNotExist(err) {
  977. t.Fatalf("/etc/resolv.conf does not exist")
  978. }
  979. hostNamservers := resolvconf.GetNameservers(resolvConf)
  980. hostSearch := resolvconf.GetSearchDomains(resolvConf)
  981. cmd := exec.Command(dockerBinary, "run", "--dns=127.0.0.1", "busybox", "cat", "/etc/resolv.conf")
  982. out, _, err := runCommandWithOutput(cmd)
  983. if err != nil {
  984. t.Fatal(err, out)
  985. }
  986. if actualNameservers := resolvconf.GetNameservers([]byte(out)); string(actualNameservers[0]) != "127.0.0.1" {
  987. t.Fatalf("expected '127.0.0.1', but says: '%s'", string(actualNameservers[0]))
  988. }
  989. actualSearch := resolvconf.GetSearchDomains([]byte(out))
  990. if len(actualSearch) != len(hostSearch) {
  991. t.Fatalf("expected '%s' search domain(s), but it has: '%s'", len(hostSearch), len(actualSearch))
  992. }
  993. for i := range actualSearch {
  994. if actualSearch[i] != hostSearch[i] {
  995. t.Fatalf("expected '%s' domain, but says: '%s'", actualSearch[i], hostSearch[i])
  996. }
  997. }
  998. cmd = exec.Command(dockerBinary, "run", "--dns-search=mydomain", "busybox", "cat", "/etc/resolv.conf")
  999. out, _, err = runCommandWithOutput(cmd)
  1000. if err != nil {
  1001. t.Fatal(err, out)
  1002. }
  1003. actualNameservers := resolvconf.GetNameservers([]byte(out))
  1004. if len(actualNameservers) != len(hostNamservers) {
  1005. t.Fatalf("expected '%s' nameserver(s), but it has: '%s'", len(hostNamservers), len(actualNameservers))
  1006. }
  1007. for i := range actualNameservers {
  1008. if actualNameservers[i] != hostNamservers[i] {
  1009. t.Fatalf("expected '%s' nameserver, but says: '%s'", actualNameservers[i], hostNamservers[i])
  1010. }
  1011. }
  1012. if actualSearch = resolvconf.GetSearchDomains([]byte(out)); string(actualSearch[0]) != "mydomain" {
  1013. t.Fatalf("expected 'mydomain', but says: '%s'", string(actualSearch[0]))
  1014. }
  1015. deleteAllContainers()
  1016. logDone("run - dns options based on host resolv.conf")
  1017. }
  1018. // Regression test for #6983
  1019. func TestAttachStdErrOnlyTTYMode(t *testing.T) {
  1020. cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stderr", "busybox", "true")
  1021. exitCode, err := runCommand(cmd)
  1022. if err != nil {
  1023. t.Fatal(err)
  1024. } else if exitCode != 0 {
  1025. t.Fatalf("Container should have exited with error code 0")
  1026. }
  1027. deleteAllContainers()
  1028. logDone("run - Attach stderr only with -t")
  1029. }
  1030. // Regression test for #6983
  1031. func TestAttachStdOutOnlyTTYMode(t *testing.T) {
  1032. cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stdout", "busybox", "true")
  1033. exitCode, err := runCommand(cmd)
  1034. if err != nil {
  1035. t.Fatal(err)
  1036. } else if exitCode != 0 {
  1037. t.Fatalf("Container should have exited with error code 0")
  1038. }
  1039. deleteAllContainers()
  1040. logDone("run - Attach stdout only with -t")
  1041. }
  1042. // Regression test for #6983
  1043. func TestAttachStdOutAndErrTTYMode(t *testing.T) {
  1044. cmd := exec.Command(dockerBinary, "run", "-t", "-a", "stdout", "-a", "stderr", "busybox", "true")
  1045. exitCode, err := runCommand(cmd)
  1046. if err != nil {
  1047. t.Fatal(err)
  1048. } else if exitCode != 0 {
  1049. t.Fatalf("Container should have exited with error code 0")
  1050. }
  1051. deleteAllContainers()
  1052. logDone("run - Attach stderr and stdout with -t")
  1053. }
  1054. func TestState(t *testing.T) {
  1055. defer deleteAllContainers()
  1056. cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
  1057. out, _, err := runCommandWithOutput(cmd)
  1058. if err != nil {
  1059. t.Fatal(err, out)
  1060. }
  1061. id := strings.TrimSpace(out)
  1062. state, err := inspectField(id, "State.Running")
  1063. if err != nil {
  1064. t.Fatal(err)
  1065. }
  1066. if state != "true" {
  1067. t.Fatal("Container state is 'not running'")
  1068. }
  1069. pid1, err := inspectField(id, "State.Pid")
  1070. if err != nil {
  1071. t.Fatal(err)
  1072. }
  1073. if pid1 == "0" {
  1074. t.Fatal("Container state Pid 0")
  1075. }
  1076. cmd = exec.Command(dockerBinary, "stop", id)
  1077. out, _, err = runCommandWithOutput(cmd)
  1078. if err != nil {
  1079. t.Fatal(err, out)
  1080. }
  1081. state, err = inspectField(id, "State.Running")
  1082. if err != nil {
  1083. t.Fatal(err)
  1084. }
  1085. if state != "false" {
  1086. t.Fatal("Container state is 'running'")
  1087. }
  1088. pid2, err := inspectField(id, "State.Pid")
  1089. if err != nil {
  1090. t.Fatal(err)
  1091. }
  1092. if pid2 == pid1 {
  1093. t.Fatalf("Container state Pid %s, but expected %s", pid2, pid1)
  1094. }
  1095. cmd = exec.Command(dockerBinary, "start", id)
  1096. out, _, err = runCommandWithOutput(cmd)
  1097. if err != nil {
  1098. t.Fatal(err, out)
  1099. }
  1100. state, err = inspectField(id, "State.Running")
  1101. if err != nil {
  1102. t.Fatal(err)
  1103. }
  1104. if state != "true" {
  1105. t.Fatal("Container state is 'not running'")
  1106. }
  1107. pid3, err := inspectField(id, "State.Pid")
  1108. if err != nil {
  1109. t.Fatal(err)
  1110. }
  1111. if pid3 == pid1 {
  1112. t.Fatalf("Container state Pid %s, but expected %s", pid2, pid1)
  1113. }
  1114. logDone("run - test container state.")
  1115. }
  1116. // Test for #1737
  1117. func TestCopyVolumeUidGid(t *testing.T) {
  1118. name := "testrunvolumesuidgid"
  1119. defer deleteImages(name)
  1120. defer deleteAllContainers()
  1121. _, err := buildImage(name,
  1122. `FROM busybox
  1123. RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1124. RUN echo 'dockerio:x:1001:' >> /etc/group
  1125. RUN mkdir -p /hello && touch /hello/test && chown dockerio.dockerio /hello`,
  1126. true)
  1127. if err != nil {
  1128. t.Fatal(err)
  1129. }
  1130. // Test that the uid and gid is copied from the image to the volume
  1131. cmd := exec.Command(dockerBinary, "run", "--rm", "-v", "/hello", name, "sh", "-c", "ls -l / | grep hello | awk '{print $3\":\"$4}'")
  1132. out, _, err := runCommandWithOutput(cmd)
  1133. if err != nil {
  1134. t.Fatal(err, out)
  1135. }
  1136. out = strings.TrimSpace(out)
  1137. if out != "dockerio:dockerio" {
  1138. t.Fatalf("Wrong /hello ownership: %s, expected dockerio:dockerio", out)
  1139. }
  1140. logDone("run - copy uid/gid for volume")
  1141. }
  1142. // Test for #1582
  1143. func TestCopyVolumeContent(t *testing.T) {
  1144. name := "testruncopyvolumecontent"
  1145. defer deleteImages(name)
  1146. defer deleteAllContainers()
  1147. _, err := buildImage(name,
  1148. `FROM busybox
  1149. RUN mkdir -p /hello/local && echo hello > /hello/local/world`,
  1150. true)
  1151. if err != nil {
  1152. t.Fatal(err)
  1153. }
  1154. // Test that the content is copied from the image to the volume
  1155. cmd := exec.Command(dockerBinary, "run", "--rm", "-v", "/hello", name, "sh", "-c", "find", "/hello")
  1156. out, _, err := runCommandWithOutput(cmd)
  1157. if err != nil {
  1158. t.Fatal(err, out)
  1159. }
  1160. if !(strings.Contains(out, "/hello/local/world") && strings.Contains(out, "/hello/local")) {
  1161. t.Fatal("Container failed to transfer content to volume")
  1162. }
  1163. logDone("run - copy volume content")
  1164. }
  1165. func TestRunCleanupCmdOnEntrypoint(t *testing.T) {
  1166. name := "testrunmdcleanuponentrypoint"
  1167. defer deleteImages(name)
  1168. defer deleteAllContainers()
  1169. if _, err := buildImage(name,
  1170. `FROM busybox
  1171. ENTRYPOINT ["echo"]
  1172. CMD ["testingpoint"]`,
  1173. true); err != nil {
  1174. t.Fatal(err)
  1175. }
  1176. runCmd := exec.Command(dockerBinary, "run", "--entrypoint", "whoami", name)
  1177. out, exit, err := runCommandWithOutput(runCmd)
  1178. if err != nil {
  1179. t.Fatalf("Error: %v, out: %q", err, out)
  1180. }
  1181. if exit != 0 {
  1182. t.Fatalf("expected exit code 0 received %d, out: %q", exit, out)
  1183. }
  1184. out = strings.TrimSpace(out)
  1185. if out != "root" {
  1186. t.Fatalf("Expected output root, got %q", out)
  1187. }
  1188. logDone("run - cleanup cmd on --entrypoint")
  1189. }
  1190. // TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected
  1191. func TestRunWorkdirExistsAndIsFile(t *testing.T) {
  1192. defer deleteAllContainers()
  1193. runCmd := exec.Command(dockerBinary, "run", "-w", "/bin/cat", "busybox")
  1194. out, exit, err := runCommandWithOutput(runCmd)
  1195. if !(err != nil && exit == 1 && strings.Contains(out, "Cannot mkdir: /bin/cat is not a directory")) {
  1196. t.Fatalf("Docker must complains about making dir, but we got out: %s, exit: %d, err: %s", out, exit, err)
  1197. }
  1198. logDone("run - error on existing file for workdir")
  1199. }
  1200. func TestRunExitOnStdinClose(t *testing.T) {
  1201. name := "testrunexitonstdinclose"
  1202. defer deleteAllContainers()
  1203. runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", "/bin/cat")
  1204. stdin, err := runCmd.StdinPipe()
  1205. if err != nil {
  1206. t.Fatal(err)
  1207. }
  1208. stdout, err := runCmd.StdoutPipe()
  1209. if err != nil {
  1210. t.Fatal(err)
  1211. }
  1212. if err := runCmd.Start(); err != nil {
  1213. t.Fatal(err)
  1214. }
  1215. if _, err := stdin.Write([]byte("hello\n")); err != nil {
  1216. t.Fatal(err)
  1217. }
  1218. r := bufio.NewReader(stdout)
  1219. line, err := r.ReadString('\n')
  1220. if err != nil {
  1221. t.Fatal(err)
  1222. }
  1223. line = strings.TrimSpace(line)
  1224. if line != "hello" {
  1225. t.Fatalf("Output should be 'hello', got '%q'", line)
  1226. }
  1227. if err := stdin.Close(); err != nil {
  1228. t.Fatal(err)
  1229. }
  1230. finish := make(chan struct{})
  1231. go func() {
  1232. if err := runCmd.Wait(); err != nil {
  1233. t.Fatal(err)
  1234. }
  1235. close(finish)
  1236. }()
  1237. select {
  1238. case <-finish:
  1239. case <-time.After(1 * time.Second):
  1240. t.Fatal("docker run failed to exit on stdin close")
  1241. }
  1242. state, err := inspectField(name, "State.Running")
  1243. if err != nil {
  1244. t.Fatal(err)
  1245. }
  1246. if state != "false" {
  1247. t.Fatal("Container must be stopped after stdin closing")
  1248. }
  1249. logDone("run - exit on stdin closing")
  1250. }
  1251. // Test for #2267
  1252. func TestWriteHostsFileAndNotCommit(t *testing.T) {
  1253. name := "writehosts"
  1254. cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hosts && cat /etc/hosts")
  1255. out, _, err := runCommandWithOutput(cmd)
  1256. if err != nil {
  1257. t.Fatal(err, out)
  1258. }
  1259. if !strings.Contains(out, "test2267") {
  1260. t.Fatal("/etc/hosts should contain 'test2267'")
  1261. }
  1262. cmd = exec.Command(dockerBinary, "diff", name)
  1263. if err != nil {
  1264. t.Fatal(err, out)
  1265. }
  1266. out, _, err = runCommandWithOutput(cmd)
  1267. if err != nil {
  1268. t.Fatal(err, out)
  1269. }
  1270. if len(strings.Trim(out, "\r\n")) != 0 {
  1271. t.Fatal("diff should be empty")
  1272. }
  1273. logDone("run - write to /etc/hosts and not commited")
  1274. }
  1275. // Test for #2267
  1276. func TestWriteHostnameFileAndNotCommit(t *testing.T) {
  1277. name := "writehostname"
  1278. cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/hostname && cat /etc/hostname")
  1279. out, _, err := runCommandWithOutput(cmd)
  1280. if err != nil {
  1281. t.Fatal(err, out)
  1282. }
  1283. if !strings.Contains(out, "test2267") {
  1284. t.Fatal("/etc/hostname should contain 'test2267'")
  1285. }
  1286. cmd = exec.Command(dockerBinary, "diff", name)
  1287. if err != nil {
  1288. t.Fatal(err, out)
  1289. }
  1290. out, _, err = runCommandWithOutput(cmd)
  1291. if err != nil {
  1292. t.Fatal(err, out)
  1293. }
  1294. if len(strings.Trim(out, "\r\n")) != 0 {
  1295. t.Fatal("diff should be empty")
  1296. }
  1297. logDone("run - write to /etc/hostname and not commited")
  1298. }
  1299. // Test for #2267
  1300. func TestWriteResolvFileAndNotCommit(t *testing.T) {
  1301. name := "writeresolv"
  1302. cmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo test2267 >> /etc/resolv.conf && cat /etc/resolv.conf")
  1303. out, _, err := runCommandWithOutput(cmd)
  1304. if err != nil {
  1305. t.Fatal(err, out)
  1306. }
  1307. if !strings.Contains(out, "test2267") {
  1308. t.Fatal("/etc/resolv.conf should contain 'test2267'")
  1309. }
  1310. cmd = exec.Command(dockerBinary, "diff", name)
  1311. if err != nil {
  1312. t.Fatal(err, out)
  1313. }
  1314. out, _, err = runCommandWithOutput(cmd)
  1315. if err != nil {
  1316. t.Fatal(err, out)
  1317. }
  1318. if len(strings.Trim(out, "\r\n")) != 0 {
  1319. t.Fatal("diff should be empty")
  1320. }
  1321. logDone("run - write to /etc/resolv.conf and not commited")
  1322. }