Deno on Fly

The Deno LogoDeno has reached version 1.0, and congratulations to all involved. Deno is a better Nodejs, with TypeScript baked in and intergrated package management. We’re going to show you how to deploy Deno applications onto Fly and let your applications run closer to your users.

We’ve been working with Deno for Fly for a while and its great blend of TypeScript, V8, Rust and simplicity makes for a great app experience. And great apps deserve a great deployment. We enjoy Deno so much that when we brought out our first cloud native buildpack we made it specifically for Deno.

That’s not the only way to deploy Deno on Fly. Fly is flexible and can run with buildpacks or you can just use a Dockerfile. In this article, we’ll take you through building and deploying Deno with a Dockerfile.

Why use a Dockerfile?

Using a Dockerfile gives you complete control of the packaging of your applications, paring the process down to the bare minimum steps. With a buildpack, to make things as simple as possible, various assumptions are made for you (what underlying OS, how the files are organized, which ports are open by default) and this can lead to larger images than necessary.

So, you may get going with a buildpack, but if you are comfortable with the Dockerfile syntax and how it builds images, you can get quite the build time performance boost and a smaller image file to boot.

Building with a Dockerfile

We’ve put a modified version of our tutorial example, hellodeno, up on the fly-examples repo. Clone or download hellodeno-dockerfile and we can begin. Let’s look at what files there are first:

    Dockerfile  
    README.md   
    deps.ts     
    server.ts

The new files here, over the original hellodeno, are the Dockerfile and the deps.ts file. The Dockerfile is based on the readme example in deno-docker, a repository of Docker images for Ubuntu, Centos, Debian and Alpine Linux.

Let’s step through the Dockerfile and see what it does:

    FROM hayd/alpine-deno:1.0.0

The first line brings in the Alpine Linux and Deno base image, already loaded with the Deno 1.0.0 toolchain.

    EXPOSE 8080 

Our application opens up port 8080 to do its work, so we expose that in the Dockerfile configuration.

    WORKDIR /app

The application will be set up in the /app directory of the image (avoiding the sometimes problematic mistake of loading code into the root of the filesystem).

    USER deno

And best practices say that even running in a container, you shouldn’t run as root, so the Dockerfile switches over to use a deno user.

    COPY deps.ts .
    RUN deno cache deps.ts

As noted, there is also a deps.ts file in our directory. This is a Deno convention of a single file which exports the dependencies that Deno automatically imports. Using this file, it’s possible to pin Deno imports to a particular version. Here, the Dockerfile copies that file across and then asks Deno to cache all the packages referenced in it. These will all go into their own layer in the Docker image.

    COPY . .
    RUN deno cache server.ts

We now copy all the other files over to the Docker image, and do a similar caching step with our code, server.ts.

    CMD ["run","--allow-net", "server.ts"]

Finally, we tell Docker the command to run this image’s contents. The ENTRYPOINT is set to “deno” in the alpine-deno image we’re building with so the CMD settings are combined with the entry point to create a startup command deno run --allow-net server.ts.

Now, there’s a file in the repo, the .dockerignore file, which lists files not to be copied over to that image. Pro-tip: remember to include your .git directory in there so that your Docker image doesn’t include the complete history of your application.

Testing locally

You may want to test your image before you attempt to deploy it. Make sure you have Docker installed and run:

    docker build -t deno-test .
    docker run -p 8080:8080 deno-test

And browse to http://localhost:8080 to see a greeting from the example app.

Deploying to Fly

We’ll assume you are all signed up, logged in and have the essential flyctl installed. If not, catch up by following our quick step-by-step Hands-On.

The first thing you need to do to deploy an app on Fly is to create a slot for the app on the platform and a fly.toml file for the deployment settings. That’s all done with one command flyctl init:

flyctl init
Selected App Name: hellodeno-dockerfile
? Select organization: Dj (dj)
? Select builder: Dockerfile
    (Use the existing Dockerfile)
New app created
  Name     = hellodeno-dockerfile  
  Owner    = dj                    
  Version  = 0                     
  Status   =                       
  Hostname = <empty>               

Wrote config file fly.toml

The flyctl init command will prompt you for an application name. We recommend you go for an auto-generated name, you can enter one but it may be rejected because it matches an already existing app. Then you’ll be asked what organization you want the app created under. Organizations are a way of sharing apps between Fly users, so for now, as we aren’t sharing this, select your personal organization (the one with your name). Once you’ve done that the fly.toml file will be created.

Now it’s time to deploy. Run flyctl deploy and the image will be created and pushed onto the Fly platform. Once it’s there it will be deployed to a datacenter and a given a host name.

To find that hostname, run flyctl info:

flyctl info
App
  Name     = hellodeno-dockerfile          
  Owner    = dj                            
  Version  = 0                             
  Status   = running                       
  Hostname = hellodeno-dockerfile.fly.dev  

Services
  PROTOCOL   PORTS                    
  TCP        80 => 8080 [HTTP]        
             443 => 8080 [TLS, HTTP]  

IP Addresses
  TYPE   ADDRESS                                CREATED AT  
  v4     77.83.140.153                          1m37s ago   
  v6     2a09:8280:1:2d25:fb3e:66b3:de90:905b   1m37s ago   

And there’s our hostname, hellodeno-dockerfile.fly.dev. Now connect to http://hellodeno-dockerfile.fly.dev (substituting in your app’s hostname as appropriate) and you should see a greeting from the application. You’ll also notice that you’ve been redirected to the https version of the site and had your application automatically secured.

Next with Deno

That is far from the end of what you can do with a Deno application on Fly. You can scale a Deno application around the world and add multiple domain names with automatically generated certificates to it, just like every other Fly application. So spread your Deno wings on Fly and make your great app today - don’t forget to tell us about it too. As for us? We’ll be building more examples, as well as production applications, with Deno and you’ll read about any insights we gain from the Deno and Fly combination here.