In the last post, we created a static front-end application with Svelte + Bulma, and then integrated it into our Rust code + Dockerfile. In this final post, we will cover the process of actually deploying the app to AWS Elastic Beanstalk.
What is Elastic Beanstalk?
Elastic Beanstalk is a service provided by AWS which enables developers to focus purely on application code, without worrying about the infrastructure the code is being run on. Although we won't be exploring the full power of EB, it is capable of capacity provisioning, load balancing, scaling, and application health monitoring.
Manual Deployment
The first step in manually deploying your application is to create a zipped archive of your code to upload to EB. As an effort to stay cross-platform, we will do this using git archive
(this has the added benefit of automatically ignoring anything in the gitignore).
git archive --format=zip HEAD -o ./target/repo.zip
This will place a zip of our repo into the target
folder.
Now we have the zip file, you should following the following steps:
- Login to AWS Console
- Use the search bar to go to the "Elastic Beanstalk" page, and make sure you are in the "Elastic Beanstalk > Environments page"
- Select your desired region using the dropdown menu in the top right
- Click the "Create application" button (alternatively, click "Create Environment, and then select "Web server environment")
- Give your application a suitable name
- Give the application environment (the collection of services that will run your application) the name "production"
- Select the following platform options:
- Upload your zip file, and then click "Create environment"
If you go back the environments page, you will see that an environment with the name "production" has been created. It should have the status "Pending" - you will now have to wait around ten minutes for your application to build and startup (EB uses the docker-compose.yml
file to build the images from scratch on the underlying EC2 instance).
Once the environment health transitions to "Ready", you should be able to go to the provided URL (HTTP only, as setting up HTTPS is beyond the scope of this series).
Creating a Deployment Pipeline
Manually updating your application like this can be time-consuming, so I will now show you how to automatically deploy your code with GitHub Actions.
First, you will need to use the "IAM" service to create a user (so that the workflow can access your AWS account). The user should be called "url-shortener-deploy" and the credential type should be "Programmatic access".
We will be using the Beanstalk Deploy, which requires the AWSElasticBeanstalkWebTier
and AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy
permissions. Make sure to attach these to the IAM role, and then create the user.
Once you have clicked Create user
, you will be shown a table with the access credentials. You will only be shown these once - don't close the window just yet. In a new tab, open your repo on GitHub and add the following secrets (Settings > Secrets > New repository secret):
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
You should set these to the corresponding credentials of your
url-shortener-deploy
user, and then close the credential view on the AWS console.
Next, create a new workflow called deploy.yml
(this should be in the same directory as test.yml
). This action will use the secrets we set in the last step to deploy our code to AWS whenever code is pushed to production.
name: Deploy to AWS
on:
push:
branches:
- production
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Latest Repo
uses: actions/checkout@master
with:
ref: "production"
- name: Generate Deployment Package
run: mkdir target && git archive --format=zip HEAD -o ./target/repo.zip
- name: Get timestamp
uses: gerred/actions/current-time@master
id: current-time
- name: Run string replace
uses: frabert/replace-string-action@master
id: format-time
with:
pattern: '[:\.]+'
string: "${{ steps.current-time.outputs.time }}"
replace-with: "-"
flags: "g"
- name: Deploy to EB
uses: einaregilsson/beanstalk-deploy@v18
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: url-shortener
environment_name: production
version_label: "url-shortener-${{ steps.format-time.outputs.replaced }}"
region: eu-west-2
deployment_package: target/repo.zip
Note: The string replacement step simply sets the code version to the current time.
Testing Auto-Deployment
Now that we have created the workflow, we need to push to the production
branch. Normally we can do this via a PR on the GitHub web interface, but that only works after we have created and pushed the branch. To do this, use the following git commands:
git branch production
git push origin production
If all goes correctly, your workflow should take about 15 minutes to deploy your code to AWS.
Now it's your turn!
Now that you have the barebones structure up and running, perhaps you could try adding the following features:
- persistance with an AWS-provided database (like Aurora or DynamoDB)
- expiring links, so that a given memory / storage limit isn't exceeded
- a fully fleshed-out frontend with common pages (such as an FAQ, contact us)
- a custom domain name + https support for EB
That's all for this series! If you have any issues, make sure to check out the part-6 tag of my repo.
Footnote
If you enjoyed reading this, then consider dropping a like or following me:
I'm just starting out, so the support is greatly appreciated!
Disclaimer - I'm a (mostly) self-taught programmer, and I use my blog to share things that I've learnt on my journey to becoming a better developer. Because of this, I apologize in advance for any inaccuracies I might have made - criticism and corrections are welcome!