TheSharperDev

Educating about C# and F#

Deploy A Giraffe App to Fly.io

Fly is a platform for running full stack apps and databases close to your users. ~ Fly.io

Creating a new Giraffe App

Creating a giraffe app is as simple as following the instructions on the giraffe template repo.

//download templates
dotnet new -i "giraffe-template::*"

//to create just a fsproj
dotnet new giraffe

//to create a full giraffe solution with tests
dotnet new giraffe --Solution

Once you have a solution, you’ll need to navigate to fly.io and signup for an account and log into their flyctl cli tool.

Creating a Dockerfile

Fly is able to recognize certain project types, F# or AspNetCore are not on that list. So we will dockerize our app. Creating a Dockerfile at the base of your repo with these contents.

## Using sdk build image
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine3.14 AS build-env
WORKDIR /app

# Copy fsproj file over and restore
COPY ./src/flytest/flytest.fsproj ./
RUN dotnet restore

# Build application
COPY ./src/flytest ./
RUN dotnet publish -c Release -o out --no-restore

# Leverage runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine3.14
WORKDIR /app

# Copy over already build components
COPY --from=build-env /app/out .

# Expose your port, this must match the `internal_port` in your soon to be created `fly.toml`
EXPOSE 5000
ENV ASPNETCORE_URLS=http://+:5000
ENTRYPOINT ["dotnet", "flytest.App.dll"]

Take note that 5000 is the default port for your giraffe app, update this if you want to change the default.

Also create a .dockerignore file to tell Docker which things not to copy.

bin
obj
Dockerfile

Create a Fly Deployment

To create a new fly deployment, run flyctl launch in your base directory (where your Dockerfile is) to allow fly to create a deployment.

You’ll walk through the options, select whichever settings are most convenient to you.

Fly will build and upload your image, as well as generate a fly.toml file to store configuration.

Once your first app deployment succeeds, we’ll modify the port in the fly.toml and redeploy.

app = "<test app>-2719"

kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 5000 #ensure this matches your exposed Dockerfile port and your app
  processes = ["app"]
  protocol = "tcp"
  script_checks = []

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

Once you update that, run flyctl deploy to redeploy your app. Then run flyctl open to access your newly deployed app!

References