Class: Pikuri::VectorDb::Server::DockerContainer
- Inherits:
-
Object
- Object
- Pikuri::VectorDb::Server::DockerContainer
- Defined in:
- lib/pikuri/vector_db/server/docker_container.rb
Overview
Lifecycle engine for one named, disposable docker container with persistent bind-mounted data — the shared machinery Qdrant and Chroma compose. The supervisor carries the engine's identity (image pin, name, persist/heartbeat paths) as constructor parameters; this class does the docker work: create/recreate/remove, publish the port, heartbeat-poll until ready.
Namespace squat: pikuri-internal-*
Containers are named "pikuri-internal-<engine>" with a
pikuri.internal=true label, and are treated as fully pikuri-owned —
wrong image, stopped, or crash-orphaned, they are removed and recreated
on the pinned image without ceremony. The bind-mounted data volume is
not nuked — the corpus is the user's even when its container is
replaced. The convention scales to any future pikuri-internal-*.
Ephemeral container, persistent data
All engine state lives on the host volume, so the container carries nothing worth keeping: #ensure_running! recreates it every boot, except one this instance already started and left running (reused, so repeated calls stay cheap). Anything else — stopped, or running from a previous run / crash / concurrent pikuri — is removed and recreated rather than adopted: a fresh container on the pinned image against the persistent volume is always a clean start with no image tag to reconcile. #close +docker rm -f+s it. The single-named-container convention assumes one active pikuri at a time.
Docker shell-outs route through Subprocess.spawn per the
subprocess seam — this class is not the seam's exception (that's
+pikuri-mcp+'s ClientWrapper, which owns a long-lived stdio pipe). The
port publish is built -p 127.0.0.1:<host>:<container>, never the docker
default (which binds every interface and would expose the corpus to the
LAN) — centralized here as the single privacy enforcement point. Errors
are loud at boot (docker missing, run non-zero, healthcheck timeout →
RuntimeError — internal caller, bug territory) and quiet at teardown
(#close best-effort, logs instead of raising).
Constant Summary collapse
- LOGGER =
Pikuri.logger_for('VectorDb::Server')
Instance Attribute Summary collapse
-
#name ⇒ String
readonly
Container name.
Instance Method Summary collapse
-
#close ⇒ void
Remove the container (+docker rm -f+), leaving the bind-mounted host volume — the data survives.
-
#endpoint ⇒ String
"http://localhost:<host_port>". -
#ensure_running! ⇒ void
Idempotent: ensure a fresh container is running, then heartbeat-poll until ready.
- #initialize(name:, image:, label:, host_port:, container_port:, volume:, health_path:, healthcheck_timeout:, connection: nil) ⇒ DockerContainer constructor
Constructor Details
#initialize(name:, image:, label:, host_port:, container_port:, volume:, health_path:, healthcheck_timeout:, connection: nil) ⇒ DockerContainer
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/pikuri/vector_db/server/docker_container.rb', line 71 def initialize(name:, image:, label:, host_port:, container_port:, volume:, health_path:, healthcheck_timeout:, connection: nil) @name = name @image = image @label = label @host_port = host_port @container_port = container_port @volume = volume @health_path = health_path @healthcheck_timeout = healthcheck_timeout @connection = connection @owns_container = false @closed = false end |
Instance Attribute Details
#name ⇒ String (readonly)
Returns container name.
88 89 90 |
# File 'lib/pikuri/vector_db/server/docker_container.rb', line 88 def name @name end |
Instance Method Details
#close ⇒ void
This method returns an undefined value.
Remove the container (+docker rm -f+), leaving the
bind-mounted host volume — the data survives. Best-effort
and idempotent: a no-op if this instance never started a
container or has already closed, and a non-zero rm is
logged rather than raised — that's teardown, boot is loud.
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/pikuri/vector_db/server/docker_container.rb', line 124 def close return if @closed || !@owns_container @closed = true result = docker('rm', '-f', @name) return if result.status.success? LOGGER.warn( "docker rm -f #{@name} failed " \ "(exit #{result.status.exitstatus}): #{result.output.strip}" ) end |
#endpoint ⇒ String
Returns "http://localhost:<host_port>".
91 92 93 |
# File 'lib/pikuri/vector_db/server/docker_container.rb', line 91 def endpoint "http://localhost:#{@host_port}" end |
#ensure_running! ⇒ void
This method returns an undefined value.
Idempotent: ensure a fresh container is running, then heartbeat-poll until ready. One this instance already started is reused; anything else is removed (if present) and recreated on the pinned image. See "Ephemeral container, persistent data".
103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/pikuri/vector_db/server/docker_container.rb', line 103 def ensure_running! state = container_state if @owns_container && state == :running LOGGER.info("#{@name} already running") else remove_container! unless state == :missing run_container! end @owns_container = true @closed = false wait_for_healthy! end |