// Ensure an error occurs when you have a container read-only rootfs but you // extract an archive to a symlink in a writable volume which points to a // directory outside of the volume. func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs(c *check.C) { // Requires local volume mount bind. // --read-only + userns has remount issues testRequires(c, SameHostDaemon, NotUserNamespace) testVol := getTestDir(c, "test-put-container-archive-err-symlink-in-volume-to-read-only-rootfs-") defer os.RemoveAll(testVol) makeTestContentInDir(c, testVol) cID := makeTestContainer(c, testContainerOptions{ readOnly: true, volumes: defaultVolumes(testVol), // Our bind mount is at /vol2 }) defer deleteContainer(cID) // Attempt to extract to a symlink in the volume which points to a // directory outside the volume. This should cause an error because the // rootfs is read-only. query := make(url.Values, 1) query.Set("path", "/vol2/symlinkToAbsDir") urlPath := fmt.Sprintf("/v1.20/containers/%s/archive?%s", cID, query.Encode()) statusCode, body, err := sockRequest("PUT", urlPath, nil) c.Assert(err, check.IsNil) if !isCpCannotCopyReadOnly(fmt.Errorf(string(body))) { c.Fatalf("expected ErrContainerRootfsReadonly error, but got %d: %s", statusCode, string(body)) } }
// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) { testRequires(c, DaemonIsLinux) dockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox") fooDir, err := inspectMountSourceField("one", "/foo") if err != nil { c.Fatal(err) } dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox") bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}} status, _, err := sockRequest("POST", "/containers/two/start", bindSpec) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusNoContent) fooDir2, err := inspectMountSourceField("two", "/foo") if err != nil { c.Fatal(err) } if fooDir2 != fooDir { c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2) } }
// Make sure a request to use a down driver doesn't block other requests func (s *DockerExternalVolumeSuite) TestStartExternalVolumeDriverLookupNotBlocked(c *check.C) { specPath := "/etc/docker/plugins/down-driver.spec" err := ioutil.WriteFile("/etc/docker/plugins/down-driver.spec", []byte("tcp://127.0.0.7:9999"), 0644) c.Assert(err, check.IsNil) defer os.RemoveAll(specPath) chCmd1 := make(chan struct{}) chCmd2 := make(chan error) cmd1 := exec.Command(dockerBinary, "volume", "create", "-d", "down-driver") cmd2 := exec.Command(dockerBinary, "volume", "create") c.Assert(cmd1.Start(), check.IsNil) defer cmd1.Process.Kill() time.Sleep(100 * time.Millisecond) // ensure API has been called c.Assert(cmd2.Start(), check.IsNil) go func() { cmd1.Wait() close(chCmd1) }() go func() { chCmd2 <- cmd2.Wait() }() select { case <-chCmd1: cmd2.Process.Kill() c.Fatalf("volume create with down driver finished unexpectedly") case err := <-chCmd2: c.Assert(err, check.IsNil, check.Commentf("error creating volume")) case <-time.After(5 * time.Second): c.Fatal("volume creates are blocked by previous create requests when previous driver is down") cmd2.Process.Kill() } }
// TestRunSeccompProfileDenyChmod checks that 'docker run --security-opt seccomp=/tmp/profile.json busybox chmod 400 /etc/hostname' exits with operation not permitted. func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) { testRequires(c, SameHostDaemon, seccompEnabled) jsonData := `{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "chmod", "action": "SCMP_ACT_ERRNO" } ] }` tmpFile, err := ioutil.TempFile("", "profile.json") defer tmpFile.Close() if err != nil { c.Fatal(err) } if _, err := tmpFile.Write([]byte(jsonData)); err != nil { c.Fatal(err) } runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "400", "/etc/hostname") out, _, _ := runCommandWithOutput(runCmd) if !strings.Contains(out, "Operation not permitted") { c.Fatalf("expected chmod with seccomp profile denied to fail, got %s", out) } }
// Issue 7941 - test to make sure a "null" in JSON is just ignored. // W/o this fix a null in JSON would be parsed into a string var as "null" func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) { testRequires(c, DaemonIsLinux) config := `{ "Hostname":"", "Domainname":"", "Memory":0, "MemorySwap":0, "CpuShares":0, "Cpuset":null, "AttachStdin":true, "AttachStdout":true, "AttachStderr":true, "ExposedPorts":{}, "Tty":true, "OpenStdin":true, "StdinOnce":true, "Env":[], "Cmd":"ls", "Image":"busybox", "Volumes":{}, "WorkingDir":"", "Entrypoint":null, "NetworkDisabled":false, "OnBuild":null}` res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json") c.Assert(err, check.IsNil) c.Assert(res.StatusCode, check.Equals, http.StatusCreated) b, err := readBody(body) if err != nil { c.Fatal(err) } type createResp struct { ID string } var container createResp if err := json.Unmarshal(b, &container); err != nil { c.Fatal(err) } out, err := inspectField(container.ID, "HostConfig.CpusetCpus") if err != nil { c.Fatal(err, out) } if out != "" { c.Fatalf("expected empty string, got %q", out) } outMemory, errMemory := inspectField(container.ID, "HostConfig.Memory") c.Assert(outMemory, check.Equals, "0") if errMemory != nil { c.Fatal(errMemory, outMemory) } outMemorySwap, errMemorySwap := inspectField(container.ID, "HostConfig.MemorySwap") c.Assert(outMemorySwap, check.Equals, "0") if errMemorySwap != nil { c.Fatal(errMemorySwap, outMemorySwap) } }
func (s *DockerSuite) TestContainerApiCreateWithDomainName(c *check.C) { testRequires(c, DaemonIsLinux) domainName := "test-domain" config := map[string]interface{}{ "Image": "busybox", "Domainname": domainName, } status, body, err := sockRequest("POST", "/containers/create", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) var container types.ContainerCreateResponse if err := json.Unmarshal(body, &container); err != nil { c.Fatal(err) } status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) var containerJSON types.ContainerJSON if err := json.Unmarshal(body, &containerJSON); err != nil { c.Fatal(err) } if containerJSON.Config.Domainname != domainName { c.Fatalf("Mismatched Domainname, Expected %s, Actual: %s ", domainName, containerJSON.Config.Domainname) } }
func (s *DockerSuite) TestContainerApiCommit(c *check.C) { testRequires(c, DaemonIsLinux) cName := "testapicommit" dockerCmd(c, "run", "--name="+cName, "busybox", "/bin/sh", "-c", "touch /test") name := "TestContainerApiCommit" status, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+cName, nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) type resp struct { ID string } var img resp if err := json.Unmarshal(b, &img); err != nil { c.Fatal(err) } cmd, err := inspectField(img.ID, "Config.Cmd") if err != nil { c.Fatal(err) } if cmd != "{[/bin/sh -c touch /test]}" { c.Fatalf("got wrong Cmd from commit: %q", cmd) } // sanity check, make sure the image is what we think it is dockerCmd(c, "run", img.ID, "ls", "/test") }
func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) { testRequires(c, DaemonIsLinux) name := "testing" config := map[string]interface{}{ "Image": "busybox", "Volumes": map[string]struct{}{"/tmp": {}}, } status, _, err := sockRequest("POST", "/containers/create?name="+name, config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) bindPath := randomTmpDirPath("test", daemonPlatform) config = map[string]interface{}{ "Binds": []string{bindPath + ":/tmp"}, } status, _, err = sockRequest("POST", "/containers/"+name+"/start", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusNoContent) pth, err := inspectMountSourceField(name, "/tmp") if err != nil { c.Fatal(err) } if pth != bindPath { c.Fatalf("expected volume host path to be %s, got %s", bindPath, pth) } }
// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) { out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=one", "busybox")) if err != nil { c.Fatal(err, out) } fooDir, err := inspectFieldMap("one", "Volumes", "/foo") if err != nil { c.Fatal(err) } out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=two", "busybox")) if err != nil { c.Fatal(err, out) } bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}} status, _, err := sockRequest("POST", "/containers/two/start", bindSpec) c.Assert(status, check.Equals, http.StatusNoContent) c.Assert(err, check.IsNil) fooDir2, err := inspectFieldMap("two", "Volumes", "/foo") if err != nil { c.Fatal(err) } if fooDir2 != fooDir { c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2) } }
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) { testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows git, err := fakeGIT("repo", map[string]string{ "Dockerfile": `FROM busybox RUN echo from Dockerfile`, "dockerfile": `FROM busybox RUN echo from dockerfile`, }, false) if err != nil { c.Fatal(err) } defer git.Close() // Make sure it tries to 'dockerfile' query param value res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json") c.Assert(res.StatusCode, check.Equals, http.StatusOK) c.Assert(err, check.IsNil) buf, err := readBody(body) if err != nil { c.Fatal(err) } out := string(buf) if !strings.Contains(out, "from Dockerfile") { c.Fatalf("Incorrect output: %s", out) } }
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) { server, err := fakeStorage(map[string]string{ "testD": `FROM busybox COPY * /tmp/ RUN find / -name ba* RUN find /tmp/`, }) if err != nil { c.Fatal(err) } defer server.Close() res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json") c.Assert(res.StatusCode, check.Equals, http.StatusOK) c.Assert(err, check.IsNil) buf, err := readBody(body) if err != nil { c.Fatal(err) } // Make sure Dockerfile exists. // Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL out := string(buf) if !strings.Contains(out, "/tmp/Dockerfile") || strings.Contains(out, "baz") { c.Fatalf("Incorrect output: %s", out) } }
func (s *DockerSuite) TestContainerApiGetAll(c *check.C) { startCount, err := getContainerCount() if err != nil { c.Fatalf("Cannot query container count: %v", err) } name := "getall" runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true") out, _, err := runCommandWithOutput(runCmd) if err != nil { c.Fatalf("Error on container creation: %v, output: %q", err, out) } status, body, err := sockRequest("GET", "/containers/json?all=1", nil) c.Assert(status, check.Equals, http.StatusOK) c.Assert(err, check.IsNil) var inspectJSON []struct { Names []string } if err = json.Unmarshal(body, &inspectJSON); err != nil { c.Fatalf("unable to unmarshal response body: %v", err) } if len(inspectJSON) != startCount+1 { c.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount) } if actual := inspectJSON[0].Names[0]; actual != "/"+name { c.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual) } }
func (s *DockerSuite) TestApiStatsNoStreamGetCpu(c *check.C) { testRequires(c, DaemonIsLinux) out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done") id := strings.TrimSpace(out) c.Assert(waitRun(id), check.IsNil) resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "") c.Assert(err, check.IsNil) c.Assert(resp.ContentLength > 0, check.Equals, true, check.Commentf("should not use chunked encoding")) c.Assert(resp.Header.Get("Content-Type"), check.Equals, "application/json") var v *types.Stats err = json.NewDecoder(body).Decode(&v) c.Assert(err, check.IsNil) body.Close() var cpuPercent = 0.0 cpuDelta := float64(v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage) systemDelta := float64(v.CPUStats.SystemUsage - v.PreCPUStats.SystemUsage) cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0 if cpuPercent == 0 { c.Fatalf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent) } }
// Regression test for https://github.com/docker/docker/issues/7843 func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) { dockerCmd(c, "run", "-d", "--name", "test", "busybox") dockerCmd(c, "wait", "test") // Expect this to fail because the above container is stopped, this is what we want if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "--link", "test:test", "busybox")); err == nil { c.Fatal("Expected error but got none") } ch := make(chan error) go func() { // Attempt to start attached to the container that won't start // This should return an error immediately since the container can't be started if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil { ch <- fmt.Errorf("Expected error but got none") } close(ch) }() select { case err := <-ch: c.Assert(err, check.IsNil) case <-time.After(time.Second): c.Fatalf("Attach did not exit properly") } }
func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) { newRepo := "127.0.0.1:5000/busybox" oldRepo := "busybox" newTag := "busybox:test" cmd := exec.Command(dockerBinary, "tag", oldRepo, newRepo) out, _, err := runCommandWithOutput(cmd) if err != nil { c.Fatalf("Could not tag busybox: %v: %s", err, out) } cmd = exec.Command(dockerBinary, "run", "--name", "test", oldRepo, "touch", "/home/abcd") out, _, err = runCommandWithOutput(cmd) if err != nil { c.Fatalf("failed to run container: %v, output: %s", err, out) } cmd = exec.Command(dockerBinary, "commit", "test", newTag) out, _, err = runCommandWithOutput(cmd) if err != nil { c.Fatalf("failed to commit container: %v, output: %s", err, out) } cmd = exec.Command(dockerBinary, "rmi", newTag) out, _, err = runCommandWithOutput(cmd) if err != nil { c.Fatalf("failed to remove image: %v, output: %s", err, out) } if !strings.Contains(out, "Untagged: "+newTag) { c.Fatalf("Could not remove image %s: %s, %v", newTag, out, err) } }
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) { name := "exportcontainer" runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test") out, _, err := runCommandWithOutput(runCmd) if err != nil { c.Fatalf("Error on container creation: %v, output: %q", err, out) } status, body, err := sockRequest("GET", "/containers/"+name+"/export", nil) c.Assert(status, check.Equals, http.StatusOK) c.Assert(err, check.IsNil) found := false for tarReader := tar.NewReader(bytes.NewReader(body)); ; { h, err := tarReader.Next() if err != nil { if err == io.EOF { break } c.Fatal(err) } if h.Name == "test" { found = true break } } if !found { c.Fatalf("The created test file has not been found in the exported image") } }
func (s *DockerSuite) TestContainerApiGetChanges(c *check.C) { testRequires(c, DaemonIsLinux) name := "changescontainer" dockerCmd(c, "run", "--name", name, "busybox", "rm", "/etc/passwd") status, body, err := sockRequest("GET", "/containers/"+name+"/changes", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) changes := []struct { Kind int Path string }{} if err = json.Unmarshal(body, &changes); err != nil { c.Fatalf("unable to unmarshal response body: %v", err) } // Check the changelog for removal of /etc/passwd success := false for _, elem := range changes { if elem.Path == "/etc/passwd" && elem.Kind == 2 { success = true } } if !success { c.Fatalf("/etc/passwd has been removed but is not present in the diff") } }
func (s *DockerSuite) TestContainerApiCommit(c *check.C) { cName := "testapicommit" out, err := exec.Command(dockerBinary, "run", "--name="+cName, "busybox", "/bin/sh", "-c", "touch /test").CombinedOutput() if err != nil { c.Fatal(err, out) } name := "TestContainerApiCommit" status, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+cName, nil) c.Assert(status, check.Equals, http.StatusCreated) c.Assert(err, check.IsNil) type resp struct { Id string } var img resp if err := json.Unmarshal(b, &img); err != nil { c.Fatal(err) } cmd, err := inspectField(img.Id, "Config.Cmd") if err != nil { c.Fatal(err) } if cmd != "{[/bin/sh -c touch /test]}" { c.Fatalf("got wrong Cmd from commit: %q", cmd) } // sanity check, make sure the image is what we think it is out, err = exec.Command(dockerBinary, "run", img.Id, "ls", "/test").CombinedOutput() if err != nil { c.Fatalf("error checking committed image: %v - %q", err, string(out)) } }
// Test for GH#10618 func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) { testRequires(c, DaemonIsLinux) name := "testdups" config := map[string]interface{}{ "Image": "busybox", "Volumes": map[string]struct{}{"/tmp": {}}, } status, _, err := sockRequest("POST", "/containers/create?name="+name, config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) bindPath1 := randomTmpDirPath("test1", daemonPlatform) bindPath2 := randomTmpDirPath("test2", daemonPlatform) config = map[string]interface{}{ "Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"}, } status, body, err := sockRequest("POST", "/containers/"+name+"/start", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusInternalServerError) if !strings.Contains(string(body), "Duplicate bind") { c.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err) } }
func (s *DockerSuite) TestContainerApiCreate(c *check.C) { config := map[string]interface{}{ "Image": "busybox", "Cmd": []string{"/bin/sh", "-c", "touch /test && ls /test"}, } status, b, err := sockRequest("POST", "/containers/create", config) c.Assert(status, check.Equals, http.StatusCreated) c.Assert(err, check.IsNil) type createResp struct { Id string } var container createResp if err := json.Unmarshal(b, &container); err != nil { c.Fatal(err) } out, err := exec.Command(dockerBinary, "start", "-a", container.Id).CombinedOutput() if err != nil { c.Fatal(out, err) } if strings.TrimSpace(string(out)) != "/test" { c.Fatalf("expected output `/test`, got %q", out) } }
// regression test for empty json field being omitted #13691 func (s *DockerSuite) TestContainerApiGetJSONNoFieldsOmitted(c *check.C) { testRequires(c, DaemonIsLinux) dockerCmd(c, "run", "busybox", "true") status, body, err := sockRequest("GET", "/containers/json?all=1", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) // empty Labels field triggered this bug, make sense to check for everything // cause even Ports for instance can trigger this bug // better safe than sorry.. fields := []string{ "Id", "Names", "Image", "Command", "Created", "Ports", "Labels", "Status", } // decoding into types.Container do not work since it eventually unmarshal // and empty field to an empty go map, so we just check for a string for _, f := range fields { if !strings.Contains(string(body), f) { c.Fatalf("Field %s is missing and it shouldn't", f) } } }
func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) { var ( expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}} result []string ) dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top") dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top") dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true") links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links") if err != nil { c.Fatal(err) } err = unmarshalJSON([]byte(links), &result) if err != nil { c.Fatal(err) } output := convertSliceOfStringsToMap(result) equal := reflect.DeepEqual(output, expected) if !equal { c.Fatalf("Links %s, but expected %s", result, expected) } }
func (s *DockerSuite) TestContainerApiBadPort(c *check.C) { testRequires(c, DaemonIsLinux) config := map[string]interface{}{ "Image": "busybox", "Cmd": []string{"/bin/sh", "-c", "echo test"}, "PortBindings": map[string]interface{}{ "8080/tcp": []map[string]interface{}{ { "HostIP": "", "HostPort": "aa80", }, }, }, } jsonData := bytes.NewBuffer(nil) json.NewEncoder(jsonData).Encode(config) status, b, err := sockRequest("POST", "/containers/create", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusInternalServerError) if strings.TrimSpace(string(b)) != `Invalid port specification: "aa80"` { c.Fatalf("Incorrect error msg: %s", string(b)) } }
func (s *DockerDaemonSuite) TestExecAfterDaemonRestart(c *check.C) { testRequires(c, SameHostDaemon) if err := s.d.StartWithBusybox(); err != nil { c.Fatalf("Could not start daemon with busybox: %v", err) } if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { c.Fatalf("Could not run top: err=%v\n%s", err, out) } if err := s.d.Restart(); err != nil { c.Fatalf("Could not restart daemon: %v", err) } if out, err := s.d.Cmd("start", "top"); err != nil { c.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out) } out, err := s.d.Cmd("exec", "top", "echo", "hello") if err != nil { c.Fatalf("Could not exec on container top: err=%v\n%s", err, out) } outStr := strings.TrimSpace(string(out)) if outStr != "hello" { c.Errorf("container should've printed hello, instead printed %q", outStr) } }
func UtilCreateNetworkMode(c *check.C, networkMode string) { config := map[string]interface{}{ "Image": "busybox", "HostConfig": map[string]interface{}{"NetworkMode": networkMode}, } status, body, err := sockRequest("POST", "/containers/create", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) var container types.ContainerCreateResponse if err := json.Unmarshal(body, &container); err != nil { c.Fatal(err) } status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) var containerJSON types.ContainerJSON if err := json.Unmarshal(body, &containerJSON); err != nil { c.Fatal(err) } if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) { c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode) } }
func (s *DockerSwarmSuite) TestServiceUpdatePort(c *check.C) { d := s.AddDaemon(c, true, true) serviceName := "TestServiceUpdatePort" serviceArgs := append([]string{"create", "--name", serviceName, "-p", "8080:8081", defaultSleepImage}, defaultSleepCommand...) // Create a service with a port mapping of 8080:8081. out, err := d.Cmd("service", serviceArgs...) c.Assert(err, checker.IsNil) waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1) // Update the service: changed the port mapping from 8080:8081 to 8082:8083. _, err = d.Cmd("service", "update", "-p", "8082:8083", serviceName) c.Assert(err, checker.IsNil) // Inspect the service and verify port mapping expected := []swarm.PortConfig{ { Protocol: "tcp", PublishedPort: 8082, TargetPort: 8083, }, } out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.EndpointSpec.Ports }}", serviceName) c.Assert(err, checker.IsNil) var portConfig []swarm.PortConfig if err := json.Unmarshal([]byte(out), &portConfig); err != nil { c.Fatalf("invalid JSON in inspect result: %v (%s)", err, out) } c.Assert(portConfig, checker.DeepEquals, expected) }
// TestRunSeccompProfileDenyUnshare checks that 'docker run --security-opt seccomp=/tmp/profile.json debian:jessie unshare' exits with operation not permitted. func (s *DockerSuite) TestRunSeccompProfileDenyUnshare(c *check.C) { testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor) jsonData := `{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "unshare", "action": "SCMP_ACT_ERRNO" } ] }` tmpFile, err := ioutil.TempFile("", "profile.json") defer tmpFile.Close() if err != nil { c.Fatal(err) } if _, err := tmpFile.Write([]byte(jsonData)); err != nil { c.Fatal(err) } runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc") out, _, _ := runCommandWithOutput(runCmd) if !strings.Contains(out, "Operation not permitted") { c.Fatalf("expected unshare with seccomp profile denied to fail, got %s", out) } }
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) { testRequires(c, DaemonIsLinux) name := "exportcontainer" dockerCmd(c, "run", "--name", name, "busybox", "touch", "/test") status, body, err := sockRequest("GET", "/containers/"+name+"/export", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) found := false for tarReader := tar.NewReader(bytes.NewReader(body)); ; { h, err := tarReader.Next() if err != nil { if err == io.EOF { break } c.Fatal(err) } if h.Name == "test" { found = true break } } if !found { c.Fatalf("The created test file has not been found in the exported image") } }
// TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to // deny unhare of a userns exits with operation not permitted. func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) { testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor) // from sched.h jsonData := fmt.Sprintf(`{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "unshare", "action": "SCMP_ACT_ERRNO", "args": [ { "index": 0, "value": %d, "op": "SCMP_CMP_EQ" } ] } ] }`, uint64(0x10000000)) tmpFile, err := ioutil.TempFile("", "profile.json") defer tmpFile.Close() if err != nil { c.Fatal(err) } if _, err := tmpFile.Write([]byte(jsonData)); err != nil { c.Fatal(err) } runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami") out, _, _ := runCommandWithOutput(runCmd) if !strings.Contains(out, "Operation not permitted") { c.Fatalf("expected unshare userns with seccomp profile denied to fail, got %s", out) } }
func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindLocalVolume(c *check.C) { if err := s.d.StartWithBusybox(); err != nil { c.Fatal(err) } expected := s.server.URL dockerfile := fmt.Sprintf(`FROM busybox:latest RUN mkdir /nobindthenlocalvol RUN echo %s > /nobindthenlocalvol/test VOLUME ["/nobindthenlocalvol"]`, expected) img := "test-checkbindlocalvolume" args := []string{"--host", s.d.sock()} buildOut, err := buildImageArgs(args, img, dockerfile, true) fmt.Println(buildOut) out, err := s.d.Cmd("run", "--rm", "--name", "test-data-nobind", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", img, "cat", "/nobindthenlocalvol/test") if err != nil { fmt.Println(out) c.Fatal(err) } if !strings.Contains(out, expected) { c.Fatalf("External volume mount failed. Output: %s\n", out) } c.Assert(s.ec.activations, check.Equals, 1) c.Assert(s.ec.creations, check.Equals, 1) c.Assert(s.ec.removals, check.Equals, 1) c.Assert(s.ec.mounts, check.Equals, 1) c.Assert(s.ec.unmounts, check.Equals, 1) }