Stop a Docker Resource step template does not actually stop the container

Upgraded to 3.8.6 for Docker support.

Created a Run a Docker Container step to deploy to a Windows Server 2016 on AWS.

The docker container is deployed and runs fine.

Trying to deploy the next version of the container, I realise you need to stop and remove the old one first and find the Stop a Docker Resource step template conveniently there. I create the process step from it and it fails to stop the running container with the following error

February 10th 2017 15:13:35Info
Performing `docker stop` command on 'Test-DockerServer'
Using filter: --filter label=Octopus.Project.Id=Projects-3
Stopping container: /pensive_thompson
Removing container: /pensive_thompson
February 10th 2017 15:13:36Error
Error response from daemon: You cannot remove a running container 58e256303441760ac5865a4295ebbfe8d7d1e16d8136541e610161d8d8be20a7. Stop the container before attempting removal or use -f
The remote script failed with exit code 1
February 10th 2017 15:13:36Fatal
Stop and Remove last Core Service container on Test-DockerServer

I have intercepted the Script.ps1 that is pushed with the deployment and it does not actually execute any command to stop the container at the function StopAllContainers() after printing to console that it is doing it Write-Host Stopping container:… The script proceeds to remove a still running container and naturally blows up

function StopAllContainers(){
    ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-3")){
        Write-Host Stopping container: $(docker inspect --format="{{.Name}}" $container)
    }
}
...
function RemoveAllContainers(){
    ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-3")) {
        Write-Host Removing container: $(docker inspect --format="{{.Name}}" $container)
        (docker rm $container)  | out-null
    }
}
...

if ([string]::IsNullOrEmpty($STEPS_TO_REMOVE)){
    RemoveAllNetworks;
    StopAllContainers;
    RemoveAllContainers;
} else {
    $STEPS_TO_REMOVE.Split(" ") | ForEach {
        RemoveNetwork($_);
        StopContainer($_);
        RemoveContainer($_);
     }
}

Please fix the function StopAllContainers() to do what it is supposed to do with something like (docker stop $container) | out-null

function StopAllContainers(){
    ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-3")){
        Write-Host Stopping container: $(docker inspect --format="{{.Name}}" $container)
        (docker stop $container)  | out-null
    }
}

I appreciate that Docker on Windows is not the most popular option and that we are possibly the only ones trying to use it judging by the lack of similar issues raised. I realise it may not be high on your priority list to QA the feature before releasing it, but I do appreciate it that it has become available at least in the state that it is in right now and we can incorporate it into our CI/CD process.

Please make this available in the coming release, as it is a very easy fix.

Hi Alexy,
Thanks for brining this to our attention. At the time of developing the Docker feature in Octopus Deploy, support for Docker on Windows was (/is) still quite immature and flakey around the edges. For this reason we made recommendations to use Linux for the time being where possible as we didn’t want to invest too much time developing for a platform that still had to find its legs.

Looking at the issue you noticed in the DockerStop scripting, this however looks like it could be an easy win so I have logged an issue in GitHub to get the stop feature working a bit better. It should go out sometime this week. I’ll note though that support for networking is still not fully fleshed out for Windows so that will need to be addressed in a future change.

I hope this update helps you to get your deployments back on track. Give it a go when its released this week, and let me know if you encounter any issues.
Cheers,
Rob

Thanks for fixing the above edge-case. I upgraded to 3.11.1 and see that fix in Script.ps1 would work in the case of if ([string]::IsNullOrEmpty($STEPS_TO_REMOVE)){

But running that step now, I see the } else { condition is actually being triggered now and there is a bug there that prevents the previously deployed container being stopped and removed, which also needs fixing. The intercepted Script.ps1 contains a non-empty $StepsToRemove=",f23ccae8-ea35-4d93-80fd-ebc72d052215"; which triggers the } else { condition, but fails to $StepsToRemove.Split(" ") since the separator is not a space " " but a comma "," and thus the [string] $actionId passed to each function is not in the right format to match the filter therein

Write-Host Using filter:  --filter "label=Octopus.Project.Id=Projects-61";

$StepsToRemove=",f23ccae8-ea35-4d93-80fd-ebc72d052215";
...

 function StopContainer([string] $actionId) {
    ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-61" --filter "label=Octopus.Action.Id=$actionId")) {
        Write-Host Stopping container: $(docker inspect --format="{{.Name}}" $container)
        (docker stop $container ) | out-null
    }
}

 function RemoveContainer([string] $actionId) {
    ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-61" --filter "label=Octopus.Action.Id=$actionId")) {
        Write-Host Removing container: $(docker inspect --format="{{.Name}}" $container)
        (docker rm $container) | out-null
    }
}

if ([string]::IsNullOrEmpty($StepsToRemove)){
    RemoveAllNetworks;
    StopAllContainers;
    RemoveAllContainers;
} else {
    $StepsToRemove.Split(" ") | ForEach {
        RemoveNetwork($_);
        StopContainer($_);
        RemoveContainer($_);
     }
}

Here is the powershell debug session to demonstrate the containers deployed and the bug failing to list them for stop and remove functions

PS C:\Users\Administrator> docker ps
CONTAINER ID        IMAGE                                                                 COMMAND    CREATED              STATUS              PORTS               NAMES
646c8742eb3b        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   About a minute ago   Up About a minute                       romantic_heisenberg
a9481324d6f2        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   About a minute ago   Up About a minute                       elegant_leakey
1823dd794488        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   2 minutes ago        Up 2 minutes                            hopeful_curran
8c740e36f59f        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   3 minutes ago        Up 3 minutes                            kickass_yalow
179f0021cc68        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   3 minutes ago        Up 3 minutes                            kickass_bohr
79708f0408b1        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   6 minutes ago        Up 6 minutes                            gigantic_hamilton
a88e846407b1        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.25   "P.T..."   9 minutes ago        Up 9 minutes                            tender_payne
4906befb9ae0        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.23   "P.T..."   17 minutes ago       Up 17 minutes                           sleepy_kilby
d2d66392a2ee        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-c-s:1.0.0.23   "P.T..."   About an hour ago    Up About an hour                        prickly_brahmagupta
b3d870c0feb3        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-d-s:1.0.0.37   "pow..."   2 days ago           Up 2 days           80/tcp              silly_wilson
cd00e9c3e614        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-o-s:1.0.0.54   "P.T..."   2 days ago           Up 2 days                               prickly_noyce
2094b24144c2        26xxx15.dkr.ecr.ap-xxx-2.amazonaws.com/microservices/t-r-s:1.0.0.51   "P.T..."   5 days ago           Up 3 days                               infallible_leakey
PS C:\Users\Administrator> $StepsToRemove=",f23ccae8-ea35-4d93-80fd-ebc72d052215";
PS C:\Users\Administrator> $StepsToRemove.Split(" ")
,f23ccae8-ea35-4d93-80fd-ebc72d052215
PS C:\Users\Administrator> $StepsToRemove.Split(" ") | ForEach {Write-Host $_}
,f23ccae8-ea35-4d93-80fd-ebc72d052215
PS C:\Users\Administrator>  $StepsToRemove.Split(" ") | ForEach {ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-61" --filter "label=Octopus.Action.Id=$_")) {Write-Host $container}}
PS C:\Users\Administrator>  $StepsToRemove.Split(",") | ForEach {ForEach($container in $(docker ps -a -q  --filter "label=Octopus.Project.Id=Projects-61" --filter "label=Octopus.Action.Id=$_")) {Write-Host $container}}
646c8742eb3b
a9481324d6f2
1823dd794488
8c740e36f59f
179f0021cc68
79708f0408b1
a88e846407b1
4906befb9ae0
d2d66392a2ee

As you can see, splitting by "," would work, while splitting by " " fails.

So the fix would be to either split by comma in $StepsToRemove.Split(",") | ForEach {

$StepsToRemove=",f23ccae8-ea35-4d93-80fd-ebc72d052215";
...
if ([string]::IsNullOrEmpty($StepsToRemove)){
    RemoveAllNetworks;
    StopAllContainers;
    RemoveAllContainers;
} else {
    $StepsToRemove.Split(",") | ForEach {
        RemoveNetwork($_);
        StopContainer($_);
        RemoveContainer($_);
     }
}

Or joining values in $StepsToRemove with spaces " " instead of commas ","

$StepsToRemove="f23ccae8-ea35-4d93-80fd-ebc72d052215 f23ccae8-ea35-4d93-80fd-ebc72d052215";
...
if ([string]::IsNullOrEmpty($StepsToRemove)){
    RemoveAllNetworks;
    StopAllContainers;
    RemoveAllContainers;
} else {
    $StepsToRemove.Split(" ") | ForEach {
        RemoveNetwork($_);
        StopContainer($_);
        RemoveContainer($_);
     }
}

and preferably without a leading comma\space separator, as that would generate an empty string as the first value of the .Split() function

PS C:\Users\Administrator> $StepsToRemove=",f23ccae8-ea35-4d93-80fd-ebc72d052215";
PS C:\Users\Administrator> $StepsToRemove.Split(",") | ForEach {Write-Host "actionId='$_'"}
actionId=''
actionId='f23ccae8-ea35-4d93-80fd-ebc72d052215'

PS C:\Users\Administrator> $StepsToRemove=" f23ccae8-ea35-4d93-80fd-ebc72d052215 f23ccae8-ea35-4d93-80fd-ebc72d052215";
PS C:\Users\Administrator> $StepsToRemove.Split(" ") | ForEach {Write-Host "actionId='$_'"}
actionId=''
actionId='f23ccae8-ea35-4d93-80fd-ebc72d052215'
actionId='f23ccae8-ea35-4d93-80fd-ebc72d052215'

Hi Alexy,
Thanks again. I have got a fix ready that should go out in the next 3.11.3 release. The support for Docker on Windows really needs a bit of love.
Cheers,
Rob

Upgraded to 3.11.3 and was able to successfully deploy the next version of the docker container with the step to automatically stop and remove the prior version.

Thanks for fixing it! Really looking forward to further windows docker support from Octopus.