Replaces our current host-based HTTP healthchecks with Docker healthchecks, and adds a new `healthcheck.cmd` config option that can be used to define a custom health check command. Also removes Traefik's healthchecks, since they are no longer necessary. When deploying a container that has a healthcheck defined, we wait for it to report a healthy status before stopping the old container that it replaces. Containers that don't have a healthcheck defined continue to wait for `MRSK.config.readiness_delay`. There are some pros and cons to using Docker healthchecks rather than checking from the host. The main advantages are: - Supports non-HTTP checks, and app-specific check scripts provided by a container. - When booting a container, allows MRSK to wait for a container to be healthy before shutting down the old container it replaces. This should be safer than relying on a timeout. - Containers with healthchecks won't be active in Traefik until they reach a healthy state, which prevents any traffic from being routed to them before they are ready. The main _disadvantage_ is that containers are now required to provide some way to check their health. Our default check assumes that `curl` is available in the container which, while common, won't always be the case.
54 lines
1.2 KiB
Ruby
54 lines
1.2 KiB
Ruby
class Mrsk::Commands::Healthcheck < Mrsk::Commands::Base
|
|
EXPOSED_PORT = 3999
|
|
|
|
def run
|
|
web = config.role(:web)
|
|
|
|
docker :run,
|
|
"--detach",
|
|
"--name", container_name_with_version,
|
|
"--publish", "#{EXPOSED_PORT}:#{config.healthcheck["port"]}",
|
|
"--label", "service=#{container_name}",
|
|
"-e", "MRSK_CONTAINER_NAME=\"#{container_name}\"",
|
|
*web.env_args,
|
|
*web.health_check_args,
|
|
*config.volume_args,
|
|
*web.option_args,
|
|
config.absolute_image,
|
|
web.cmd
|
|
end
|
|
|
|
def status
|
|
pipe container_id, xargs(docker(:inspect, "--format", DOCKER_HEALTH_STATUS_FORMAT))
|
|
end
|
|
|
|
def logs
|
|
pipe container_id, xargs(docker(:logs, "--tail", 50, "2>&1"))
|
|
end
|
|
|
|
def stop
|
|
pipe container_id, xargs(docker(:stop))
|
|
end
|
|
|
|
def remove
|
|
pipe container_id, xargs(docker(:container, :rm))
|
|
end
|
|
|
|
private
|
|
def container_name
|
|
[ "healthcheck", config.service, config.destination ].compact.join("-")
|
|
end
|
|
|
|
def container_name_with_version
|
|
"#{container_name}-#{config.version}"
|
|
end
|
|
|
|
def container_id
|
|
container_id_for(container_name: container_name_with_version)
|
|
end
|
|
|
|
def health_url
|
|
"http://localhost:#{EXPOSED_PORT}#{config.healthcheck["path"]}"
|
|
end
|
|
end
|