Skip to content
File

Blob: src/workerd/io/container.capnp

10.3 KB
1@0xcb7be0e1be835084;
2 
3using Cxx = import "/capnp/c++.capnp";
4$Cxx.namespace("workerd::rpc");
5$Cxx.allowCancellation;
6 
7using import "/capnp/compat/byte-stream.capnp".ByteStream;
8using CompatibilityFlags = import "/workerd/io/compatibility-date.capnp".CompatibilityFlags;
9 
10interface 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}