diff --git a/Dockerfile b/Dockerfile index 0bb846cbc54db..8a361cedec48d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -191,10 +191,15 @@ RUN set -x \ && rm -rf "$GOPATH" # Get the "docker-py" source so we can run their integration tests -ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324 +ENV DOCKER_PY_COMMIT 4a08d04aef0595322e1b5ac7c52f28a931da85a5 RUN git clone https://github.com/docker/docker-py.git /docker-py \ && cd /docker-py \ && git checkout -q $DOCKER_PY_COMMIT \ + # To run integration tests docker-pycreds is required. + # Before running the integration tests conftest.py is + # loaded which results in loads auth.py that + # imports the docker-pycreds module. + && pip install docker-pycreds==0.2.1 \ && pip install -r test-requirements.txt # Install yamllint for validating swagger.yaml diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index e58e2f7e8d15e..2a6d0fdeafdea 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -142,11 +142,15 @@ RUN set -x \ && rm -rf "$GOPATH" # Get the "docker-py" source so we can run their integration tests -ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324 +ENV DOCKER_PY_COMMIT 4a08d04aef0595322e1b5ac7c52f28a931da85a5 RUN git clone https://github.com/docker/docker-py.git /docker-py \ && cd /docker-py \ && git checkout -q $DOCKER_PY_COMMIT \ && pip install wheel \ + # Before running the integration tests conftest.py is + # loaded which results in loads auth.py that + # imports the docker-pycreds module. + && pip install docker-pycreds==0.2.1 \ && pip install -r test-requirements.txt # Install yamllint for validating swagger.yaml diff --git a/api/swagger.yaml b/api/swagger.yaml index b59888c17bc08..b5c10eb5fb1d7 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -4165,7 +4165,7 @@ paths: $ref: "#/definitions/ErrorResponse" examples: application/json: - message: "You cannot remove a running container: c2ada9df5af8. Stop the container before attempting removal or use -f" + message: "You cannot remove a running container: c2ada9df5af8. Stop the container before attempting removal or force remove" 500: description: "server error" schema: diff --git a/daemon/delete.go b/daemon/delete.go index c27cef0d3cc3a..fd1759ee1c5e7 100644 --- a/daemon/delete.go +++ b/daemon/delete.go @@ -80,7 +80,12 @@ func (daemon *Daemon) rmLink(container *container.Container, name string) error func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemove, removeVolume bool) (err error) { if container.IsRunning() { if !forceRemove { - err := fmt.Errorf("You cannot remove a running container %s. Stop the container before attempting removal or use -f", container.ID) + state := container.StateString() + procedure := "Stop the container before attempting removal or force remove" + if state == "paused" { + procedure = "Unpause and then " + strings.ToLower(procedure) + } + err := fmt.Errorf("You cannot remove a %s container %s. %s", state, container.ID, procedure) return apierrors.NewRequestConflictError(err) } if err := daemon.Kill(container); err != nil { diff --git a/integration-cli/docker_cli_rm_test.go b/integration-cli/docker_cli_rm_test.go index 9188ea7fc2c22..13ef9561347fb 100644 --- a/integration-cli/docker_cli_rm_test.go +++ b/integration-cli/docker_cli_rm_test.go @@ -38,8 +38,10 @@ func (s *DockerSuite) TestRmContainerWithVolume(c *check.C) { func (s *DockerSuite) TestRmContainerRunning(c *check.C) { createRunningContainer(c, "foo") - _, _, err := dockerCmdWithError("rm", "foo") + res, _, err := dockerCmdWithError("rm", "foo") c.Assert(err, checker.NotNil, check.Commentf("Expected error, can't rm a running container")) + c.Assert(res, checker.Contains, "cannot remove a running container") + c.Assert(res, checker.Contains, "Stop the container before attempting removal or force remove") } func (s *DockerSuite) TestRmContainerForceRemoveRunning(c *check.C) { @@ -83,3 +85,31 @@ func (s *DockerSuite) TestRmInvalidContainer(c *check.C) { func createRunningContainer(c *check.C, name string) { runSleepingContainer(c, "-dt", "--name", name) } + +// #30842 +func (s *DockerSuite) TestRmRestartingContainer(c *check.C) { + name := "rst" + dockerCmd(c, "run", "--name", name, "--restart=always", "busybox", "date") + + res, _, err := dockerCmdWithError("rm", name) + c.Assert(err, checker.NotNil, check.Commentf("Expected error on rm a restarting container, got none")) + c.Assert(res, checker.Contains, "cannot remove a restarting container") + c.Assert(res, checker.Contains, "Stop the container before attempting removal or force remove") + dockerCmd(c, "rm", "-f", name) +} + +// #30842 +func (s *DockerSuite) TestRmPausedContainer(c *check.C) { + testRequires(c, IsPausable) + name := "psd" + dockerCmd(c, "run", "--name", name, "-d", "busybox", "sleep", "1m") + dockerCmd(c, "pause", name) + + res, _, err := dockerCmdWithError("rm", name) + c.Assert(err, checker.NotNil, check.Commentf("Expected error on rm a paused container, got none")) + c.Assert(res, checker.Contains, "cannot remove a paused container") + c.Assert(res, checker.Contains, "Unpause and then stop the container before attempting removal or force remove") + unpauseContainer(c, name) + dockerCmd(c, "stop", name) + dockerCmd(c, "rm", name) +}