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.
57 lines
1.3 KiB
Ruby
57 lines
1.3 KiB
Ruby
module Mrsk::Commands
|
|
class Base
|
|
delegate :sensitive, :argumentize, to: Mrsk::Utils
|
|
|
|
DOCKER_HEALTH_STATUS_FORMAT = "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'"
|
|
|
|
attr_accessor :config
|
|
|
|
def initialize(config)
|
|
@config = config
|
|
end
|
|
|
|
def run_over_ssh(*command, host:)
|
|
"ssh".tap do |cmd|
|
|
cmd << " -J #{config.ssh_proxy.jump_proxies}" if config.ssh_proxy
|
|
cmd << " -t #{config.ssh_user}@#{host} '#{command.join(" ")}'"
|
|
end
|
|
end
|
|
|
|
def container_id_for(container_name:)
|
|
docker :container, :ls, "--all", "--filter", "name=^#{container_name}$", "--quiet"
|
|
end
|
|
|
|
private
|
|
def combine(*commands, by: "&&")
|
|
commands
|
|
.compact
|
|
.collect { |command| Array(command) + [ by ] }.flatten # Join commands
|
|
.tap { |commands| commands.pop } # Remove trailing combiner
|
|
end
|
|
|
|
def chain(*commands)
|
|
combine *commands, by: ";"
|
|
end
|
|
|
|
def pipe(*commands)
|
|
combine *commands, by: "|"
|
|
end
|
|
|
|
def append(*commands)
|
|
combine *commands, by: ">>"
|
|
end
|
|
|
|
def write(*commands)
|
|
combine *commands, by: ">"
|
|
end
|
|
|
|
def xargs(command)
|
|
[ :xargs, command ].flatten
|
|
end
|
|
|
|
def docker(*args)
|
|
args.compact.unshift :docker
|
|
end
|
|
end
|
|
end
|