I am trying to migrate from Elastic Beanstalk to AWS App Runner, but AWS App Runner does not seem to consider the environment variable during it's build
phase.
Would really like to use AWS AppRunner out of the box, part of the reason of migrating to app runner was ease of use and quickly pushing code and having it published.
name: Deploy to Elastic Beanstalk
on:
push:
branches:
- main
- dev
workflow_dispatch:
env:
BUCKET_NAME: marketbase-web
DEV_APP_NAME: Marketbase-web-dev
MAIN_APP_NAME: marketbase-web-prod-2
DEV_ENV_NAME: Marketbase-web-dev-env
MAIN_ENV_NAME: marketbase-web-prod-2-env
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Generate Last Updated Timestamp
run: echo "NEXT_PUBLIC_LAST_UPDATED=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > .env.local
working-directory: ./
- name: Log environment variables
run: |
echo "NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}"
echo "NEXT_PUBLIC_STANDARD_PRICE_ID=${{ secrets.NEXT_PUBLIC_STANDARD_PRICE_ID }}"
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Build Next.js project
run: |
if [ "${{ github.ref }}" == "refs/heads/dev" ]; then
export NEXT_PUBLIC_API_URL=${{ secrets.DEV_NEXT_PUBLIC_API_URL }}
export NEXT_PUBLIC_STANDARD_PRICE_ID=${{ secrets.DEV_NEXT_PUBLIC_STANDARD_PRICE_ID }}
export NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${{ secrets.DEV_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
export NEXT_PUBLIC_M_API_KEY=${{ secrets.DEV_NEXT_PUBLIC_M_API_KEY }}
export NEXT_PUBLIC_CLOUDFRONT_URL=${{secrets.DEV_NEXT_PUBLIC_CLOUDFRONT_URL}}
export NEXT_PUBLIC_ENVIRONMENT=${{secrets.DEV_NEXT_PUBLIC_ENVIRONMENT}}
else
export NEXT_PUBLIC_API_URL=${{ secrets.PROD_NEXT_PUBLIC_API_URL }}
export NEXT_PUBLIC_STANDARD_PRICE_ID=${{ secrets.PROD_NEXT_PUBLIC_STANDARD_PRICE_ID }}
export NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${{ secrets.PROD_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
export NEXT_PUBLIC_M_API_KEY=${{ secrets.PROD_NEXT_PUBLIC_M_API_KEY }}
export NEXT_PUBLIC_CLOUDFRONT_URL=${{secrets.PROD_NEXT_PUBLIC_CLOUDFRONT_URL}}
export NEXT_PUBLIC_ENVIRONMENT=${{secrets.PROD_NEXT_PUBLIC_ENVIRONMENT}}
fi
npm run build
env:
NEXT_PUBLIC_API_URL: ${{ env.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_STANDARD_PRICE_ID: ${{ env.NEXT_PUBLIC_STANDARD_PRICE_ID }}
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${{ env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
NEXT_PUBLIC_M_API_KEY: ${{ env.NEXT_PUBLIC_M_API_KEY }}
NEXT_PUBLIC_CLOUDFRONT_URL: ${{ env.NEXT_PUBLIC_CLOUDFRONT_URL }}
NEXT_PUBLIC_ENVIRONMENT: ${{ env.NEXT_PUBLIC_ENVIRONMENT }}
- name: Cache
uses: actions/cache@v3
with:
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node
path: |
~/.npm
${{ github.workspace }}/.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- name: Generate version label
run: echo "VERSION_LABEL=$(git rev-parse --short HEAD)-$(date +%s)" >> $GITHUB_ENV
- name: Zip the application
run: zip -r ${VERSION_LABEL}.zip . -x '*.git*' 'node_modules/*'
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1 # Change to your desired region
- name: Deploy to Dev Elastic Beanstalk on commit to dev branch
if: github.ref == 'refs/heads/dev'
run: |
aws s3 cp ${VERSION_LABEL}.zip s3://$BUCKET_NAME/dev/${VERSION_LABEL}.zip
aws elasticbeanstalk create-application-version --application-name $DEV_APP_NAME --version-label ${VERSION_LABEL} --source-bundle S3Bucket="$BUCKET_NAME",S3Key="dev/${VERSION_LABEL}.zip"
aws elasticbeanstalk update-environment --environment-name $DEV_ENV_NAME --version-label ${VERSION_LABEL}
- name: Deploy to Main Elastic Beanstalk on commit to main branch
if: github.ref == 'refs/heads/main'
run: |
aws s3 cp ${VERSION_LABEL}.zip s3://$BUCKET_NAME/main/${VERSION_LABEL}.zip
aws elasticbeanstalk create-application-version --application-name $MAIN_APP_NAME --version-label ${VERSION_LABEL} --source-bundle S3Bucket="$BUCKET_NAME",S3Key="main/${VERSION_LABEL}.zip"
aws elasticbeanstalk update-environment --environment-name $MAIN_ENV_NAME --version-label ${VERSION_LABEL}
module.exports = {
env: {
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'default',
NEXT_PUBLIC_CLOUDFRONT_URL: process.env.NEXT_PUBLIC_CLOUDFRONT_URL || 'default',
NEXT_PUBLIC_ENVIRONMENT: process.env.NEXT_PUBLIC_ENVIRONMENT || 'default',
NEXT_PUBLIC_LAST_UPDATED: process.env.NEXT_PUBLIC_LAST_UPDATED || 'default',
NEXT_PUBLIC_M_API_KEY: process.env.NEXT_PUBLIC_M_API_KEY || 'default',
NEXT_PUBLIC_STANDARD_PRICE_ID: process.env.NEXT_PUBLIC_STANDARD_PRICE_ID || 'default',
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || 'default',
},
};
I've even tried using a manual apprunner file and it still will not include the environment variables in the build (they actually disappear from the AppRunner UI until I switch back to the configuration as opposed to apprunner.yaml file.
While I have not been able to directly answer the above, my workaround to deploying Next.JS on AppRunner has been to have github actions deploy to ECR and then use the container in AppRunner as opposed to the source reposistory.
GH Actions and Dockerfile for reference.
name: Build and Push Docker Image to ECR
on:
push:
branches:
- main
- dev
workflow_dispatch:
env:
AWS_REGION: us-east-1 # Change to your AWS region
ECR_REPOSITORY_NAME_DEV: your-ecr-name-space/your-service-dev ECR_REPOSITORY_NAME_MAIN: your-ecr-name-space/your-service-main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
# 1. Checkout the repository
- name: Checkout code
uses: actions/checkout@v2
# 2. Generate Last Updated Timestamp
- name: Generate Last Updated Timestamp
run: echo "NEXT_PUBLIC_LAST_UPDATED=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > .env.local
# 3. Set environment variables based on branch using repository variables
- name: Set environment variables based on branch
run: |
if [ "${{ github.ref }}" == "refs/heads/dev" ]; then
echo "NEXT_PUBLIC_VAR=${{ vars.DEV_NEXT_PUBLIC_VAR}}" >> $GITHUB_ENV
else
echo "NEXT_PUBLIC_VAR=${{ vars.PROD_NEXT_PUBLIC_VAR }}" >> $GITHUB_ENV
fi
# 4. Set up Node.js
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
# 5. Install dependencies
- name: Install dependencies
run: npm install
# 6. Build Next.js project
- name: Build Next.js project
run: npm run build
# 7. Configure AWS Credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 8. Get AWS Account ID
- name: Get AWS Account ID
id: aws_account
run: echo "AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)" >> $GITHUB_ENV
# 9. Set ECR repository URI
- name: Set ECR repository URI
run: |
echo "ECR_REPOSITORY_URI=${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY_NAME }}" >> $GITHUB_ENV
# 10. Login to Amazon ECR
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
# 11. Build Docker image
- name: Build Docker image
run: |
docker build -t $ECR_REPOSITORY_URI:${{ github.sha }} \
.
# 12. Push Docker image to Amazon ECR
- name: Push Docker image to Amazon ECR
run: |
docker push $ECR_REPOSITORY_URI:${{ github.sha }}
# 13. (Optional) Tag the image as 'latest'
- name: Tag and push latest Docker image
run: |
docker tag $ECR_REPOSITORY_URI:${{ github.sha }} $ECR_REPOSITORY_URI:latest
docker push $ECR_REPOSITORY_URI:latest
# Use the official Node.js 18 image as the base
FROM node:18
# Set the working directory inside the container
WORKDIR /app
# Accept build arguments for environment-specific configurations
ARG NEXT_PUBLIC_VAR
# Set environment variables based on the build arguments
ENV NEXT_PUBLIC_VAR=${NEXT_PUBLIC_VAR}
# Copy package.json and package-lock.json to leverage Docker cache
COPY package*.json ./
# Install project dependencies
RUN npm install
# Copy the rest of the application code to the container
COPY . .
# Build the Next.js application for production
RUN npm run build
# Expose port 3000 to allow external access
EXPOSE 3000
# Define the default command to run the application
CMD ["npm", "start"]