Running Astro Node SSR on Fly.io with Docker

Deploying an Astro Node.js application with Server-Side Rendering (SSR) on Fly.io can be made easy with the use of Docker. In this post, we’ll walk through the steps to create a Dockerfile, set up continuous integration (CI) and automatic deployment on Fly.io.

Prerequisites

  • An Astro project with Node.js SSR setup
  • A GitHub account
  • A Fly.io account

Step 1: Create the Dockerfile

Start by creating a Dockerfile in the root of your Astro project. This file will define the Docker image that will be used to run your application:

FROM node:lts-slim as runtime
WORKDIR /app

# Ensure that both node_modules and package-lock.json are removed.
COPY package.json .
RUN rm -rf node_modules package-lock.json

# Perform a fresh installation of npm dependencies.
RUN npm install

# Copy the rest of your application files.
COPY . .

# Build your application.
RUN npm run build

# Set environment variables and expose the appropriate port.
ENV HOST=0.0.0.0
ENV PORT=3000
EXPOSE 3000

# Define the command to run your application.
CMD node ./dist/server/entry.mjs

This Dockerfile does the following:

  1. Starts from the node:lts-slim base image, which provides a lightweight Node.js runtime.
  2. Sets the working directory to /app.
  3. Copies the package.json file and removes any existing node_modules and package-lock.json to ensure a fresh installation of dependencies.
  4. Installs the project dependencies using npm install.
  5. Copies the rest of the application files.
  6. Builds the Astro application using npm run build.
  7. Sets the necessary environment variables and exposes port 3000.
  8. Defines the command to run the application’s server-side entry point.

Also very important, add this .dockerignore (or the build will fail):

.DS_Store
node_modules
dist
.env
.git
.gitignore

After running fly launch , from your local project folder, you should have this fly.toml file:

# fly.toml app configuration file generated for aha-test-flavio on 2024-01-03T13:48:33+01:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = "<your app name>"
primary_region = "<region>"

[build]

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 1024

For environment variables, import existing .env ones using:

cat .env | fly secrets import
(or add them through Fly’s dashboard).

Now run fly deploy --ha=false , from your local project folder, to deploy.

This is without CI/CD. Follow Step 2 for CI/CD

Step 2: Set up CI/CD with GitHub Actions

To enable continuous integration and automatic deployment, we’ll use GitHub Actions. Create a new workflow file in your project’s .github/workflows directory, e.g., deploy.yml:

name: Deploy to Fly.io

on:
  push:
    branches:
      - main

jobs:

  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Deploy to Fly.io
        uses: superfly/flyctl-actions@1.3
        with:
          args: deploy
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

This workflow will be triggered on pushes to the main branch. It uses the superfly/flyctl-actions GitHub Action to deploy the application to Fly.io.

You’ll need to add the FLY_API_TOKEN secret to your GitHub repository. You can obtain this token by logging in to your Fly.io account and generating a new API token.

Step 3: Deploy to Fly.io

  1. Create a new Fly.io application by running fly launch in your project’s root directory. This will create a fly.toml file with the necessary configuration.

  2. If you haven’t already, log in to Fly.io using the CLI by running fly auth login.

  3. Import your existing environment variables from a .env file using cat .env | fly secrets import.

  4. Commit and push your changes to the main branch of your GitHub repository. This will trigger the GitHub Actions workflow, which will build and deploy your Astro application to Fly.io.

After the deployment is complete, you can access your application at the URL provided by Fly.io.

Additional Considerations

  • If you encounter any issues during the deployment, you can troubleshoot by checking the GitHub Actions workflow logs or the Fly.io dashboard.
  • Make sure to keep your Dockerfile up-to-date with any changes made to your Astro project, such as new dependencies or build steps.
  • Consider setting up automatic builds and deployments on other branches (e.g., develop) for a more robust CI/CD pipeline.
  • Explore Fly.io’s advanced features, such as scaling, load balancing, and monitoring, to optimize the performance and reliability of your Astro application.

By following this guide, you can successfully run your Astro Node.js SSR application on Fly.io using Docker, with a smooth CI/CD workflow powered by GitHub Actions.