In our previous post we learned how to deploy our application to AWS Elastic Beanstalk using Docker and building our images directly on the created instances. This approach works well most of the time but in some cases we need to take into consideration other options.
In this post we’re going to learn an alternative way to deploy our application using Docker Hub to automate some parts of the process and optimize the use of our instances.
My personal experience
To better understand why I decided to use Docker Hub first let me share a personal experience about how I discovered it.
At Wolox, we have been working on web projects in .NET Core using an AWS service — Elastic Beanstalk — as our deployment platform of preference. We usually deploy our code to these environments quite often and sometimes the instances would stop working right in the middle of a deployment. This caused us a bit of irritation because it meant we had to wait 10 - 15 minutes for it to fail, reboot the instance and try it again. It was a waste of time and it could mean a downtime of 20 minutes or more for the application development process to continue. Doing a bit of research, I discovered that our instances were overloading due to all of the work that they had to do when a new version was being deployed. That's when I started to search for alternative methods to deploy our application and I stumbled upon Docker Hub.
The premise is simple: Docker Hub gives us a space to host and manage our Docker containers. This way we can delegate all the hard and tedious work to it.
The main purpose of doing this is to separate the container management from the deployment service. Once Docker Hub informs us that our new image has been built correctly, we’re ready to deliver it to whichever service we prefer. This has a huge benefit over traditional methods because separating the image building process from the actual instance means that our application environment will keep running until we do the actual deployment.
But that's not all! Docker Hub also comes with many handy features to make our work easier.
In my opinion, the true star features are these two:
Autobuild: Docker Hub automatically pulls our code from GitHub or BitBucket, locates the Dockerfile in it and starts building, tagging and pushing the image into the container.
Autotest: Docker Hub starts running our application tests after building the image and allows us to automatically stop the push process if anything fails.
You can get more information about Docker Hub here.
AWS - Elastic Beanstalk
As I mentioned before, using Docker Hub allows us to choose any deployment service that supports Docker containers. This means that we are not necessarily tied to a specific deployment service. We can adapt this solution to our desired service. In this post we’ll be using Elastic Beanstalk as our deployment platform because it comes with an easy way to configure the Docker Hub integration and an even easier way to continue deploying newer versions.
You can get more information about AWS here.
Github or BitBucket
As mentioned above, we’ll be using the Docker Hub Autobuild tool, which requires you to use either GitHub or BitBucket to host your code.
In this post, I will be using GitHub. You can get more information about it here
Using Docker has the benefit of not being attached to a specific tech, in this post I will be using a simple MVC application in .NET Core. For more information on how to install it you can check out this post and for more information on how to create an MVC application you can read our previous post.
Before we can start, we will need:
- A Docker Hub account
- An account on our preferred hosting service. In this post I will be using AWS Elastic Beanstalk
- A GitHub or BitBucket account linked to our Docker Hub account. Follow this quick tutorial to set it up
And for this specific post, I will also be using the following tools:
- AWS Elastic Beanstalk Command Line Interface (this tool simplifies the deployment to AWS)
- Docker CE (required to manage our Docker images)
- .NET Core SDK (used to generate the application we will be deploying. I will be using the default MVC application created with `dotnet new mvc`)
- Visual Studio Code or your text editor of preference
Finally, we will need to set the autobuild configuration in Docker Hub. I’m using a Regex`/(release)/` to catch any branch named release but you can use your own.
Now we just need to follow the next steps:
1. Add a Dockerfile to your project. Docker will use this file to know how to build your image. This is a default Dockerfile for .NET Core projects we usually use:
2. Login to Docker using `docker login`. This will create a file located at `.docker/config.json` that you’ll need later. Take this file and edit it so that it matches this format (I didn’t need to change the file name, but your mileage may vary here).
3. Add a `Dockerrun.aws.json` file to your project.
4. Go to AWS web console and create an Elastic Beanstalk application. Next, create an environment selecting Docker as your platform and choose the “upload your code” option. This will take a few minutes and your application won’t start properly the first time, so don’t worry if you see an error message.
5. Now let's head to AWS S3 and create a private bucket to store your Docker credentials. Upload the `config.json` file edited in step 2.
6. Go to EC2 and search for your recently created instance. Once there, update its IAM credentials and attach theAmazonS3ReadOnlyAccess policy. It should be set like the following image:
7. Initialize the AWS EB CLI using the `eb init` command, follow the steps and, once it’s done, go to the `.elasticbeanstalk` folder and configure the `config.yml` file to only upload the Dockerrun.aws.json file. Our file should look like this:
8. Push your code to a branch that meets the conditions set in Docker Hub autobuild (in my case, I will be pushing a branch called release)
9. Hold on until Docker Hub finishes building the image, once the status is “Success” you’re ready to deploy it on Elastic Beanstalk
10. Use `eb deploy` command in terminal to automatically upload the `Dockerrun.aws.json` file. Now Elastic beanstalk will start to update our application using our Docker Hub container. This process should only take a few minutes.
That’s it! Now, every time we want to update our application, we only need to push our code to a branch that matches our regex, wait for Docker Hub to build your image and deploy it to AWS.
Now we have our application up and running. We just learned how to use Docker Hub to manage, build and deploy our Docker images. This process has the benefits of being really intuitive, providing a good way of tracking errors and helping to maintain an organized structure in our project.
Stay tuned for our next post!