Skip to content

Deploy an app

Package a JavaScript or TypeScript server in a container image on elide.dev/elide, with environment, sandbox flags, logs and a health check.

On this page

This page packages a TypeScript server as a container image on elide.dev/elide.

Write the app

ts
// server.ts
import { Hono } from "hono";

const app = new Hono();

app.use(async (c, next) => {
  await next();
  console.log(JSON.stringify({ method: c.req.method, path: c.req.path, status: c.res.status }));
});

app.get("/healthz", (c) => c.text("ok"));
app.get("/", (c) => c.json({ greeting: process.env.GREETING ?? "hello" }));

export default app;
utf-8 · ts · Lines: 14
js
// healthcheck.mjs
const res = await fetch("http://127.0.0.1:8080/healthz");
process.exit(res.ok ? 0 : 1);
utf-8 · js · Lines: 3
json
{
  "name": "deploy-app",
  "type": "module",
  "dependencies": {
    "hono": "^4.7.0"
  }
}
utf-8 · json · Lines: 7

Run elide install --ecosystems=npm once to write aube-lock.yaml.

Write the Dockerfile

dockerfile
FROM elide.dev/elide:1.6.0
WORKDIR /app
COPY package.json aube-lock.yaml ./
RUN elide install --ecosystems=npm
COPY . .
EXPOSE 8080
HEALTHCHECK --interval=10s --timeout=3s CMD ["elide", "healthcheck.mjs"]
CMD ["--allow-read=/app,/root/.cache/aube", "--allow-net=api.example.com", "serve", "--no-tui", "--host", "0.0.0.0", "--port", "8080", "server.ts"]
utf-8 · dockerfile · Lines: 8
text
# .dockerignore
node_modules
.env
utf-8 · text · Lines: 3
LineWhy
FROM elide.dev/elide:1.6.0The image’s entrypoint is elide, so CMD holds only its arguments. Tags: Container Images.
RUN elide install --ecosystems=npmInstalls inside the image. node_modules links into /root/.cache/aube, so a host node_modules would not work.
--host 0.0.0.0A default-exported handler binds 127.0.0.1, which is unreachable from outside the container.
--no-tuiWithout it, docker run -t starts the terminal UI and the app’s output never reaches docker logs.
HEALTHCHECKThe image has no curl or wget; a short Elide script does the check.
Terminal
bash
docker build -t my-app .
docker run -d --name my-app -p 8080:8080 -e GREETING=hi my-app
curl http://127.0.0.1:8080/
text
{"greeting":"hi"}
utf-8 · text · Lines: 1

docker inspect --format '{{.State.Health.Status}}' my-app prints healthy once the first check passes. docker stop ends the server within a second, with exit code 143.

Pass environment variables

process.env holds the container’s variables; pass them with docker run -e NAME=value or Docker’s --env-file .env. This supplies configuration without copying the file into the image.

For local runs with Elide 1.6.2 or later, the launcher reads .env and .env.local automatically. Use --env-file to select other files or --no-env to disable loading. Elide does not set NODE_ENV. See Environment and properties for precedence and Environment variables for JavaScript access.

Restrict the server

Programs run unrestricted until a sandbox flag is given. Grant a server what it needs and nothing else:

FlagIn the Dockerfile above
--allow-read=PATHS/app and the npm store /root/.cache/aube.
--allow-net=HOSTSOutbound hosts. Listening on a port needs no grant.
--allow-run=CMDSNot given: subprocesses stay allowed. Give a list to restrict them.
--deny-net=HOSTSHosts to block even when allowed, e.g. --deny-net=169.254.169.254.
--max-mem=SIZE, --timeout=DURATIONHeap size and total run time.

Global flags go before the command (serve, run). --deny-net and --deny-run need the = form. Leaving the npm store out of --allow-read stops the server at startup:

text
Error: Filesystem read denied by policy: /app/node_modules/hono
utf-8 · text · Lines: 1

A blocked outbound call names the flag:

text
fetch to '169.254.169.254:80' denied by --deny-net
utf-8 · text · Lines: 1

Every flag: Sandbox and Limits.

Read logs

console.log writes to stdout and console.error to stderr; docker logs shows both:

text
{"method":"GET","path":"/healthz","status":200}
{"method":"GET","path":"/","status":200}
utf-8 · text · Lines: 2

elide serve --no-tui prints no access log, and a handler that throws answers 500 without printing the error. Log requests and errors in the app, or export request spans, metrics, and errors with OpenTelemetry.

Deploy a JVM app

Was this page helpful?