Module: Docker::API::Context
- Defined in:
- lib/docker/api/context.rb
Overview
Docker's context store, which is where the CLI keeps the daemon it is
pointed at when DOCKER_HOST is not set.
docker context use colima does not export anything. It writes
currentContext into ~/.docker/config.json, and every later docker
command resolves the endpoint out of the store. A client that reads only
DOCKER_HOST therefore disagrees with the CLI on the same machine, and
falls back to /var/run/docker.sock -- which Docker Desktop happens to
symlink, and Colima, Rancher Desktop, rootless Docker and Podman
generally do not. The failure is a connection refused with a correct
looking environment, which is a bad way to spend an afternoon.
The store is a directory per context, named for the SHA-256 of the context's own name, holding a meta.json:
~/.docker/contexts/meta/<sha256(name)>/meta.json
~/.docker/contexts/tls/<sha256(name)>/docker/{ca,cert,key}.pem
Every failure here is soft. An unreadable store, a malformed meta.json or a context that no longer exists all mean "no context", because falling back to the platform default is what the CLI does and is more useful than refusing to start.
Constant Summary collapse
- DEFAULT =
The context name that means "no context": use DOCKER_HOST, or the platform's default socket. It has no entry in the store.
"default"
Class Method Summary collapse
-
.config_root(env = ENV) ⇒ String
The Docker configuration directory.
-
.current_name(env = ENV, root = config_root(env)) ⇒ String?
The active context's name: DOCKER_CONTEXT first, then whatever
docker context uselast wrote into config.json. -
.endpoint(name, root = config_root) ⇒ Hash?
With :url and optionally :tls.
- .read_json(path) ⇒ Object? private
-
.resolve(env = ENV, root: nil) ⇒ Hash?
Resolve the endpoint the CLI would use, if any.
-
.tls_material(root, digest, skip_verify: false) ⇒ Hash
private
A context may carry its own TLS material, which is how
docker context create --docker host=tcp://...,ca=...,cert=...,key=...stores it.
Class Method Details
.config_root(env = ENV) ⇒ String
Returns the Docker configuration directory.
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/docker/api/context.rb', line 84 def config_root(env = ENV) configured = env["DOCKER_CONFIG"] return configured unless configured.nil? || configured.empty? File.join(Dir.home, ".docker") rescue ArgumentError # Dir.home raises when there is no home to speak of, which happens in # stripped containers and some CI images. ".docker" end |
.current_name(env = ENV, root = config_root(env)) ⇒ String?
The active context's name: DOCKER_CONTEXT first, then whatever
docker context use last wrote into config.json.
59 60 61 62 63 64 65 |
# File 'lib/docker/api/context.rb', line 59 def current_name(env = ENV, root = config_root(env)) from_env = env["DOCKER_CONTEXT"] return from_env unless from_env.nil? || from_env.empty? config = read_json(File.join(root, "config.json")) config.is_a?(Hash) ? config["currentContext"] : nil end |
.endpoint(name, root = config_root) ⇒ Hash?
Returns with :url and optionally :tls.
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/docker/api/context.rb', line 70 def endpoint(name, root = config_root) digest = Digest::SHA256.hexdigest(name) = read_json(File.join(root, "contexts", "meta", digest, "meta.json")) host = .dig("Endpoints", "docker", "Host") if .is_a?(Hash) return nil if host.nil? || host.empty? resolved = { url: host } tls = tls_material(root, digest, skip_verify: .dig("Endpoints", "docker", "SkipTLSVerify")) resolved[:tls] = tls unless tls.empty? resolved end |
.read_json(path) ⇒ Object?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
115 116 117 118 119 120 121 |
# File 'lib/docker/api/context.rb', line 115 def read_json(path) return nil unless File.readable?(path) JSON.parse(File.read(path)) rescue JSON::ParserError, SystemCallError nil end |
.resolve(env = ENV, root: nil) ⇒ Hash?
Resolve the endpoint the CLI would use, if any.
45 46 47 48 49 50 51 |
# File 'lib/docker/api/context.rb', line 45 def resolve(env = ENV, root: nil) root ||= config_root(env) name = current_name(env, root) return nil if name.nil? || name.empty? || name == DEFAULT endpoint(name, root) end |
.tls_material(root, digest, skip_verify: false) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
A context may carry its own TLS material, which is how docker context create --docker host=tcp://...,ca=...,cert=...,key=... stores it.
100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/docker/api/context.rb', line 100 def tls_material(root, digest, skip_verify: false) directory = File.join(root, "contexts", "tls", digest, "docker") material = { ca_file: "ca.pem", cert_file: "cert.pem", key_file: "key.pem" } .filter_map { |key, file| path = File.join(directory, file) [key, path] if File.readable?(path) }.to_h return {} if material.empty? material.merge(verify: !skip_verify) end |