Skip to content

Commit 2f85d32

Browse files
gfraiteurclaude
andcommitted
Add Docker container reuse for interactive sessions and fix bug
Optimize DockerBuild.ps1 to detect and reuse existing containers in interactive mode instead of killing and recreating them. This improves developer experience by avoiding unnecessary container restarts. Also removes erroneous undefined variable reference in docker command execution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent 0553883 commit 2f85d32

File tree

2 files changed

+130
-78
lines changed

2 files changed

+130
-78
lines changed

DockerBuild.ps1

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -641,55 +641,68 @@ Write-Host "Volume mappings: " @VolumeMappings -ForegroundColor Gray
641641
Write-Host "Mount points: " $mountPointsAsString -ForegroundColor Gray
642642
Write-Host "Git directories: " $gitDirectoriesAsString -ForegroundColor Gray
643643

644-
# Kill all containers
645-
docker ps -q --filter "ancestor=$ImageTag" | ForEach-Object {
646-
Write-Host "Killing container $_"
647-
docker kill $_
644+
# Check if a container is already running with this image (only for interactive scenarios)
645+
$existingContainerId = $null
646+
647+
if ($Interactive)
648+
{
649+
# Check for existing container
650+
$existingContainerId = docker ps -q --filter "ancestor=$ImageTag" | Select-Object -First 1
651+
if ($existingContainerId)
652+
{
653+
Write-Host "Found existing container $existingContainerId running with image $ImageTag" -ForegroundColor Cyan
654+
Write-Host "Will reuse existing container instead of starting a new one." -ForegroundColor Cyan
655+
$ImageTag = $searchImageTag
656+
}
657+
else
658+
{
659+
Write-Host "No existing container for $ImageTag."
660+
}
661+
}
662+
663+
# If no existing container, kill any stopped containers with same image to avoid conflicts
664+
if (-not $existingContainerId)
665+
{
666+
docker ps -q --filter "ancestor=$ImageTag" | ForEach-Object {
667+
Write-Host "Killing container $_"
668+
docker kill $_
669+
}
648670
}
649671

650672
# Building the image.
651-
if (-not $NoBuildImage)
673+
if (-not $NoBuildImage -and -not $existingContainerId)
652674
{
675+
653676
if ($Claude)
654677
{
655-
# Build Claude image directly from standalone Dockerfile.claude
656-
$ImageTag = "$ImageTag-claude"
657-
Write-Host "Building the Claude image with tag: $ImageTag" -ForegroundColor Green
658-
659-
if (-not (Test-Path "Dockerfile.claude"))
660-
{
661-
Write-Error "Dockerfile.claude not found. Make sure generate-scripts was run with Claude support."
662-
exit 1
663-
}
664-
665-
Get-Content -Raw Dockerfile.claude | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
666-
if ($LASTEXITCODE -ne 0)
667-
{
668-
Write-Host "Docker build (Claude) failed with exit code $LASTEXITCODE" -ForegroundColor Red
669-
exit $LASTEXITCODE
670-
}
678+
$Dockerfile = "Dockerfile.claude"
671679
}
672680
else
673681
{
674-
# Build base image
675-
Write-Host "Building the base image with tag: $ImageTag" -ForegroundColor Green
676-
Get-Content -Raw Dockerfile | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
677-
if ($LASTEXITCODE -ne 0)
678-
{
679-
Write-Host "Docker build failed with exit code $LASTEXITCODE" -ForegroundColor Red
680-
exit $LASTEXITCODE
681-
}
682+
$Dockerfile = "Dockerfile"
683+
}
684+
685+
686+
Write-Host "Building the image with tag: $ImageTag" -ForegroundColor Green
687+
Get-Content -Raw $Dockerfile | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
688+
if ($LASTEXITCODE -ne 0)
689+
{
690+
Write-Host "Docker build failed with exit code $LASTEXITCODE" -ForegroundColor Red
691+
exit $LASTEXITCODE
682692
}
683693
}
684694
else
685695
{
686-
Write-Host "Skipping image build (-NoBuildImage specified)." -ForegroundColor Yellow
687-
688-
# If Claude mode and skipping build, use the Claude image tag
689-
if ($Claude)
696+
if ($existingContainerId)
697+
{
698+
Write-Host "Skipping image build (reusing existing container $existingContainerId)." -ForegroundColor Yellow
699+
}
700+
else
690701
{
691-
$ImageTag = "$ImageTag-claude"
702+
Write-Host "Skipping image build (-NoBuildImage specified)." -ForegroundColor Yellow
692703
}
704+
705+
693706
}
694707

695708

@@ -867,9 +880,9 @@ if (-not $BuildImage)
867880
$envArgs += @("-e", "MCP_APPROVAL_SERVER_TOKEN=$mcpSecret")
868881
}
869882

870-
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
871-
872883
try {
884+
# Start new container with docker run
885+
Write-Host "Executing: docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
873886
docker run --rm --memory=12g $dockerArgs @volumeArgs @envArgs -w $ContainerSourceDir $ImageTag $pwshPath -Command $inlineScript
874887
$dockerExitCode = $LASTEXITCODE
875888
}
@@ -967,12 +980,25 @@ if (-not $BuildImage)
967980
$inlineScript = "${substCommandsInline}& c:\Init.g.ps1; cd '$SourceDirName'; & .\$Script $buildArgsString; $pwshExitCommand"
968981

969982
$pwshPath = 'C:\Program Files\PowerShell\7\pwsh.exe'
970-
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
971983

972-
docker run --rm --memory=12g $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
984+
# Build docker command arguments
985+
if ($existingContainerId)
986+
{
987+
# Reuse existing container with docker exec
988+
Write-Host "Executing: ``docker exec $existingContainerId $dockerArgsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
989+
docker exec $dockerArgs -w $ContainerSourceDir $existingContainerId $pwshPath $pwshArgs -Command $inlineScript
990+
991+
}
992+
else
993+
{
994+
# Start new container with docker run
995+
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
996+
docker run --rm --memory=12g $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
997+
}
998+
973999
if ($LASTEXITCODE -ne 0)
9741000
{
975-
Write-Host "Docker run (build) failed with exit code $LASTEXITCODE" -ForegroundColor Red
1001+
Write-Host "Container failed with exit code $LASTEXITCODE" -ForegroundColor Red
9761002
exit $LASTEXITCODE
9771003
}
9781004
}

src/PostSharp.Engineering.BuildTools/Resources/DockerBuild.ps1

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -641,55 +641,68 @@ Write-Host "Volume mappings: " @VolumeMappings -ForegroundColor Gray
641641
Write-Host "Mount points: " $mountPointsAsString -ForegroundColor Gray
642642
Write-Host "Git directories: " $gitDirectoriesAsString -ForegroundColor Gray
643643

644-
# Kill all containers
645-
docker ps -q --filter "ancestor=$ImageTag" | ForEach-Object {
646-
Write-Host "Killing container $_"
647-
docker kill $_
644+
# Check if a container is already running with this image (only for interactive scenarios)
645+
$existingContainerId = $null
646+
647+
if ($Interactive)
648+
{
649+
# Check for existing container
650+
$existingContainerId = docker ps -q --filter "ancestor=$ImageTag" | Select-Object -First 1
651+
if ($existingContainerId)
652+
{
653+
Write-Host "Found existing container $existingContainerId running with image $ImageTag" -ForegroundColor Cyan
654+
Write-Host "Will reuse existing container instead of starting a new one." -ForegroundColor Cyan
655+
$ImageTag = $searchImageTag
656+
}
657+
else
658+
{
659+
Write-Host "No existing container for $ImageTag."
660+
}
661+
}
662+
663+
# If no existing container, kill any stopped containers with same image to avoid conflicts
664+
if (-not $existingContainerId)
665+
{
666+
docker ps -q --filter "ancestor=$ImageTag" | ForEach-Object {
667+
Write-Host "Killing container $_"
668+
docker kill $_
669+
}
648670
}
649671

650672
# Building the image.
651-
if (-not $NoBuildImage)
673+
if (-not $NoBuildImage -and -not $existingContainerId)
652674
{
675+
653676
if ($Claude)
654677
{
655-
# Build Claude image directly from standalone Dockerfile.claude
656-
$ImageTag = "$ImageTag-claude"
657-
Write-Host "Building the Claude image with tag: $ImageTag" -ForegroundColor Green
658-
659-
if (-not (Test-Path "Dockerfile.claude"))
660-
{
661-
Write-Error "Dockerfile.claude not found. Make sure generate-scripts was run with Claude support."
662-
exit 1
663-
}
664-
665-
Get-Content -Raw Dockerfile.claude | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
666-
if ($LASTEXITCODE -ne 0)
667-
{
668-
Write-Host "Docker build (Claude) failed with exit code $LASTEXITCODE" -ForegroundColor Red
669-
exit $LASTEXITCODE
670-
}
678+
$Dockerfile = "Dockerfile.claude"
671679
}
672680
else
673681
{
674-
# Build base image
675-
Write-Host "Building the base image with tag: $ImageTag" -ForegroundColor Green
676-
Get-Content -Raw Dockerfile | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
677-
if ($LASTEXITCODE -ne 0)
678-
{
679-
Write-Host "Docker build failed with exit code $LASTEXITCODE" -ForegroundColor Red
680-
exit $LASTEXITCODE
681-
}
682+
$Dockerfile = "Dockerfile"
683+
}
684+
685+
686+
Write-Host "Building the image with tag: $ImageTag" -ForegroundColor Green
687+
Get-Content -Raw $Dockerfile | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
688+
if ($LASTEXITCODE -ne 0)
689+
{
690+
Write-Host "Docker build failed with exit code $LASTEXITCODE" -ForegroundColor Red
691+
exit $LASTEXITCODE
682692
}
683693
}
684694
else
685695
{
686-
Write-Host "Skipping image build (-NoBuildImage specified)." -ForegroundColor Yellow
687-
688-
# If Claude mode and skipping build, use the Claude image tag
689-
if ($Claude)
696+
if ($existingContainerId)
697+
{
698+
Write-Host "Skipping image build (reusing existing container $existingContainerId)." -ForegroundColor Yellow
699+
}
700+
else
690701
{
691-
$ImageTag = "$ImageTag-claude"
702+
Write-Host "Skipping image build (-NoBuildImage specified)." -ForegroundColor Yellow
692703
}
704+
705+
693706
}
694707

695708

@@ -867,9 +880,9 @@ if (-not $BuildImage)
867880
$envArgs += @("-e", "MCP_APPROVAL_SERVER_TOKEN=$mcpSecret")
868881
}
869882

870-
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
871-
872883
try {
884+
# Start new container with docker run
885+
Write-Host "Executing: docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
873886
docker run --rm --memory=12g $dockerArgs @volumeArgs @envArgs -w $ContainerSourceDir $ImageTag $pwshPath -Command $inlineScript
874887
$dockerExitCode = $LASTEXITCODE
875888
}
@@ -967,12 +980,25 @@ if (-not $BuildImage)
967980
$inlineScript = "${substCommandsInline}& c:\Init.g.ps1; cd '$SourceDirName'; & .\$Script $buildArgsString; $pwshExitCommand"
968981

969982
$pwshPath = 'C:\Program Files\PowerShell\7\pwsh.exe'
970-
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
971983

972-
docker run --rm --memory=12g $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
984+
# Build docker command arguments
985+
if ($existingContainerId)
986+
{
987+
# Reuse existing container with docker exec
988+
Write-Host "Executing: ``docker exec $existingContainerId $dockerArgsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
989+
docker exec $dockerArgs -w $ContainerSourceDir $existingContainerId $pwshPath $pwshArgs -Command $inlineScript
990+
991+
}
992+
else
993+
{
994+
# Start new container with docker run
995+
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
996+
docker run --rm --memory=12g $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
997+
}
998+
973999
if ($LASTEXITCODE -ne 0)
9741000
{
975-
Write-Host "Docker run (build) failed with exit code $LASTEXITCODE" -ForegroundColor Red
1001+
Write-Host "Container failed with exit code $LASTEXITCODE" -ForegroundColor Red
9761002
exit $LASTEXITCODE
9771003
}
9781004
}

0 commit comments

Comments
 (0)