Redefine what the "latest" container means
Currently the latest container is the one that was created last. But if we have had a failed deployment that left two containers running that would not be the one we want. The second container could be in a restart loop for example. Instead we want the container that is running the image tagged as latest. As we now tag as latest after a successful deployment we can trust that that is a healthy container. In the case that there is no container running the latest image tag, we'll fall back to the latest container. This could happen if the deploy was halted in between the old container being stopped and the image being tagged as latest.
This commit is contained in:
@@ -49,7 +49,9 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
|
||||
|
||||
def current_running_container_id
|
||||
docker :ps, "--quiet", *filter_args(statuses: ACTIVE_DOCKER_STATUSES), "--latest"
|
||||
pipe \
|
||||
[ shell(chain(latest_image_container_id, latest_container_id)) ],
|
||||
[ :head, "-1" ]
|
||||
end
|
||||
|
||||
def container_id_for_version(version, only_running: false)
|
||||
@@ -57,13 +59,16 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
end
|
||||
|
||||
def current_running_version
|
||||
list_versions("--latest", statuses: ACTIVE_DOCKER_STATUSES)
|
||||
pipe \
|
||||
[ shell(chain(latest_image_container_name, latest_container_name)) ],
|
||||
[ :head, "-1" ],
|
||||
extract_version_from_name
|
||||
end
|
||||
|
||||
def list_versions(*docker_args, statuses: nil)
|
||||
pipe \
|
||||
docker(:ps, *filter_args(statuses: statuses), *docker_args, "--format", '"{{.Names}}"'),
|
||||
%(while read line; do echo ${line##{role.container_prefix}-}; done) # Extract SHA from "service-role-dest-SHA"
|
||||
extract_version_from_name
|
||||
end
|
||||
|
||||
|
||||
@@ -81,10 +86,43 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
[ role.container_prefix, version || config.version ].compact.join("-")
|
||||
end
|
||||
|
||||
def latest_image_id
|
||||
docker :image, :ls, *argumentize("--filter", "reference=#{config.latest_image}"), "--format", "'{{.ID}}'"
|
||||
end
|
||||
|
||||
def latest_image_container_id
|
||||
latest_image_container format: "--quiet"
|
||||
end
|
||||
|
||||
def latest_container_id
|
||||
latest_container format: "--quiet"
|
||||
end
|
||||
|
||||
def latest_image_container_name
|
||||
latest_image_container format: "--format '{{.Names}}'"
|
||||
end
|
||||
|
||||
def latest_container_name
|
||||
latest_container format: "--format '{{.Names}}'"
|
||||
end
|
||||
|
||||
def latest_image_container(format: nil)
|
||||
docker :ps, "--latest", *format, *filter_args(statuses: ACTIVE_DOCKER_STATUSES), "--filter", "ancestor=$(#{latest_image_id.join(" ")})"
|
||||
end
|
||||
|
||||
def latest_container(format:)
|
||||
docker :ps, "--latest", *format, *filter_args(statuses: ACTIVE_DOCKER_STATUSES)
|
||||
end
|
||||
|
||||
def filter_args(statuses: nil)
|
||||
argumentize "--filter", filters(statuses: statuses)
|
||||
end
|
||||
|
||||
def extract_version_from_name
|
||||
# Extract SHA from "service-role-dest-SHA"
|
||||
%(while read line; do echo ${line##{role.container_prefix}-}; done)
|
||||
end
|
||||
|
||||
def filters(statuses: nil)
|
||||
[ "label=service=#{config.service}" ].tap do |filters|
|
||||
filters << "label=destination=#{config.destination}" if config.destination
|
||||
|
||||
@@ -71,7 +71,7 @@ module Kamal::Commands
|
||||
end
|
||||
|
||||
def shell(command)
|
||||
[ :sh, "-c", "'#{command.flatten.join(" ").gsub("'", "'\\''")}'" ]
|
||||
[ :sh, "-c", "'#{command.flatten.join(" ").gsub("'", "'\\\\''")}'" ]
|
||||
end
|
||||
|
||||
def docker(*args)
|
||||
|
||||
Reference in New Issue
Block a user