Park source container on duplicate so host ports can be reused
Release rolling / release (push) Has been cancelled
Release rolling / release (push) Has been cancelled
When duplicating with the same host ports, stop+rename the origin, deploy and verify the new container, then remove the parked source. Client precheck ignores ports owned only by the origin to avoid false blocks.
This commit is contained in:
+29
-7
@@ -759,12 +759,15 @@ export async function deployContainerWithSteps(args) {
|
||||
const state = { pulledOk: false }
|
||||
const replace = args.replace === true
|
||||
const fromAdd = args.source === 'add-container'
|
||||
const fromDuplicate = args.source === 'duplicate' || Boolean(args.sourceContainerId)
|
||||
const alwaysPull = args.alwaysPull !== false
|
||||
const jobLabel = replace
|
||||
? `Replace ${args.containerName || 'container'}`
|
||||
: fromAdd
|
||||
? `Create ${args.containerName || 'container'}`
|
||||
: `Deploy ${args.containerName || 'container'}`
|
||||
: fromDuplicate
|
||||
? `Duplicate ${args.containerName || 'container'}`
|
||||
: fromAdd
|
||||
? `Create ${args.containerName || 'container'}`
|
||||
: `Deploy ${args.containerName || 'container'}`
|
||||
|
||||
return runJob(
|
||||
jobLabel,
|
||||
@@ -782,6 +785,11 @@ export async function deployContainerWithSteps(args) {
|
||||
log(`Image=${args.image}`)
|
||||
log(`Always pull image: ${alwaysPull ? 'yes' : 'no (local if present)'}`)
|
||||
if (replace) log('Mode: replace existing container with same name')
|
||||
if (args.sourceContainerId) {
|
||||
log(
|
||||
`Origin: ${args.sourceContainerName || String(args.sourceContainerId).slice(0, 12)} — will stop+rename if name/ports conflict, remove after new container is verified`
|
||||
)
|
||||
}
|
||||
if (args.publishAllPorts) log('Publish all exposed ports: yes')
|
||||
if (args.ports?.length) log(`Ports: ${args.ports.join(', ')}`)
|
||||
if (args.volumes?.length) log(`Volumes: ${args.volumes.join(', ')}`)
|
||||
@@ -845,12 +853,18 @@ export async function deployContainerWithSteps(args) {
|
||||
},
|
||||
{
|
||||
id: 'create',
|
||||
label: replace ? 'Replace, create & start' : 'Create & start container',
|
||||
label: replace
|
||||
? 'Replace, create & start'
|
||||
: fromDuplicate
|
||||
? 'Swap origin, create & verify'
|
||||
: 'Create & start container',
|
||||
run: async ({ log }) => {
|
||||
log(
|
||||
replace
|
||||
? 'Removing previous container (if present), then creating…'
|
||||
: 'Creating and starting container…'
|
||||
: args.sourceContainerId
|
||||
? 'Parking origin if needed (stop+rename), then create/start/verify…'
|
||||
: 'Creating and starting container…'
|
||||
)
|
||||
// Only skip server pull when client pull already succeeded
|
||||
const payload = {
|
||||
@@ -863,7 +877,15 @@ export async function deployContainerWithSteps(args) {
|
||||
const res = await manager.request(Methods.deployContainer, payload)
|
||||
log(res?.message || `Container "${args.containerName}" is running`)
|
||||
if (res?.id) log(`ID: ${String(res.id).slice(0, 12)}`)
|
||||
if (replace) log('Previous container was replaced')
|
||||
if (res?.swapped) {
|
||||
log(
|
||||
res.parkedName
|
||||
? `Origin was parked then removed after verify (was ${res.parkedName})`
|
||||
: 'Origin was parked then removed after verify'
|
||||
)
|
||||
} else if (replace) {
|
||||
log('Previous container was replaced')
|
||||
}
|
||||
return res
|
||||
} catch (err) {
|
||||
const info = explainError(err, 'deployContainer')
|
||||
@@ -891,7 +913,7 @@ export async function deployContainerWithSteps(args) {
|
||||
],
|
||||
{
|
||||
peerId: manager.active?.id,
|
||||
icon: replace ? 'fa-recycle' : 'fa-rocket',
|
||||
icon: replace ? 'fa-recycle' : fromDuplicate ? 'fa-clone' : 'fa-rocket',
|
||||
subtitle: args.image || args.containerName || null,
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user