fix: skip retiring images still in use by app containers
When ps:rebuild runs against an image-based deploy via git:from-image, the resulting image often shares the same SHA as the previous deployment, so retiring the old container's image would target the live image of the new container. The retirement is now skipped when another running container of the same app still references the image, and the cron retire loop self-heals previously stuck entries the next time it encounters them.
This commit is contained in:
@@ -243,6 +243,11 @@ fn-scheduler-docker-local-retire-images() {
|
||||
fi
|
||||
|
||||
if echo "$RM_OUTPUT" | grep -q "image is being used by running container"; then
|
||||
if fn-scheduler-docker-local-image-in-use-by-app "$RETIRE_APP" "$IMAGE_ID" ""; then
|
||||
dokku_log_warn "Image ${IMAGE_ID} is still in use by ${RETIRE_APP}, removing from retire list"
|
||||
DEAD_IMAGES+=("$IMAGE_ID")
|
||||
continue
|
||||
fi
|
||||
dokku_log_warn "Image ${IMAGE_ID} has running containers, skipping rm"
|
||||
continue
|
||||
fi
|
||||
@@ -273,6 +278,39 @@ fn-scheduler-docker-local-register-retired() {
|
||||
fi
|
||||
}
|
||||
|
||||
fn-scheduler-docker-local-image-in-use-by-app() {
|
||||
declare desc="returns 0 if IMAGE_ID is used by an app container that is not already pending retirement"
|
||||
declare APP="$1" IMAGE_ID="$2" EXCLUDE_CONTAINER_ID="$3"
|
||||
local DEAD_CONTAINER_FILE="${DOKKU_LIB_ROOT}/data/scheduler-docker-local/dead-containers"
|
||||
local cid exclude_full_id container_image short_cid
|
||||
|
||||
if [[ -z "$IMAGE_ID" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -n "$EXCLUDE_CONTAINER_ID" ]]; then
|
||||
exclude_full_id="$("$DOCKER_BIN" container inspect "$EXCLUDE_CONTAINER_ID" --format '{{.Id}}' 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
for cid in $("$DOCKER_BIN" container ls -q --no-trunc -f label=com.dokku.app-name="$APP" 2>/dev/null); do
|
||||
[[ -z "$cid" ]] && continue
|
||||
if [[ -n "$exclude_full_id" ]] && [[ "$cid" == "$exclude_full_id" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
short_cid="${cid:0:12}"
|
||||
if [[ -f "$DEAD_CONTAINER_FILE" ]] && grep -q "$short_cid" "$DEAD_CONTAINER_FILE"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
container_image="$("$DOCKER_BIN" container inspect "$cid" --format '{{.Image}}' 2>/dev/null | cut -d: -f2 || true)"
|
||||
if [[ -n "$container_image" ]] && [[ "$container_image" == "$IMAGE_ID" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
fn-scheduler-docker-local-start-app-container() {
|
||||
declare desc="starts a single app container"
|
||||
declare APP="$1"
|
||||
|
||||
@@ -21,12 +21,17 @@ trigger-scheduler-docker-local-scheduler-register-retired() {
|
||||
if [[ -n "$IMAGE_ID" ]] && [[ -z "$DOKKU_SKIP_IMAGE_CLEANUP_REGISTRATION" ]]; then
|
||||
ALT_IMAGE_TAGS="$("$DOCKER_BIN" image inspect --format '{{ index .Config.Labels "com.dokku.docker-image-labeler/alternate-tags" }}' "$IMAGE_ID" 2>/dev/null || true)"
|
||||
|
||||
fn-scheduler-docker-local-register-retired "image" "$APP" "$IMAGE_ID" "$WAIT"
|
||||
if ! fn-scheduler-docker-local-image-in-use-by-app "$APP" "$IMAGE_ID" "$CONTAINER_ID"; then
|
||||
fn-scheduler-docker-local-register-retired "image" "$APP" "$IMAGE_ID" "$WAIT"
|
||||
fi
|
||||
if [[ -n "$ALT_IMAGE_TAGS" ]]; then
|
||||
ALT_IMAGE_TAG="$(echo "$ALT_IMAGE_TAGS" | jq -r ".[]")"
|
||||
if [[ "$(plugn trigger git-get-property "$APP" "source-image")" != "$ALT_IMAGE_TAG" ]]; then
|
||||
ALT_IMAGE_ID="$("$DOCKER_BIN" image inspect --format '{{ .Id }}' "$ALT_IMAGE_TAG" 2>/dev/null || true)"
|
||||
fn-scheduler-docker-local-register-retired "image" "$APP" "$(echo "$ALT_IMAGE_ID" | cut -d ':' -f2)" "$WAIT"
|
||||
ALT_IMAGE_ID="$(echo "$ALT_IMAGE_ID" | cut -d ':' -f2)"
|
||||
if [[ -n "$ALT_IMAGE_ID" ]] && ! fn-scheduler-docker-local-image-in-use-by-app "$APP" "$ALT_IMAGE_ID" "$CONTAINER_ID"; then
|
||||
fn-scheduler-docker-local-register-retired "image" "$APP" "$ALT_IMAGE_ID" "$WAIT"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user