File
Blob: src/workerd/io/container.capnp
| 1 | @0xcb7be0e1be835084; |
| 2 | |
| 3 | using Cxx = import "/capnp/c++.capnp"; |
| 4 | $Cxx.namespace("workerd::rpc"); |
| 5 | $Cxx.allowCancellation; |
| 6 | |
| 7 | using import "/capnp/compat/byte-stream.capnp".ByteStream; |
| 8 | using CompatibilityFlags = import "/workerd/io/compatibility-date.capnp".CompatibilityFlags; |
| 9 | |
| 10 | interface Container @0x9aaceefc06523bca { |
| 11 | # RPC interface to talk to a container, for containers attached to Durable Objects. |
| 12 | # |
| 13 | # When the actor shuts down, workerd will drop the `Container` capability, at which point |
| 14 | # the container engine should implicitly destroy the container. |
| 15 | |
| 16 | status @0 () -> (running :Bool); |
| 17 | # Returns the container's current status. The runtime will always call this at DO startup. |
| 18 | |
| 19 | start @1 StartParams -> (); |
| 20 | # Start the container. It's an error to call this if the container is already running. |
| 21 | |
| 22 | struct StartParams { |
| 23 | entrypoint @0 :List(Text); |
| 24 | # Specifies the command to run as the root process of the container. If null, the container |
| 25 | # image's default command is used. |
| 26 | |
| 27 | enableInternet @1 :Bool = false; |
| 28 | # Set true to enable the container to talk directly to the public internet. Otherwise, the |
| 29 | # public internet will not be accessible -- but it's still possible to intercept connection |
| 30 | # attempts and handle them in the DO, using the `listenTcp()` method below. |
| 31 | |
| 32 | environmentVariables @2 :List(Text); |
| 33 | # Specifies the environment variables of the container. |
| 34 | # It will spread over the existing defined environment variables of the container image. |
| 35 | # If null, the container will start with the environment variables defined in its image. |
| 36 | # The format is defined as a list of `NAME=VALUE`. |
| 37 | # The container runtime should validate the environment variables input. |
| 38 | |
| 39 | hardTimeoutMs @3 :Int64; |
| 40 | # Configures an absolute timeout that starts when the container starts and never resets. |
| 41 | # The container will be forcefully terminated when this timeout expires, regardless of activity. |
| 42 | # Unlike inactivity timeout, this is a hard deadline from container startup. |
| 43 | # If 0 (default), no hard timeout is applied. |
| 44 | |
| 45 | compatibilityFlags @4 :CompatibilityFlags; |
| 46 | # Compatibility flags for this worker |
| 47 | |
| 48 | labels @5 :List(Label); |
| 49 | # Optional key-value metadata labels for metrics/observability. |
| 50 | |
| 51 | directorySnapshots @6 :List(DirectorySnapshotRestoreParams); |
| 52 | # Directory snapshots to restore before the container starts. |
| 53 | |
| 54 | containerSnapshotId @7 :Text; |
| 55 | # Id of the full container snapshot to restore before the container starts. |
| 56 | } |
| 57 | |
| 58 | struct Label { |
| 59 | name @0 :Text; |
| 60 | value @1 :Text; |
| 61 | } |
| 62 | |
| 63 | struct DirectorySnapshotRestoreParams { |
| 64 | snapshotId @0 :Text; |
| 65 | # The id of the snapshot to restore. |
| 66 | |
| 67 | restorePath @1 :Text; |
| 68 | # Where to restore the snapshot in the container filesystem. |
| 69 | } |
| 70 | |
| 71 | struct DirectorySnapshot { |
| 72 | # Opaque handle to a directory snapshot. |
| 73 | |
| 74 | id @0 :Text; |
| 75 | # Unique identifier of the snapshot. |
| 76 | |
| 77 | size @1 :UInt64; |
| 78 | # Snapshot size, in bytes. |
| 79 | |
| 80 | dir @2 :Text; |
| 81 | # Path of the snapshotted directory. |
| 82 | |
| 83 | name @3 :Text; |
| 84 | # Optional human-friendly name. Empty string means not set. |
| 85 | } |
| 86 | |
| 87 | struct SnapshotDirectoryParams { |
| 88 | dir @0 :Text; |
| 89 | # Directory path to snapshot. |
| 90 | |
| 91 | name @1 :Text; |
| 92 | # Optional human-friendly name. Empty string means not set. |
| 93 | } |
| 94 | |
| 95 | struct ContainerSnapshot { |
| 96 | # Opaque handle to a full container snapshot. |
| 97 | |
| 98 | id @0 :Text; |
| 99 | # Unique identifier of the snapshot. |
| 100 | |
| 101 | size @1 :UInt64; |
| 102 | # Snapshot size, in bytes. |
| 103 | |
| 104 | name @2 :Text; |
| 105 | # Optional human-friendly name. Empty string means not set. |
| 106 | } |
| 107 | |
| 108 | struct SnapshotContainerParams { |
| 109 | name @0 :Text; |
| 110 | # Optional human-friendly name. Empty string means not set. |
| 111 | } |
| 112 | |
| 113 | struct ExecOptions { |
| 114 | env @0 :List(Text); |
| 115 | # Environment variables to add/override for the exec'd process, in NAME=VALUE format. |
| 116 | |
| 117 | workingDirectory @1 :Text; |
| 118 | # Working directory for the exec'd process. Empty string means use the container default. |
| 119 | |
| 120 | user @2 :Text; |
| 121 | # User for the exec'd process. Empty string means use the container default. |
| 122 | |
| 123 | combinedOutput @3 :Bool; |
| 124 | # If true, stderr is combined into stdout. If stdout is not set, combined output is discarded. |
| 125 | } |
| 126 | |
| 127 | struct Process { |
| 128 | pid @0 :Int32; |
| 129 | handle @1 :ProcessHandle; |
| 130 | } |
| 131 | |
| 132 | interface ProcessHandle { |
| 133 | wait @0 () -> (exitCode :Int32); |
| 134 | # Waits for the process to exit and returns its exit code. |
| 135 | |
| 136 | stdinWriter @1 () -> (writer :ByteStream); |
| 137 | # Retrieves a ByteStream handle to write to the process's stdin. |
| 138 | # If not called before wait(), stdin automatically EOFs. |
| 139 | # Throws an error if called after wait(). |
| 140 | |
| 141 | kill @2 (signo :UInt32); |
| 142 | # Sends the given signal to the process. |
| 143 | } |
| 144 | |
| 145 | monitor @2 () -> (exitCode: Int32); |
| 146 | # Waits for the container to shut down. |
| 147 | # |
| 148 | # If the container shuts down because the root process exited with a success status, or because |
| 149 | # the client invoked `destroy()`, then `monitor()` completes without an error. If it shuts down |
| 150 | # for any other reason, `monitor()` throws an exception describing what happened. (This exception |
| 151 | # may or may not be a JSG exception depending on whether it is an application error or a system |
| 152 | # error.) |
| 153 | |
| 154 | destroy @3 (); |
| 155 | # Immediately and abruptly stops the container and tears it down. The application is not given |
| 156 | # any warning, it simply stops immediately. Upon successful return from destroy(), the container |
| 157 | # is no longer running. If a call to `monitor()` is waiting when `destroy()` is invoked, |
| 158 | # `monitor()` will also return (with no error). If the container is not running when `destroy()` |
| 159 | # is invoked, `destroy()` silently returns with no error. |
| 160 | |
| 161 | signal @4 (signo :UInt32); |
| 162 | # Sends the given Linux signal number to the root process. |
| 163 | |
| 164 | getTcpPort @5 (port :UInt16) -> (port :Port); |
| 165 | # Obtains an object which can be used to connect to the application inside the container on the |
| 166 | # given TCP port (the application must be listening on this port). |
| 167 | |
| 168 | interface Port { |
| 169 | # Represents a port to which connections can be made. |
| 170 | |
| 171 | connect @0 (down :ByteStream) -> (up :ByteStream); |
| 172 | # Forms a raw socket connection to the port. |
| 173 | # |
| 174 | # Note that when the Durable Object application uses the HTTP-oriented APIs, workerd will |
| 175 | # take care of speaking the HTTP protocol on top of the raw socket. So, the container engine |
| 176 | # need only implement raw connections. |
| 177 | } |
| 178 | |
| 179 | listenTcp @6 (filter :IpFilter, handler :TcpHandler) -> (handle :Capability); |
| 180 | # Arranges to intercept outgoing TCP connections from the container and redirect them to the |
| 181 | # given `handler`. |
| 182 | |
| 183 | struct IpFilter { |
| 184 | # Specifies a range of IP addresses and/or port numbers which should be intercepted when the |
| 185 | # application in the container tries to connect to them. |
| 186 | |
| 187 | addr @0 :Text; |
| 188 | # null = all addresses |
| 189 | # TODO(someday): Support CIDR? (e.g. "192.168.0.0/16") |
| 190 | |
| 191 | port @1 :UInt16 = 0; |
| 192 | # 0 = all ports |
| 193 | } |
| 194 | |
| 195 | interface TcpHandler { |
| 196 | # Interface which intercepts outgoing connections from a container. |
| 197 | |
| 198 | connect @0 (addr :Text, port :UInt16, down :ByteStream) -> (up :ByteStream); |
| 199 | # Like Port.connect() but also receives the address and port number to which the container was |
| 200 | # attempting to connect. |
| 201 | } |
| 202 | |
| 203 | setInactivityTimeout @7 (durationMs :Int64); |
| 204 | # Configures the duration where the runtime should shutdown the container after there is |
| 205 | # no connections or activity to the Container. |
| 206 | # |
| 207 | # After a capability disconnect, the runtime should signal the container |
| 208 | # at the configured duration. |
| 209 | # |
| 210 | # Note that if there is an open connection to the container, the runtime must not shutdown the container. |
| 211 | # If there is no activity timeout duration configured and no container connection, it's up to the runtime |
| 212 | # to decide when to signal the container to exit. |
| 213 | |
| 214 | setEgressHttp @8 (hostPort :Text, channelToken :Data); |
| 215 | # Configures egress HTTP routing for the container. When the container attempts to connect to the |
| 216 | # specified host:port, the connection should be routed back to the Workers runtime using the channel token. |
| 217 | # The format of hostPort can be '<ip|cidr|hostnameGlob>[':'<port>]'. If the host part is not an |
| 218 | # IP or CIDR, it is treated as a hostname glob. |
| 219 | # If port is omitted, it's assumed to only cover port 80. |
| 220 | # This method does not support HTTPs yet. |
| 221 | |
| 222 | setEgressHttps @9 (hostPort :Text, channelToken :Data); |
| 223 | # Configures egress HTTPS routing for the container. The format of `hostPort` is the same as |
| 224 | # `setEgressHttp`: '<ip|cidr|hostnameGlob>[':'<port>]'. If the host part is not an IP or CIDR, |
| 225 | # it is treated as a hostname glob matched against the TLS SNI hostname. If `port` is omitted, |
| 226 | # it is assumed to only cover port 443. |
| 227 | # |
| 228 | # The runtime routes matching decrypted HTTP traffic back to Workers using `channelToken` and |
| 229 | # must ensure the container trusts the interception CA. |
| 230 | |
| 231 | setEgressTcp @13 (hostPort :Text, channelToken :Data); |
| 232 | # Configures egress TCP routing for the container. When the container attempts a raw TCP |
| 233 | # connection to the specified host:port, the connection is routed back to the Workers |
| 234 | # runtime using the channel token. The worker binding is expected to implement a connect() |
| 235 | # handler that receives the destination address and a bidirectional byte stream. |
| 236 | # The format of `hostPort` is '<ip|cidr>[':'<port>]'. Hostname glob matching is not |
| 237 | # supported for TCP since there is no application-layer hostname information. If `port` |
| 238 | # is omitted, all ports are matched. |
| 239 | |
| 240 | snapshotDirectory @10 SnapshotDirectoryParams -> (snapshot :DirectorySnapshot); |
| 241 | # Creates a snapshot for a directory in the running container. |
| 242 | |
| 243 | snapshotContainer @11 SnapshotContainerParams -> (snapshot :ContainerSnapshot); |
| 244 | # Creates a full container snapshot for the running container. |
| 245 | |
| 246 | exec @12 (cmd :List(Text), stdoutWriter :ByteStream, stderrWriter :ByteStream, |
| 247 | params :ExecOptions) -> (process :Process); |
| 248 | # Executes a short-lived process in the running container. |
| 249 | # |
| 250 | # If stdoutWriter/stderrWriter are not provided, output is discarded. If params.combinedOutput |
| 251 | # is true, stderr is merged into stdout and the stderrWriter capability is ignored. |
| 252 | |
| 253 | inspect @14 () -> (info :InspectInfo); |
| 254 | # Returns information about the container, or `none` if the container has not been started. |
| 255 | |
| 256 | struct InspectInfo { |
| 257 | union { |
| 258 | none @0 :Void; |
| 259 | started :group { |
| 260 | labels @1 :List(Label); |
| 261 | # Echo of StartParams.labels. Empty list means start() was called with no labels. |
| 262 | } |
| 263 | } |
| 264 | } |
| 265 | } |