DEV Community

flisk
flisk

Posted on

Flisk BYO Runs Any Language. Goose Uses That Door.

Part 1 of Any language on Flisk.

docs/byo.md does not list allowed languages. The heading is "Bringing a framework app (Node, Go, Rust, ...)" and the next sentence is the rule: any app that fits the contract can run as a bring-your-own resource. Fastify is the worked example only because it needs nothing beyond the framework. The provider guide sends Java, Ruby, and a legacy service through the same door. Goose goes through it too.

--type backend --language is a different door. That one scaffolds Bun, or Python, Go, Rust, and Node if you ask. It is a generator. BYO is not a generator. Flisk does not write your application. You bring the image. The language inside the image is yours.

Same command, any language

flisk resource <name> --type bring-your-own --stack <stack> \
  --dockerfile ./Dockerfile --health-path /health \
  --path services/<stack>/<name> --yes
Enter fullscreen mode Exit fullscreen mode

byo is the same type as bring-your-own. Fastify, Gin, Flask, Quarkus, Phoenix, and a Goose binary all use that line. What changes is the directory you point --path at.

The only contract

The container has to do four things. The language does not change them.

  1. Listen on the port in service.json. Compose sets PORT to that value. It also sets DATABASE_URL in every BYO container. Read PORT. Do not hardcode it.
  2. Bind 0.0.0.0. Traefik is on the Docker network.
  3. Answer HTTP 200 on healthCheckPath if it speaks HTTP. --health-path /health is the usual value. Flisk does not add a Compose curl probe for this type, so the image does not need curl. A non-HTTP process can omit healthCheckPath.
  4. Provide the image with a Dockerfile or --image. COPY paths are relative to the resource directory unless you set buildContext.

Ports are 4000 through 5999. --port must be unused in that range. Omit it and Flisk picks the next free one.

What "any language" does not mean

It does not mean Flisk writes a Goose scaffold, a health route, or a PORT read. The limits section says that outright: no generated code. If you run the command with no Dockerfile, Flisk writes an Nginx placeholder that listens on the assigned port. If a Dockerfile already exists, Flisk keeps it and does not overwrite it. Bring yours first.

It also does not mean live reload. Only the manifest is watched. After a source change, rebuild the image from the Tilt UI or restart flisk up. A native Go service can opt into dev.liveReload. A Go app you bring as a container, including the Gin example, does not get that loop. Goose will not either.

Part 2 is a Goose app that meets the same four rules as the Fastify server.js in the doc.

Top comments (2)

Collapse
 
alexcodebytes profile image
Oleksandr •

The distinction between scaffolding a language (--type backend --language) and providing a runtime contract (--type bring-your-own) is a really clean design choice. It prevents the classic "generator bloat" problem where a CLI tries to support every framework under the sun and inevitably does them all poorly. The four rules for the container are basically the 12-factor app manifest boiled down to its absolute essentials for a Docker network.

Since you lose live reload for BYO apps (which makes total sense for non-native runtimes), how does the Tilt UI handle the rebuild latency? I imagine bringing a heavy Quarkus or Rust binary through this door takes significantly longer to rebuild from source than a native Go service. Do you have any dependency caching strategies in place, or is it just expected that the dev embraces the slower iteration cycle in exchange for total language freedom?

Collapse
 
flisk profile image
flisk •

great comment, we will add it github.com/flisk-sh/flisk/issues/1917