home / tils / til

Menu
  • GraphQL API

til: fly_redbean-on-fly.md

This data as json

path topic title url body html shot created created_utc updated updated_utc shot_hash slug
fly_redbean-on-fly.md fly Deploying a redbean app to Fly https://github.com/simonw/til/blob/main/fly/redbean-on-fly.md [redbean](https://redbean.dev/) is a fascinating project - it provides a web server in a self-contained executable which you can add assets (or dynamic Lua code) to just by zipping them into the same binary package. I decided to try running it on [Fly](https://fly.io). Here's the recipe that worked for me. ## The Dockerfile I copied this Dockerfile, unmodified, from https://github.com/kissgyorgy/redbean-docker/blob/master/Dockerfile-multistage by György Kiss: ```dockerfile FROM alpine:latest as build ARG DOWNLOAD_FILENAME=redbean-original-2.0.8.com RUN apk add --update zip bash RUN wget https://redbean.dev/${DOWNLOAD_FILENAME} -O redbean.com RUN chmod +x redbean.com # normalize the binary to ELF RUN sh /redbean.com --assimilate # Add your files here COPY assets /assets WORKDIR /assets RUN zip -r /redbean.com * # just for debugging purposes RUN ls -la /redbean.com RUN zip -sf /redbean.com FROM scratch COPY --from=build /redbean.com / CMD ["/redbean.com", "-vv", "-p", "80"] ``` It uses a multi-stage build to download redbean, copy in the contents of your `assets/` folder, zip those back up and then create a TINY container from `scratch` that copies in just that executable. I made an `assets/` folder with something fun in it (a copy of my [Datasette Lite](https://github.com/simonw/datasette-lite) app) like this: ``` mkdir assets cd assets wget https://lite.datasette.io/index.html wget https://lite.datasette.io/webworker.js ``` ## Deploying to Fly First I needed to create a new application. I ran this: fly apps create redbean-on-fly Then I needed a `fly.toml` file. I created this one (copied from a previous example, but I updated the internal server port and the name): ```toml app = "redbean-on-fly" kill_signal = "SIGINT" kill_timeout = 5 [[services]] internal_port = 80 protocol = "tcp" [services.concurrency] hard_limit = 25 soft_limit = 20 [[services.ports]] handlers = ["http"] port = "80" [[services.ports]] handlers = ["tls", "http"] port = "443" [[services.tcp_checks]] interval = 10000 timeout = 2000 grace_period = "10s" ``` Finally, I deployed the app by running this in the same directory as `fly.toml`: fly deploy This uploaded the `Dockerfile` and `assets/` folder to Fly, ran the build there, then deployed the result. <p><a href="https://redbean.dev/" rel="nofollow">redbean</a> is a fascinating project - it provides a web server in a self-contained executable which you can add assets (or dynamic Lua code) to just by zipping them into the same binary package.</p> <p>I decided to try running it on <a href="https://fly.io" rel="nofollow">Fly</a>. Here's the recipe that worked for me.</p> <h2> <a id="user-content-the-dockerfile" class="anchor" href="#the-dockerfile" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>The Dockerfile</h2> <p>I copied this Dockerfile, unmodified, from <a href="https://github.com/kissgyorgy/redbean-docker/blob/master/Dockerfile-multistage">https://github.com/kissgyorgy/redbean-docker/blob/master/Dockerfile-multistage</a> by György Kiss:</p> <div class="highlight highlight-source-dockerfile"><pre><span class="pl-k">FROM</span> alpine:latest as build <span class="pl-k">ARG</span> DOWNLOAD_FILENAME=redbean-original-2.0.8.com <span class="pl-k">RUN</span> apk add --update zip bash <span class="pl-k">RUN</span> wget https://redbean.dev/${DOWNLOAD_FILENAME} -O redbean.com <span class="pl-k">RUN</span> chmod +x redbean.com <span class="pl-c"><span class="pl-c">#</span> normalize the binary to ELF</span> <span class="pl-k">RUN</span> sh /redbean.com --assimilate <span class="pl-c"><span class="pl-c">#</span> Add your files here</span> <span class="pl-k">COPY</span> assets /assets <span class="pl-k">WORKDIR</span> /assets <span class="pl-k">RUN</span> zip -r /redbean.com * <span class="pl-c"><span class="pl-c">#</span> just for debugging purposes</span> <span class="pl-k">RUN</span> ls -la /redbean.com <span class="pl-k">RUN</span> zip -sf /redbean.com <span class="pl-k">FROM</span> scratch <span class="pl-k">COPY</span> --from=build /redbean.com / <span class="pl-k">CMD</span> [<span class="pl-s">"/redbean.com"</span>, <span class="pl-s">"-vv"</span>, <span class="pl-s">"-p"</span>, <span class="pl-s">"80"</span>]</pre></div> <p>It uses a multi-stage build to download redbean, copy in the contents of your <code>assets/</code> folder, zip those back up and then create a TINY container from <code>scratch</code> that copies in just that executable.</p> <p>I made an <code>assets/</code> folder with something fun in it (a copy of my <a href="https://github.com/simonw/datasette-lite">Datasette Lite</a> app) like this:</p> <pre><code>mkdir assets cd assets wget https://lite.datasette.io/index.html wget https://lite.datasette.io/webworker.js </code></pre> <h2> <a id="user-content-deploying-to-fly" class="anchor" href="#deploying-to-fly" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Deploying to Fly</h2> <p>First I needed to create a new application. I ran this:</p> <pre><code>fly apps create redbean-on-fly </code></pre> <p>Then I needed a <code>fly.toml</code> file. I created this one (copied from a previous example, but I updated the internal server port and the name):</p> <div class="highlight highlight-source-toml"><pre><span class="pl-smi">app</span> = <span class="pl-s"><span class="pl-pds">"</span>redbean-on-fly<span class="pl-pds">"</span></span> <span class="pl-smi">kill_signal</span> = <span class="pl-s"><span class="pl-pds">"</span>SIGINT<span class="pl-pds">"</span></span> <span class="pl-smi">kill_timeout</span> = <span class="pl-c1">5</span> [[<span class="pl-en">services</span>]] <span class="pl-smi">internal_port</span> = <span class="pl-c1">80</span> <span class="pl-smi">protocol</span> = <span class="pl-s"><span class="pl-pds">"</span>tcp<span class="pl-pds">"</span></span> [<span class="pl-en">services</span>.<span class="pl-en">concurrency</span>] <span class="pl-smi">hard_limit</span> = <span class="pl-c1">25</span> <span class="pl-smi">soft_limit</span> = <span class="pl-c1">20</span> [[<span class="pl-en">services</span>.<span class="pl-en">ports</span>]] <span class="pl-smi">handlers</span> = [<span class="pl-s"><span class="pl-pds">"</span>http<span class="pl-pds">"</span></span>] <span class="pl-smi">port</span> = <span class="pl-s"><span class="pl-pds">"</span>80<span class="pl-pds">"</span></span> [[<span class="pl-en">services</span>.<span class="pl-en">ports</span>]] <span class="pl-smi">handlers</span> = [<span class="pl-s"><span class="pl-pds">"</span>tls<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>http<span class="pl-pds">"</span></span>] <span class="pl-smi">port</span> = <span class="pl-s"><span class="pl-pds">"</span>443<span class="pl-pds">"</span></span> [[<span class="pl-en">services</span>.<span class="pl-en">tcp_checks</span>]] <span class="pl-smi">interval</span> = <span class="pl-c1">10000</span> <span class="pl-smi">timeout</span> = <span class="pl-c1">2000</span> <span class="pl-smi">grace_period</span> = <span class="pl-s"><span class="pl-pds">"</span>10s<span class="pl-pds">"</span></span></pre></div> <p>Finally, I deployed the app by running this in the same directory as <code>fly.toml</code>:</p> <pre><code>fly deploy </code></pre> <p>This uploaded the <code>Dockerfile</code> and <code>assets/</code> folder to Fly, ran the build there, then deployed the result.</p> <Binary: 60,876 bytes> 2022-07-24T17:46:24-07:00 2022-07-25T00:46:24+00:00 2022-07-24T17:46:24-07:00 2022-07-25T00:46:24+00:00 89bed785f237c5f289ee7400beef1c18 redbean-on-fly
Powered by Datasette · How this site works · Code of conduct