finite lifetime private workers

I’m trying to run an ephemeral container against some private services running on fly. I’ve posted about trying to access it via a wireguard tunnel.

Another option is to run that code in a container directly inside of fly.

I need this code to make some HTTP requests and then terminate. Unlike the pattern for sidekiq or celery workers, I don’t need the workers to operate indefinitely. Unlike the release_command pattern, I don’t have anything that it’s supposed to “run before”. It feels a lot like a “remote builder”, except the output is not an image.

For now my plan is to use release_command before starting a trivial webserver. Once the webserver is available, I’ll scale the application to zero. This feels gross. Is there a better way?

Yep! Try fly machine run --help. This works similarly to Docker, it will run until it exist by default. If you want, you can specify a restart policy that restarts it on failure.

I just tried this:

flyctl machine run -a deployment-1638403247 --build-local-only --dockerfile docker/Dockerfile

And I’m getting:

Error: requires at least 1 arg(s), only received 0

According to help, usage should be:

flyctl machine run <image> [command] [flags]

But when I run this:

flyctl machine run deployment-1638403247 -a deployment-1638403247 --build-local-only --dockerfile docker/Dockerfile

I get:

Searching for image 'deployment-1638403247' locally...
Searching for image 'deployment-1638403247' remotely...
Error Could not resolve App

Is deployment-163803247 the app name? Try this:

flyctl machine run . --build-local-only --dockerfile docker/Dockerfile

The argument it wants is an image label or working directory. . should make it build the current working directory.

Progress!

It builds now with ., though I’m now seeing

Error error rendering push status stream: name unknown: app repository not found

Do I need to use an app name that already exists?

Ah, yes! That’s not obvious, sorry about that. Machines run within the context of an app. So you either need to create a new app for your one off tasks, or run them within an existing app.

Got it, ok I think it’s running.

Is the running machine directly addressable via private and/or public networking?

In flyctl machine run --help I see:

  -p, --port strings                     Exposed port mappings (format: edgePort[:machinePort]/[protocol[:handler]])

This makes me think it should be possible to reach the machine at some sort of unique address or ID.

That exposes publicly it on <appname>.fly.dev:<port>. If you are connected via wireguard, you can just use the private IPv6 address to talk to the machine, no port argument necessary.

To clarify, are the public ports exposed by flyctl machine run merged with those exposed by the running app (and possibly other flyctl machine runs?)

Yep! That’s exactly how it works.