docker_cli_run_test.go 41 KB

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