#!/bin/bash # ^ # There's nothing magical about shebang (#!) lines- they just tell the shell which executable should be used to run this script # The <Dockerfile <<'EOF' # syntax = docker/dockerfile:1.4.0 FROM node:20 WORKDIR /root RUN npm install sqlite3 # We can write any text inside a heredoc- including other heredocs! RUN cat >/root/schema.sql <<'EOSQL' CREATE TABLE IF NOT EXISTS clicks ( id INTEGER PRIMARY KEY AUTOINCREMENT, time INTEGER NOT NULL ); EOSQL # The heredoc terminator doesn't need to be "EOF", it's just an arbitrary string RUN cat >/root/server.js <<'BANANACAT' 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...")); BANANACAT RUN cat >/root/index.html <<'EOHTML' #!/usr/bin/env docker run
Page loads over time (last 4 hours) 0 EOHTML CMD ["node", "/root/server.js"] EOF # Build the Docker image docker build -t myimage . # Run a Docker container from the built image docker run -p 8080:8080 -it --rm myimage