noob conceptual question

Experienced dev here. Struggling conceptually. I have flyctl installed & working ok.

Goal: run a docker image (containing a single script) hourly, passing the contained script secrets via environment variables and command-line arguments explicitly. Each invocation of the container will be identical, and the container will execute for a few seconds then exit (usually with a 0 status code, but it may exit nonzero).

My docker image has an ENTRYPOINT so it acts like an executable. I want to have environment variables POOLMINDER_TOKEN & POOLMINDER_POOL_ID contain secrets. When I run it locally, I do it like this: docker run --rm -it -e POOLMINDER_TOKEN="(a secret)" -e POOLMINDER_POOL_ID="(another secret)" poolminder:latest --verbose --topup-shortfall-strategy increase --no-dry-run

I’m not really conceptually understanding fly launch vs fly deploy vs fly machine. Things I think I know:

  • Applications are some kind of space.
  • I can push Docker images to an application space.
  • Secrets are bound to an application.
  • A machine can run a Docker image.
  • Machines can be scheduled.

Questions:

  • If I start with zero applications in my dashboard, what are the fly commands to execute, exactly?
  • How do I pass command-line arguments to my container’s invocation? (I don’t see the position for them when I run fly machine run --help.)
  • Are environment variables present in the application’s space?
  • Do secrets appear as environment variables in my docker container (as though they were passed via -e arguments)?
  • Do I really need a fly.toml file?

Thanks in advance for the noob help,
Matthew

1 Like

if you want to use the fly machines, the rough sequence of events would be

fly launch --name <app_name>

it will prompt you some questions like follows, you can reply No mostly

? Would you like to set up a Postgresql database now? No
? Would you like to set up an Upstash Redis database now? No
Wrote config file fly.toml
? Would you like to deploy now? No
Your app is ready! Deploy with `flyctl deploy`

This will basically create a new app. This generates a fly.toml file too, but since you’re using fly machines, I don’t think you really need the fly.toml.

If you have a Dockerfile, then you can push an image to fly registry as follows:

fly deploy --image-label v0.0.1 --build-only --push --remote-only -a <app_name>

This will build your image on a remote builder and push it to the fly registry - registry.fly.io/<app_name>:v0.0.1

You can set secrets as follows (these will be available as env vars when you start a machine).

fly secrets set POOLMINDER_TOKEN=token \
    POOLMINDER_POOL_ID =id \
    -a <app_name>

To launch a fly machine with your image, you could do

fly machine run registry.fly.io/<app_name>:v0.0.1

You could pass env vars with this command too. And you could schedule your machine run etc. See documentation here - flyctl machine run · Fly Docs

To update the image version

fly image update --image registry.fly.io/<app_name>:v0.0.1 -a <app_name>

It IS a bit confusing between traditional fly apps and fly machines to be honest. I feel the fly machines REST API is better documented. Hope this helps.

1 Like

Thanks for the reply. After reading through it & experimenting, I understand marginally better.

Here’s what I came up with:

#!/usr/bin/env bash
set -e

APP=poolminder
APP_ARG="-a $APP"
APP_REGEX="^$APP"
TAG="$(cat VERSION)"
SCHEDULE=${1:-hourly}

LOCATION=local
if [ -z "$(which docker)" ]; then
  LOCATION=remote
fi

if [ -z "$(fly apps list | grep -vE '^APP\s+' | grep -iE "$APP_REGEX\s+")" ]; then
  echo "No app named $APP found; creating." >&2
  fly apps create $APP --machines
else
  echo "App $APP exists; not creating." >&2
fi

echo "Building & pushing Docker image $LOCATIONly." >&2
fly deploy \
  $APP_ARG \
  --build-only \
  --$LOCATION-only \
  --push \
  --image-label $TAG \
  --verbose

# just nuke all machines & run a new one
IDS="$(fly machine list -q $APP_ARG)"
if echo "$IDS" | grep -Eqv '^No\s+'; then # -q should only emit machine ids or nothing, but it doesn't
  echo "Existing machine(s) found; destroying." >&2
  IDS="$(echo "$IDS" | tail -n +6)" # -q should only emit machine ids or nothing, but it doesn't
  for id in $IDS; do
    echo "Destroying machine $id." >&2
    fly machine destroy "$id" $APP_ARG -f --verbose
  done
fi

IMAGE=registry.fly.io/$APP:$TAG
echo "Running $IMAGE on a new machine $SCHEDULE." >&2
fly machine run \
  $IMAGE \
  $APP_ARG \
  --schedule $SCHEDULE \
  -e POOLMINDER_VERBOSE=1 \
  -e POOLMINDER_NO_DRY_RUN=1 \
  --detach \
  --verbose

I noticed some bugs in fly with respect to its honoring the -q flag. I’ll try to find the issue tracker & report them.