Skip to content

Instantly share code, notes, and snippets.

@adtac
Last active April 13, 2024 22:33
Show Gist options
  • Save adtac/595b5823ef73b329167b815757bbce9f to your computer and use it in GitHub Desktop.
Save adtac/595b5823ef73b329167b815757bbce9f to your computer and use it in GitHub Desktop.
#!/usr/bin/env docker run
#!/usr/bin/env -S bash -c "docker run -p 8080:8080 -it --rm \$(docker build --progress plain -f \$0 . 2>&1 | tee /dev/stderr | grep -oP 'sha256:[0-9a-f]*')"
# syntax = docker/dockerfile:1.4.0
FROM node:20
WORKDIR /root
RUN npm install sqlite3
RUN <<EOF cat >/root/schema.sql
CREATE TABLE IF NOT EXISTS clicks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
time INTEGER NOT NULL
);
EOF
RUN <<EOF cat >/root/server.js
const fs = require("fs");
const http = require("http");
const sqlite3 = require("sqlite3");
const db = new sqlite3.Database(":memory:");
db.run(fs.readFileSync("/root/schema.sql", "utf8"));
const html = fs.readFileSync("/root/index.html", "utf8");
const server = http.createServer((req, res) => {
db.run("INSERT INTO clicks(time) VALUES(unixepoch())");
const data = [];
db.each(
"SELECT time as t, COUNT(*) as n FROM clicks WHERE t > unixepoch()-4*60*60 GROUP BY t-t%60",
(_, { t, n }) => data.push([Math.floor(t/60), n]),
() => {
res.writeHead(200, { "content-type": "text/html" });
res.end(html.replace("__DATA__", JSON.stringify(data)));
},
);
});
server.listen(8080, "", () => console.log("serving :8080..."));
EOF
RUN <<EOF cat >/root/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#!/usr/bin/env docker run</title>
</head>
<body style="font-family: monospace; font-size; 12px; ">
<div style="position: absolute; top: 0; left: 0; width: 100vw; height: 100vh; background-size: 5vh 5vh; background-image: linear-gradient(to right, #f0f0f0 1px, transparent 1px), linear-gradient(to bottom, #f0f0f0 1px, transparent 1px); "></div>
<span style="position: absolute; top: 1vh; left: 5vh;">Page loads over time (last 4 hours)</span>
<span id="max" style="position: absolute; top: 5vh; left: 1vh;"></span>
<span id="min" style="position: absolute; top: 95vh; left: 1vh;">0</span>
<canvas id="canvas" style="position: absolute; top: 5vh; left: 5vw; "></canvas>
<script>
(() => {
const el = document.getElementById("canvas"), ctx = el.getContext("2d");
el.width = 0.9 * window.innerWidth * window.devicePixelRatio;
el.height = 0.9 * window.innerHeight * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
const data = __DATA__;
const max = data.reduce((prev, [_, n]) => (n > prev ? n : prev), 0);
document.getElementById("max").innerText = max;
ctx.beginPath();
ctx.moveTo(0, el.height);
const draw = (t, n) => {
const [x, y] = [el.width * (t-data[0][0])/240, el.height * (1 - n/max)];
ctx.lineTo(x, y);
ctx.moveTo(x, y);
}
let last = -1;
for (const [t, n] of data) {
if (last != -1 && t > last + 1) {
draw(last + 0.1, 0);
draw(t - 0.1, 0);
}
draw(t, n);
last = t;
}
ctx.stroke();
})();
</script>
</body>
</html>
EOF
CMD node /root/server.js

What is this?

#! (pronounced shebang) is a Unix convention that's typically used for scripting languages like Python and Bash. This abuses it to let you package applications in a cross-distro and cross-platform way. This example Dockerfile is a fullstack server that includes a backend, a database and a UI, all in a single file.

It's kinda like Cosmopolitan Libc but for packaging applications.

Why?

Why not?

Is it safe?

Probably not.

Should I use it?

If you want.

Is it performant?

Maybe.

Is it maintanable?

No.

Does it work?

Yes.

How do I run this?

chmod +x ./Dockerfile
./Dockerfile

Then go to http://127.0.0.1:8080

@stevekrouse
Copy link

stevekrouse commented Jan 16, 2024

I ported it over to Val Town!

Code: https://www.val.town/v/stevekrouse/backend_in_a_file
Live demo: https://stevekrouse-backend_in_a_file.web.val.run

I think there may be a frontend / css bug - would love any help debugging it or a PR on my val.

import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
import { html } from "https://esm.town/v/stevekrouse/html";

sqlite.execute(`CREATE TABLE IF NOT EXISTS backend_in_a_file_clicks (
  id   INTEGER PRIMARY KEY AUTOINCREMENT,
  time INTEGER NOT NULL
)`);

export default async function(req: Request): Promise<Response> {
  await sqlite.execute("INSERT INTO backend_in_a_file_clicks(time) VALUES(unixepoch())");
  const results = await sqlite.execute(
    "SELECT time as t, COUNT(*) as n FROM backend_in_a_file_clicks WHERE t > unixepoch()-4*60*60 GROUP BY t-t%60",
  );
  const data = (results.rows as any as [number, number][]).map(([t, n]) => [Math.floor(t / 60), n]);
  return html(`
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>#!/usr/bin/env docker run</title>
  </head>
  <body style="font-family: monospace; font-size; 12px; ">
    <div style="position: absolute; top: 0; left: 0; width: 100vw; height: 100vh; background-size: 5vh 5vh; background-image: linear-gradient(to right, #f0f0f0 1px, transparent 1px), linear-gradient(to bottom, #f0f0f0 1px, transparent 1px); "></div>
    <span style="position: absolute; top: 1vh; left: 5vh;">Page loads over time (last 4 hours)</span>
    <span id="max" style="position: absolute; top: 5vh; left: 1vh;"></span>
    <span id="min" style="position: absolute; top: 95vh; left: 1vh;">0</span>
    <canvas id="canvas" style="position: absolute; top: 5vh; left: 5vw; "></canvas>
    <script>
      (() => {
        const el = document.getElementById("canvas"), ctx = el.getContext("2d");
        el.width = 0.9 * window.innerWidth * window.devicePixelRatio;
        el.height = 0.9 * window.innerHeight * window.devicePixelRatio;
        ctx.scale(window.devicePixelRatio, window.devicePixelRatio);

        const data = ${JSON.stringify(data)};
        const max = data.reduce((prev, [_, n]) => (n > prev ? n : prev), 0);
        document.getElementById("max").innerText = max;

        ctx.beginPath();
        ctx.moveTo(0, el.height);

        const draw = (t, n) => {
          const [x, y] = [el.width * (t-data[0][0])/240, el.height * (1 - n/max)];
          ctx.lineTo(x, y);
          ctx.moveTo(x, y);
        }

        let last = -1;
        for (const [t, n] of data) {
          if (last != -1 && t > last + 1) {
            draw(last + 0.1, 0);
            draw(t - 0.1, 0);
          }
          draw(t, n);
          last = t;
        }
        ctx.stroke();
      })();
    </script>
  </body>
</html>`);
}

@nhumrich
Copy link

There was a bug in the she-bang line:

#11 writing image sha256:72b14c1cfde038ddccb0e7b6c600c0c23cd48acf5a37ae3cffbd224f629ccb6e done
#11 DONE 0.0s
docker: Error response from daemon: No such image: >sha256:ffebb4405810c92d267a764b21975fb2d96772e41877248a37bf3abaa0d3b590.
See 'docker run --help'.

grep is reading the wrong line. (needs to be the last line), so i fixed the shebang line by using tac to reverse the file, and then grep -m 1 so if stops on first match. Final she-bang line:

#!/usr/bin/env -S bash -c "docker run -p 8080:8080 -it --rm \$(docker build --progress plain -f \$0 . 2>&1 | tee /dev/stderr | tac | grep -m 1 -oP 'sha256:[0-9a-f]*')"

@MuhammadSawalhy
Copy link

I got this error:

DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
            Install the buildx component to build images with BuildKit:
            https://docs.docker.com/go/buildx/

unknown flag: --progress
See 'docker build --help'.
"docker run" requires at least 1 argument.
See 'docker run --help'.

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Create and run a new container from an image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment