simonw / datasette-publish-fly

Datasette plugin for publishing data using Fly
Apache License 2.0
20 stars 7 forks source link

Research how to deploy with latest flyctl and with a volume #11

Closed simonw closed 2 years ago

simonw commented 2 years ago

Just got "Error: unknown flag: --builder" from flyctl apps create while trying to run a deploy.

simonw commented 2 years ago

Hmm... this help is confusing:

% flyctl apps create --help                                                                                 
The APPS CREATE command will both register a new application 
with the Fly platform and create the fly.toml file which controls how 
the application will be deployed. The --builder flag allows a cloud native 
buildpack to be specified which will be used instead of a Dockerfile to 
create the application image when it is deployed.

Usage:
  flyctl apps create [APPNAME] [flags]

Flags:
      --generate-name    Generate a name for the app
  -h, --help             help for create
      --name string      The app name to use
      --network string   Specify custom network id
  -o, --org string       The organization to operate on

--builder isn't in the list of options, but it's part of the description that says:

The --builder flag allows a cloud native buildpack to be specified which will be used instead of a Dockerfile to create the application image when it is deployed.

simonw commented 2 years ago

Looks like things may have changed back in July: https://fly.io/blog/flyctl-evolved-fly-changelog/

It says that flyctl apps create was deprecated in favor of flyctl init - but I don't see init in the output from flyctl --help on my machine.

Maybe it's flyctl create now instead.

simonw commented 2 years ago

Filed a bug report here:

simonw commented 2 years ago

Maybe I should switch over to using fly launch instead: https://fly.io/docs/flyctl/launch/

simonw commented 2 years ago
% flyctl launch --help
Create and configure a new app from source code or an image reference.

Usage:
  flyctl launch [flags]

Flags:
      --copy-config         Use the configuration file if present without prompting.
      --dockerfile string   Path to a Dockerfile. Defaults to the Dockerfile in the working directory.
      --generate-name       Always generate a name for the app
  -h, --help                help for launch
      --image string        the image to launch
      --name string         the name of the new app
      --no-deploy           Do not prompt for deployment
      --now                 deploy now without confirmation
      --org string          the organization that will own the app
      --path string         path to app code and where a fly.toml file will be saved. (default ".")
      --region string       the region to launch the new app in
      --remote-only         Perform builds remotely without using the local docker daemon (default true)

Global Flags:
  -t, --access-token string   Fly API Access Token
  -j, --json                  json output
      --verbose               verbose output

Since there's a --generate-name option maybe I use that if the user doesn't specify the -a option.

simonw commented 2 years ago

I created a fly.toml and Dockerfile manually, then figured out this command to deploy without stopping to ask questions about various things:

flyctl launch --copy-config --name simon-tiddlywiki --region sjc --now
simonw commented 2 years ago
fly-temp % fly volumes create simon-tiddlywiki_volume --region sjc --size 1
Error failed creating volume: Validation failed: Name only allows alphanumeric characters and underscores

So no - in volume names.

simonw commented 2 years ago
fly-temp % fly volumes create simon_tiddlywiki_volume --region sjc --size 1      
        ID: vol_70zy6r7qepnvdjng
      Name: simon_tiddlywiki_volume
       App: simon-tiddlywiki
    Region: sjc
      Zone: c0a5
   Size GB: 1
 Encrypted: true
Created at: 21 Jan 22 20:38 UTC

Only actually I want JSON. So I deleted that volume with fly volumes delete xxx and ran this:

 % fly volumes create simon_tiddlywiki_volume --region sjc --size 1 --json
{
    "id": "vol_gez1nvxwldjrmxl7",
    "App": {
        "Name": "simon-tiddlywiki"
    },
    "Name": "simon_tiddlywiki_volume",
    "SizeGb": 1,
    "Snapshots": {
        "Nodes": null
    },
    "Region": "sjc",
    "Encrypted": true,
    "CreatedAt": "2022-01-21T20:40:08Z",
    "AttachedAllocation": null,
    "Host": {
        "ID": "c0a5"
    }
}

(fly and flyctl are apparently aliases to each other now)

simonw commented 2 years ago

Now this worked:

fly-temp % flyctl launch --copy-config --name simon-tiddlywiki --region sjc --now 
An existing fly.toml file was found for app simon-tiddlywiki
App is not running, deploy...
Deploying simon-tiddlywiki
==> Validating app configuration
--> Validating app configuration done
Services
TCP 80/443 ⇢ 8080
...
v0 is being deployed

1 desired, 1 placed, 0 healthy, 0 unhealthy [health checks: 1 total, 1 passing]

But... https://simon-tiddlywiki.fly.dev/ is currently giving me this error:

Secure Connection Failed

An error occurred during a connection to simon-tiddlywiki.fly.dev. PR_END_OF_FILE_ERROR

Maybe the letsencrypt certificate hasn't been issued yet?

simonw commented 2 years ago
~ % curl 'https://simon-tiddlywiki.fly.dev/'            
curl: (35) Server aborted the SSL handshake
~ % curl 'https://simon-tiddlywiki.fly.dev/' --insecure
curl: (35) Server aborted the SSL handshake

Maybe it's not a certificate issue. Maybe I didn't open the port correctly?

Datasette is running there according to the logs:

fly-temp % flyctl --app simon-tiddlywiki logs
2022-01-21T20:41:37.016 runner[0ffeb16a] sjc [info]Starting instance
2022-01-21T20:41:37.051 runner[0ffeb16a] sjc [info]Configuring virtual machine
2022-01-21T20:41:37.052 runner[0ffeb16a] sjc [info]Pulling container image
2022-01-21T20:41:39.255 runner[0ffeb16a] sjc [info]Unpacking image
2022-01-21T20:41:41.124 runner[0ffeb16a] sjc [info]Preparing kernel init
2022-01-21T20:41:41.251 runner[0ffeb16a] sjc [info]Setting up volume 'simon_tiddlywiki_volume'
2022-01-21T20:41:41.254 runner[0ffeb16a] sjc [info]Uninitialized volume 'simon_tiddlywiki_volume', initializing...
2022-01-21T20:41:41.334 runner[0ffeb16a] sjc [info]Encrypting volume
2022-01-21T20:41:47.908 runner[0ffeb16a] sjc [info]Opening encrypted volume
2022-01-21T20:41:49.818 runner[0ffeb16a] sjc [info]Formatting volume
2022-01-21T20:41:50.119 runner[0ffeb16a] sjc [info]Configuring firecracker
2022-01-21T20:41:50.224 runner[0ffeb16a] sjc [info]Starting virtual machine
2022-01-21T20:41:50.373 app[0ffeb16a] sjc [info]Starting init (commit: 0c50bff)...
2022-01-21T20:41:50.388 app[0ffeb16a] sjc [info]Mounting /dev/vdc at /data w/ uid: 0, gid: 0 and chmod 0755
2022-01-21T20:41:50.393 app[0ffeb16a] sjc [info]Preparing to run: `/bin/sh -c datasette serve --host 0.0.0.0 --cors --inspect-file inspect-data.json /data/tiddlywiki.db --create --port $PORT` as root
2022-01-21T20:41:50.408 app[0ffeb16a] sjc [info]2022/01/21 20:41:50 listening on [fdaa:0:4ef:a7b:ad1:0:7cde:2]:22 (DNS: [fdaa::3]:53)
2022-01-21T20:41:51.150 app[0ffeb16a] sjc [info]INFO:     Started server process [524]
2022-01-21T20:41:51.150 app[0ffeb16a] sjc [info]INFO:     Waiting for application startup.
2022-01-21T20:41:51.151 app[0ffeb16a] sjc [info]INFO:     Application startup complete.
2022-01-21T20:41:51.151 app[0ffeb16a] sjc [info]INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
2022-01-21T20:42:26.720 proxy[0ffeb16a] sjc [info]Health check status changed 'warning' => 'passing'
simonw commented 2 years ago

I think I've hit this bug: https://community.fly.io/t/moving-to-fly/1412

It appears the particular app you’re refering to doesn’t have any IPs assigned to it. The .fly.dev hostname for it points to an older IP from a deleted app (I assume). Deleting an app an recreating one with the same name later might cause the DNS record to point to the wrong IP.

Did you remove IP assignments from your app?

simonw commented 2 years ago

I ran fly apps destroy simon-tiddlywiki - I'm going to try again with simon-tiddlywiki2

Here's the fly.toml I'm using:

# fly.toml file generated for simon-tiddlywiki on 2022-01-21T12:35:22-08:00

app = "simon-tiddlywiki2"

[[mounts]]
  destination = "/data"
  source = "simon_tiddlywiki_volume"

[[services]]
  internal_port = 8080
  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

And the Dockerfile:

FROM python:3.8
COPY . /app
WORKDIR /app

ENV DATASETTE_SECRET '...'
RUN pip install -U datasette datasette-tiddlywiki
RUN datasette inspect  --inspect-file inspect-data.json
ENV PORT 8080
EXPOSE 8080
CMD datasette serve --host 0.0.0.0 --cors --inspect-file inspect-data.json /data/tiddlywiki.db --create --port $PORT
simonw commented 2 years ago

The relationship between apps and volumes isn't entirely obvious to me.

It looks like volumes HAVE to belong to an app - and deleting an app also deletes its volume.

It also looks like you can't run volumes create without first creating an app:

% fly volumes create simon_tiddlywiki_volume --region sjc --size 1 --json
Error Could not resolve App

Which suggests to me that volumes may currently be incompatible with the fly launch command - because that command both creates an app and then deploys it, but you need to actually do the following:

  1. Create the empty, named app
  2. Create the volume
  3. Deploy the app with a fly.toml that mounts the volume
simonw commented 2 years ago

(This issue has turned into a research issue where I try to figure out how to deploy a Fly app with a volume such that Datasette can write to it, so it's actually more about #10 than it is about fixing the current bug.)

simonw commented 2 years ago

Tried it again, like this:

flyctl apps create --name simon-tiddlywiki-3
fly volumes create simon_tiddlywiki_volume_3 --region sjc --size 1 --json
flyctl deploy --region sjc --now

Weird: https://simon-tiddlywiki-3.fly.dev/ is giving me that "An error occurred during a connection to simon-tiddlywiki-3.fly.dev. PR_END_OF_FILE_ERROR" error again.

But in my terminal:

~ % host simon-tiddlywiki-3.fly.dev
simon-tiddlywiki-3.fly.dev has address 109.105.217.25

And in the web console:

image
simonw commented 2 years ago

Error is gone now - took a few minutes but https://simon-tiddlywiki-3.fly.dev/ now serves correctly.

simonw commented 2 years ago

It seems to work! I used the TiddlyWiki interface to create a tiddler and it was persisted.

Not sure how to check that it's persisted on the volume though, since destroying the app appears to also destroy any attached volumes.

simonw commented 2 years ago

I'll try shipping another deploy that adds a new plugin.

simonw commented 2 years ago

Yes, that worked - I shipped a deploy adding the datasette-graphql plugin and it kept the tiddlewiki.db data I had already created.

simonw commented 2 years ago

Tried another deploy adding a metadata.yml file and it worked too:

databases:
  tiddlywiki:
    tables:
      tiddlers:
        plugins:
          datasette-graphql:
            json_columns:
            - meta

Now this query returns nicely: https://simon-tiddlywiki-3.fly.dev/graphql?query=%7B%0A%20%20tiddlers%20%7B%0A%20%20%20%20totalCount%0A%20%20%20%20nodes%20%7B%0A%20%20%20%20%20%20title%0A%20%20%20%20%20%20meta%0A%20%20%20%20%20%20revision%0A%20%20%20%20%20%20text%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D

simonw commented 2 years ago

I need to add authentication to datasette-tiddlywiki:

simonw commented 2 years ago

Research complete, switching back to this issue for the implementation: