Getting Started on APPUiO Cloud with the Terminal using F#
This tutorial explains how to run applications written in the F# programming language on APPUiO Cloud using the command line.
If you aren’t familiar with issuing commands on a terminal session, you might want to try the Getting Started with F# on the OpenShift Web Console guide instead.
Requirements
To follow this guide, please make sure that you have the following tools installed:
oc
-
You can download the OpenShift command directly from APPUiO Cloud, selecting the help menu (marked as a question mark) and selecting the "Command line tools" entry.
docker
orpodman
-
You can download them from www.docker.com and podman.io.
curl
-
Available from curl.se.
About the Application
To demo how to run applications written in the F# programming language on APPUiO Cloud, we will use a small demo application using the Giraffe Framework, bundled as a container thanks to its corresponding Dockerfile
, and ready to be used on APPUiO Cloud.
You can browse the full source code of this application on GitLab.
The "Fortune in F#" application does a few simple things:
-
When invoked on the browser, it returns a random number and a funny quote.
-
When invoked with an HTTP request including the
Accept: application/json
header, it returns the same information in JSON format. -
Finally, when invoked with an HTTP request including the
Accept: text/plain
header, it returns the same information in plain text format.
Learn more about the fortune-fsharp
application, including how to edit and build it, on the project README.
The Application Router
The code below shows the main router of the application in the F# programming language, located at Program.fs, courtesy of the Giraffe Framework.
let fortuneHandler next (ctx: HttpContext) =
task {
let obj = { Message = fortune(); Hostname = hostname; Version = "1.2-f#"; Number = random() }
let header =
match ctx.GetRequestHeader "Accept" with
| Error msg -> "text/html"
| Ok headerValue -> headerValue
match header with
| "application/json" ->
return! ctx.WriteJsonAsync obj
| "text/plain" ->
return! ctx.WriteTextAsync (sprintf "Fortune %s cookie of the day #%d:\n\n%s" obj.Version obj.Number obj.Message)
| _ ->
return! (razorHtmlView "Index" (Some obj) None None) next ctx
}
let webApp =
choose [
GET >=>
choose [
route "/" >=> warbler (fun _ -> fortuneHandler)
]
setStatusCode 404 >=> text "Not Found" ]
Run the Container
This step is optional; you can easily test the application locally with Docker:
docker run --rm --publish 8080:8080 registry.gitlab.com/vshn/applications/fortune-fsharp:latest
Or with Podman:
podman run --rm --publish 8080:8080 registry.gitlab.com/vshn/applications/fortune-fsharp:latest
Now you can test the application with curl
, for example to get some JSON:
curl http://localhost:8080 --header "Accept: application/json"
Or to see a plain text version:
curl http://localhost:8080 --header "Accept: text/plain"
You can also open a browser and navigate to localhost:8080 to get your fortune cookie of the day.
Dockerfile
The application includes a Dockerfile ready to build a container fully compatible with OpenShift. The snippet below shows the instructions used to build the actual running image:
# Stage 2: runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine
RUN apk add fortune
WORKDIR /dotnetapp
COPY --from=build /build/out .
COPY Views /dotnetapp/Views
EXPOSE 8080
(1)
USER 1001
ENTRYPOINT ["dotnet", "fortune-fsharp.App.dll"]
1 | This explicitly prevents the container from running as root; this is a requirement of OpenShift, and a good practice for images in general. |
You can use the Dockerfile
above to build your own copy of the container, which you can then push to the registry of your choice. Clone the repo:
git clone https://gitlab.com/vshn/applications/fortune-fsharp.git
cd
into it:
cd fortune-fsharp
And build your image with Docker:
docker build -t fortune-fsharp .
Or with Podman instead:
podman build -t fortune-fsharp .
Step 1: Create a Project
Follow these steps to login to APPUiO Cloud on your terminal:
-
Login to the APPUiO Cloud console:
oc login --server=https://api.${zone}.appuio.cloud:6443
You can find the exact URL of your chosen zone in the APPUiO Cloud Portal.
This command displays a URL on your terminal:
You must obtain an API token by visiting https://oauth-openshift.apps.${zone}.appuio.cloud/oauth/token/request
-
Click on the link above and open it in your browser.
-
Click "Display token" and copy the login command shown as "Log in with this token"
-
Paste the
oc login
command on the terminal:oc login --token=sha256~_xxxxxx_xxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx-X \ --server=https://api.${zone}.appuio.cloud:6443
-
Create a new project called "[YOUR_USERNAME]-fortune-fsharp"
oc new-project [YOUR_USERNAME]-fortune-fsharp
-
To deploy the application we will use a standard Kubernetes
Deployment
object. Save the following YAML in a file calleddeployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: fortune-fsharp spec: template: spec: containers: - image: registry.gitlab.com/vshn/applications/fortune-fsharp:latest imagePullPolicy: Always name: fortune-container ports: - containerPort: 8080 metadata: labels: app: fortune-fsharp selector: matchLabels: app: fortune-fsharp strategy: type: Recreate --- apiVersion: v1 kind: Service metadata: name: fortune-fsharp spec: ports: - port: 8080 targetPort: 8080 selector: app: fortune-fsharp type: ClusterIP
-
Then apply the deployment to your APPUiO Cloud project:
oc apply -f deployment.yaml
And wait until your pod appears with the status "Running":
oc get pods --watch
Step 2: Publish your Application
At the moment your container is running but it’s not available from the Internet. To be able to access our application, we must create an Ingress
object.
-
Create another file called
ingress.yaml
with the following contents, customizing the parts marked as[YOUR_USERNAME]
and[YOUR_CHOSEN_ZONE]
to your liking (and according to the Zones documentation page):apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-production name: fortune-fsharp-ingress spec: rules: - host: [YOUR_USERNAME]-fortune-fsharp.apps.[YOUR_CHOSEN_ZONE].appuio.cloud (1) http: paths: - pathType: Prefix path: / backend: service: name: fortune-fsharp port: number: 8080 tls: - hosts: - [YOUR_USERNAME]-fortune-fsharp.apps.[YOUR_CHOSEN_ZONE].appuio.cloud secretName: fortune-fsharp-cert
1 Replace the placeholders YOUR_USERNAME
andYOUR_CHOSEN_ZONE
with valid values.
About URL lengths
Make sure that the total length of the prefix string
If your Ingress doesn’t generate a route after deploying your application, shorten the URL in your YAML and redeploy. |
-
Apply the ingress object to your APPUiO Cloud project and wait until you route shows as available.
oc apply -f ingress.yaml
And wait for your route to be ready:
oc get routes --watch
-
After a few seconds, you should be able to get your daily fortune message using
curl
in plain text!curl https://[YOUR_USERNAME]-fortune-fsharp.apps.[YOUR_CHOSEN_ZONE].appuio.cloud --header "Accept: text/plain"
Or in JSON instead:
curl https://[YOUR_USERNAME]-fortune-fsharp.apps.[YOUR_CHOSEN_ZONE].appuio.cloud --header "Accept: application/json"
Step 3: There’s no Step 3!
The "Fortune in F#" application is now running on APPUiO Cloud. Congratulations! Hit the R key in your keyboard to see a new fortune message, or just wait 10 seconds to get a new one automatically.
What’s next? To run your own application written in F# or using the Giraffe Framework on APPUiO Cloud, follow these steps:
-
Containerize the application making sure it’s compatible with APPUiO Cloud. The
Dockerfile
above can serve as a starting point. -
Enhance the deployment for your application with liveness and health probes, or better yet, create a Helm chart.
-
Configure your CI/CD system to automatically deploy your application to your preferred APPUiO Cloud zone.
Finally, when you’re done testing the fortune application, delete the fortune-fsharp
project with the following command:
oc delete project [YOUR_USERNAME]-fortune-fsharp