Running a service in a container
not builtThis page is the design; Jadpo doesn't do this yet. See What is built.
On this page
A provider's API can be a stateless container image that Jadpo starts beside
your app, such as Gotenberg turning HTML into PDFs or ClamAV scanning uploads.
This is called a service run by Jadpo, and it isn't built yet. Its package
declares the image with runs:, and Jadpo starts and supervises the container
through Docker or Podman and hands the connection the address. This runs:
isn't the one on a deployable, which
lists its background work.
Here is the design for Gotenberg's package and a connection to it, which fills
the documents capability. It doesn't compile today:
// packages/gotenberg/v8/provider.jadpo/// Gotenberg's HTTP API, run by Jadpo as a container beside the app.provider { protocol: Protocol.multipart_http runs: { image: "gotenberg/gotenberg:8@sha256:…" port: 3000 asks: ["fonts.googleapis.com"] }}// app.jadpoapplication { connections: { pdfs: { package: Gotenberg.v8 domains: [billing] outbound: ["fonts.googleapis.com"] } } documents: { connection: pdfs }}
jadpo dev |
jadpo test |
Native deployable | Workers deployable |
|---|---|---|---|
Started as a container by jadpo dev |
Never started: the package's fake answers | A container beside the app: jadpo build writes the configuration that runs it (Compose first), then the deployable supervises it itself |
None: Workers runs no containers, so the connection gives host: where the service is hosted elsewhere |
No built-in service starts a container, but one could use a service run by Jadpo through its capability, as documents would use Gotenberg.
Services
- Only stateless services. A service holds no data and has no volume, and each app instance runs its own copy, so many servers need nothing shared. Anything that holds data (PostgreSQL, Redis) is infrastructure the operator provides and the app reaches through a driver connection.
- A service never starts until approved. Installing shows the image, its
digest and the hosts it asks for; the app names it on a connection, and a
new or changed image needs a person's acceptance in the approval report
before it runs, so an upgrade cannot swap in a different image unseen. The
image's digest is written in the package source, which the package's own
digest pins; an own integration in
shared/providers/has no lock entry, and its image is listed the same way. - Outbound network needs the app's permission. A package only asks
(
asks:); the service gets none of those hosts until the connection grants them (outbound: [...]), and a new grant is a new outside host, which needs a person's acceptance (NetworkChange.host_added). Until thenjadpo checknames the hosts asked for and the line that grants them. - Three settings Jadpo always applies when it creates a container: no outbound network unless granted, never privileged, and no access to the host's disk. Jadpo creates the containers itself, so there is no configuration to audit.
- Reaching a service. A package says only the port its service listens on inside its container, so two packages can both use 3000. Jadpo gives each app a private network that only it and its services are on, and hands each connection the address: the service's name on that network when the app runs in a container, or a loopback port the engine picked when it runs as a plain process. Nobody writes an address.
- Jadpo is a client, never a container runtime. It talks to whatever
engine the machine has through the Docker-compatible API, which Docker and
Podman both serve, and leaves pulling, isolation and restart policies to
it. An app with no service never needs an engine; when one is needed and
none is found,
jadpo devand the deployable say so and how to install one. - Docker stays behind the scenes.
jadpo serviceslists each service (package, image, state, health, CPU and memory, restarts, uptime);jadpo services start,stopandrestart <name>,logs <name>(--follow,--since) andshell <name>(development only) manage them, each with--json. In production the commands talk to the running app, which supervises its services. A service's output joins the app's OpenTelemetry logs under its name, and a call to it appears in the request's trace as a provider call. You never write a Dockerfile or a Compose file. - Where services run.
jadpo devstarts the declared services, and tests keep using fakes.jadpo buildwrites the configuration that runs each one beside the app, Compose first. The native deployable supervises its services itself. On Workers, which runs no containers, a service is hosted elsewhere and the connection giveshost:.
Not built yet
Jadpo starts no containers yet, and jadpo services isn't a command. Until it
does, run the container yourself, with Docker, Podman or Compose, and connect
to it as you would to any API at an address you know:
- Start the image yourself, with its port open on the machine your app runs on, and keep it running and up to date yourself.
- Describe its API in
shared/providers/, with neitherhosts:norruns:inprovider.jadpo. - Give the connection
host:, read from aUrlsetting such ashttp://localhost:3000(Connecting inapp.jadpo).
Calls go over HTTPS, or plain HTTP only to the machine the app is on. So on
Workers, or when the container is on another machine, it needs an HTTPS
address. Your actions call its operations through the connection: the
documents capability isn't built either.
Markdown for agents: /docs/running-a-service-in-a-container.md.Built from Jadpo main at 7b64d64.