LaunchFast Logo LaunchFast

Deploy Astro to Amazon ECS on AWS Fargate: A Step-by-Step Guide

Rishi Raj Jain
Deploy Astro to Amazon ECS on AWS Fargate

In this guide, you will learn how to deploy an Astro SSR project to Amazon ECS on AWS Fargate. You will go through the process of setting up a new Astro project, enabling server-side rendering using Node.js adapter, and finally deploying it to Amazon ECS on AWS Fargate.

Table Of Contents

Prerequisites

You’ll need the following:

Create a new Astro application

Let’s get started by creating a new Astro project. Open your terminal and run the following command:

npm create astro@latest my-app

npm create astro is the recommended way to scaffold an Astro project quickly.

When prompted, choose:

Once that’s done, you can move into the project directory and start the app:

cd my-app
npm run dev

The app should be running on localhost:4321.

Next, in your first terminal window, run the command below to install the necessary libraries and packages for building the application:

npm install dotenv

The libraries installed include:

Once it is installed, you’ll need to add it to your astro.config.mjs file. Open the file and add the following code:

import 'dotenv/config'; 
import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({});

Let’s move on to enable Server-Side Rendering by using the Node.js adapter.

Getting Started with the Node.js Adapter for Astro

Before deploying your Astro project, you need to install the @astrojs/node adapter. This is easily done via the Astro CLI:

npm install @astrojs/node

The libraries installed include:

Once the adapter is installed, you’ll need to add it to your astro.config.mjs file. Open the file and add the following code:

import node from '@astrojs/node'; 
import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({
  output: "server", 
  adapter: node({ 
    mode: 'standalone'
  }), 
});

Let’s move on to dockerizing your Astro application.

Dockerize your Astro application

Deploying to Amazon ECS on AWS Fargate requires a AWS ECR repository to be created. Imagine ECR as a handler of Docker based deployments.

To dockerize your Astro application, you’re going to create two files at the root of your Astro project:

Create the .dockerignore file at the root of your Astro project with following code:

# build output
dist/
# generated types
.astro/

# dependencies
node_modules/

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*


# environment variables
.env
.env.production

# macOS-specific files
.DS_Store

Create the Dockerfile file at the root of your Astro project with following code:

ARG NODE_VERSION=20.11.0
FROM node:${NODE_VERSION}-slim as base

WORKDIR /app

# Set production environment
ENV NODE_ENV="production"

# Throw-away build stage to reduce size of final image
FROM base as build

# Install packages needed to build node modules
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3

# Install node modules
COPY --link package-lock.json package.json ./
RUN npm install

# Copy application code
COPY --link . .

# Build application
RUN npm run build

# Final stage for app image
FROM base

# Copy built application
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist

ENV PORT=80
ENV HOST=0.0.0.0

# Start the server by default, this can be overwritten at runtime
EXPOSE 80
CMD [ "node", "./dist/server/entry.mjs" ]

The Dockerfile above defines the following set of actions:

Let’s move on creating a Amazon VPC to accept traffic to your Astro application when deployed.

Create a Amazon Virtual Private Cloud (VPC)

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

and you are now done with setting up Amazon VPC for your account. Let’s move on to creating an Amazon ECR image repository.

Create Amazon ECR private repository

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

and you are now done with setting up an Amazon ECR repository.

Grab Deployment URL in AWS Amplify

Let’s move on to configuring IAM roles for your account.

Configure your IAM Roles

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

and you are now done with setting up IAM Roles for your account. Let’s move on to creating an Amazon ECS task definition.

Create an Amazon ECS task definition

Grab Deployment URL in AWS Amplify
{
  "containerDefinitions": [
    {
      "cpu": 256,
      "memory": 512,
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      "name": "fargate-app",
      "image": "2*.dkr.ecr.ap-south-1.amazonaws.com/repos-astro" // enter your own repo URI
    }
  ],
  "cpu": "1024",
  "memory": "3072",
  "family": "sample-fargate",
  "networkMode": "awsvpc",
  "taskRoleArn": "arn:aws:iam::2*:role/ecsTaskRole", // Enter your own account's role ID
  "executionRoleArn": "arn:aws:iam::2*:role/ecsTaskExecutionRole" // Enter your own account's role ID
}
Grab Deployment URL in AWS Amplify

and you are now done with setting up an Amazon ECS task definition for your service. Let’s move on to creating an Amazon ECS Cluster.

Create an Amazon ECS Cluster

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

and you are now done with setting up an Amazon ECS Cluster your service.

Grab Deployment URL in AWS Amplify

Let’s move on to creating an Amazon ECS Service.

Create an Amazon ECS Service

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

and you are now done with creating an ECS Service in your ECS Cluster. Let’s move on to creating access keys for IAM users for your account.

Create access keys for IAM users

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

Let’s move on to configuring GitHub Workflows for continous deployments.

Create GitHub Actions for Continuous Deployment (CD) Workflow

To automate deployments of your Astro application, you are going to use GitHub Actions.

name: Deploy to Amazon ECS on AWS Fargate

on:
  push:
      branches:
        - master
  workflow_dispatch:

env:
  AWS_REGION: us-west-1 # enter your deployment region
  ECS_SERVICE: service-test # enter your ECS service name
  ECS_CLUSTER: new-cluster # enter your ECS cluster name
  CONTAINER_NAME: fargate-app # enter your container name used in the task definition
  ECR_REPOSITORY: astro-repo # enter your ECS repo name
  ECS_TASK_DEFINITION: ./task-definition.json

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: ${{ env.AWS_REGION }}
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          IMAGE_TAG: ${{ github.sha }}
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        run: |
          # Build a docker container and
          # push it to ECR so that it can
          # be deployed to ECS.
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          container-name: ${{ env.CONTAINER_NAME }}
          image: ${{ steps.build-image.outputs.image }}
          task-definition: ${{ env.ECS_TASK_DEFINITION }}

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          service: ${{ env.ECS_SERVICE }}
          cluster: ${{ env.ECS_CLUSTER }}
          wait-for-service-stability: true
          task-definition: ${{ steps.task-def.outputs.task-definition }}

The workflow above does the following:

Now, push the added workflow file to yoru GitHub repo and, follow the steps below to trigger the deployment:

Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify Grab Deployment URL in AWS Amplify

References

Conclusion

Yay! You’ve now an Astro project that automatically deploys to Amazon ECS on AWS Fargate upon Git push.

If you have any questions or comments, feel free to reach out to me on Twitter.

Learn More Using PhotoSwipe in Astro to Build an Image Gallery → Using Transformers for Shiki to enrich Syntax Highlighting in Astro → Using GreenSock Animation Platform (GSAP) in Astro with View Transitions: A Step-by-Step Guide →