Enable javascript in your browser for better experience. Need to know to enable it? Go here.
Blogs Banner

Continuous Deployment of a Static Website to AWS with SnapCI

Implementing a deployment pipeline does not have to be difficult, and this article will show you how to use Thoughtworks' SnapCI to deploy a static website to the cloud using Amazon Web Services (AWS).

In the book "Devops na Prática" (currently only available in Portuguese), I show how to configure a deployment pipeline for a non-trivial Java web application. One of the main objectives of the book is to show how to apply the principles of DevOps and continuous delivery in practice, but we had to make choices about which tools and libraries to use in our examples. This article is an extension to the book's content to show that we can apply the same practices using other tools, even for a completely different type of application.

As part of the book launch, we built a static website to aggregate information, testimonials and act as a marketing landing page for the book.

Static website for the book

The website source code is available on Github and the production environment is running on Amazon, using these AWS services: S3, CloudFront, and Route 53.

Continuous Delivery or Continuous Deployment?

This is a question I hear frequently. In this post, Jez Humble explains the difference. Continuous deployment is the practice of releasing every good commit that goes through the pipeline to production, without any manual intervention. Continuous delivery is the practice where every good commit can potentially go to production, but the moment when the release should happen is a business decision.

To better understand the difference, consider two companies with different business models: the first one sells software as a service (SaaS) while the second one distributes software to their customers and charges license fees depending on how many copies are installed.

While the first company can decide to do continuous deployment, releasing to production the most recent changes, the second company might prefer a slower delivery cadence because each new release requires repackaging and distribution of the software upgrade across all their customer base.

Regardless of which approach you decide to use, they both require a change in mindset: any commit can be chosen to go to production. This requires discipline, automation and this is where DevOps practices can help. In particular, you have to create a deployment pipeline that models your current software release process in an automated fashion. Every commit that goes through the pipeline successfully is a release candidate that can go to production.

SnapCI

SnapCI is a service developed and maintained by Thoughtworks Studios, the product division of Thoughtworks. It helps you go from continuous integration to continuous delivery, with native support for creating deployment pipelines.

SnapCI integrates with Github and supports applications written in various platforms – Ruby, Java, JavaScript, Rails, Node.JS, or Python – using different types of databases – Sqlite3, PostgreSQL, MySQL, Redis, CouchDB, and MongoDB. It also supports different deployment options if your production environment is on Heroku or AWS. You can read the documentation to learn more details about the platforms and deployment options supported by SnapCI.

The Production Environment

The production environment on AWS is relatively simple. We are using S3 (Simple Storage Service) to store all our static files: HTML, CSS, Javascript, images, etc. S3 acts as a kind of file system that is highly resilient, where each object is replicated multiple times to increase the durability in case of a disaster.

There are two basic concepts on S3: buckets and objects. A bucket acts as a namespace that is uniquely identifiable across all of AWS. Inside the bucket you create objects that can be files or folders. Both buckets and objects have security properties that allow you to define their access rules.

Although S3 can be used independently to host an entire static website, our production environment also uses CloudFront that acts as a Content Distribution Network, or CDN. A CDN is a network of edge nodes spread around the globe that act as a local cache for the original content, which in this case is hosted in S3. When users try to access a given URL, they are routed to a node that is geographically close to their location, offering a better performance to fetch the content.

Finally, we also use Route 53 to configure the DNS host zone for our static website. With the integration between AWS services, we can use Route 53 to redirect our website's entry point URLs ( www.devopsnapratica.com.br and devopsnapratica.com.br) to our CDN distribution in CloudFront.

To create the project, you must choose which Github repository will be the trigger. In our case, we click the + Add button on the devops-book-site repository. You will not see that project listed unless you have a fork on your GitHub account.

SnapCI supports different types of stages for you to choose – Rake, RSpec, Capybara, etc. In our case we want to define which tasks to execute, so we will choose Custom Stage. On the next screen, we will need to name our stage and define the commands to execute on each task:

For security reasons, you should not commit any sensitive information in plain text on your Github repository. If you do, anyone can use your AWS credentials to spin up multiple AWS resources using your account and you will have to pay the bill at the end of the month. That is why we decided to configure this information as environment variables that will be available at deploy time without requiring them to be committed in the repository. To understand how they are used, you can look at the s3_website.yml configuration file:

​s3_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
s3_secret: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
s3_bucket: <%= ENV['S3_BUCKET'] %>
...

Once you click OK your project will be created and, within a few moments, SnapCI will start executing your first build:

Success! We have configured a simple deployment pipeline consisting of a single stage that will deploy a static website to AWS every time a new commit is made to Github. For mode complex applications, your pipeline will probably require more than one stage, so you can test it and get enough confidence before releasing it to production.

As new commits are made, SnapCI will keep a history of your deployment pipeline execution, giving you end to end traceability from commit to deployment:

Conclusion

In this article we showed how to configure a simple deployment pipeline to implement continuous deployment of a static website to AWS using SnapCI. The source code is available on Github if you want to get more details about how we are using these tools.

Although our example is simple, it shows how easy it is to create and configure a deployment pipeline using SnapCI. SnapCI has many other features that were not covered in this article, such as: artifact promotion, pipelines with multiple stages, manual trigger for stages, support for integration pipelines to track Github branches, deploy to Heroku, and much more. You can explore the SnapCI documentation to learn more details and subscribe to their blog to keep up-to-date about the latest news and releases.

To better understand the concepts and practices presented in this article or to see a more complete and elaborate example, you can read the book DevOps na Prática, currently only available in Portuguese. The static website discussed in this article is live on http://www.devopsnapratica.com.br/ and it has more information about the book's content (currently only available in Portuguese).

Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.

Keep up to date with our latest insights