9 Steps for building a CI/CD pipeline with Travis-CI, Docker and AWS.
I would be using a simple React app for the frontend, docker for containerisation and AWS for deployment
Requirements:
Travis-CI is a hosted continuous integration(CI) service used to build and test software projects hosted at GitHub.
It basically helps developers automate the process of deploying their code from it’s repository onto the live environment while ensuring all the set tests of the application are passing before it’s allowed unto production.
Step 1: React —
I used an npm package called create-react-app to quickly spin up a react application by running create-react-app sample-app
After this is done, you should see a folder structure like this:
Step 2: Docker —
If you’re at this point, we would need to create a docker image of this application and for this, we would be adding two files named below to the root of our application:
- Dockerfile — Used for building the image that contains the optimized version of this application
- Dockerfile.dev — Used for building the image that contains the development version which would be used to run tests
A Dockerfile file contains instructions that docker uses to build an image of an application
To keep things short, I’d just show you the actual code:
- Dockerfile:
- Dockerfile.dev:
At this point, you should create a new github repository (You can name it sample-docker-react like I did for consistency) and push the simple-app to it.
Your repository should look something like this:
Now we need to connect our repository to travis-ci and for this, we’d move on to:
Step 3: Travis-CI!
I’m assuming you already have an account with travis-ci using your Github account. This gives travis the access it needs to your repositories.
Next, click on your profile icon > settings then toggle on the sample-docker-react
repository we just pushed to Github.
This tells travis-ci to start monitoring the repository. but for this we need a YAML file called .travis.yml
to be added to the application as this would contain the instructions on what you want travis-ci to do with your code when a build is triggered.
Here are some instructions you should add to your .travis.yml file:
sudo: required language: node_js
node_js:
- "stable"
services:
- docker
before_install:
- docker build -t wilpat/sample-app -f Dockerfile.dev .script:
- docker run -e CI=true wilpat/sample-app npm run test -- --coverage
- sudo: required- Travis ci requires the user to be with elevated permission
- language: node_js- A way to specify the language that should be used in building the app
- services- Used to tell travis-ci that we need an instance of docker running for this build
- before_install- An array of things to do with your code before running tests or deploying your code(The instruction here builds the docker image using our Dockerfile.dev file and tags it with the name wilpat/sample-app)
- scripts: An array of scripts to run before deploying your code.(Tests typically go here (The instruction here runs the our test by running image named wilpat/sample-app and overriding the command specified in the Dockerfile.dev)
We’d be needing one more instruction to tell travis-ci how and where to deploy our application, but we first need to setup AWS to receive our code.
Step 4: AWS Elastic Beanstalk—
Disclaimer: Nothing prepares you enough for the maze called AWS
AWS Elastic Beanstalk is an easy-to-use service for deploying and scaling web applications and services developed with Java, . NET, PHP, Node. js, Python, Ruby, Go, and Docker on familiar servers such as Apache, Nginx, Passenger, and IIS.
We need to sign into AWS, hover on services and select Elastic Beanstalk
then select Create New Application
by the top right as seen below:
Enter the application name sample-docker-react
, enter a description (optional) and then submit.
You should be redirected to the application itself and you’d notice a screen like:
We need to create an environment for our application to run in so click the Create one now link.
On the next page, select a Web server environment and you should get directed to a page like below:
Choose docker as the platform for this environment. Then leave the application code at Sample application then submit it and wait for the environment to be built up.
PS: You might need to refresh the page to show the finished environment
If everything went as planned, you should see something like this when it’s finished:
Step 5: AWS IAM —
Identity and Access Management (IAM) provides a way for external platforms to access elastic beanstalk apps in our AWS account.
For this to be possible, we need to create an IAM user and grant the user the appropriate privileges.
Go to Services(at the top left) > IAM > users > Add user on the page.
You should be directed to a page where you’re asked to enter the user name and the access type. I used sample-docker-react
as the username and selected Programmatic access as that’s what this app needs.
The next page asks you to add the set permissions for this user, all you need here is:
- Select Attach existing policies directly
- Search for “elasticbeanstalk” in the table that shows up
- Tick all the options that shows up
- Click next till you create the user.
On success, you’d see a table showing you your AccessKeyID and SecretAccessKey as see below.
PS: You need to store these somewhere as we would be using them in Travis-CI for deploying our app and you’re only able to see the secret key visible once.
Step 6: AWS S3 Buckets—
Amazon S3 or Amazon Simple Storage Service is a service offered by Amazon Web Services (AWS) that provides object storage through a web service interface.
Also, while creating an elastic beanstalk environment, AWS selects a server location closest to you for hosting it(You can select a different location too).
Also, after the environment is created, an S3 bucket is also created bearing a name that’s contains an identifier of this server location (e.g us-east-1, us-west-1) and it is used to store applications that you deployed in environments existing in this same server location.
Secondly, you need to specify a folder(aka bucket path in travis) that would be used by travis-ci for deployment
Goto Services > Storage > S3
Select the bucket with a name that has the identifier of the server location of your environment in it’s name.
Create a folder and you can name it the same name with your application( sample-docker-react
`) this name choice is optional and I do it to help me remember what app it’s for.
Step 7: Back to Travis-CI
You’d need to save the AccessKeyID and SecretAccessKey as an environment variable in Travis-CI.
Go to your dashboard and select the sample-docker-react repository > click on the options by the top right > click on settings.
On this settings page you should add AWS_ACCESS_KEY and AWS_SECRET_KEY like I have done:
Step 8: Back to React —
We need to update our .travis-yml file with the instructions for deploying our code and then push to github.
Update yours with the following:
deploy: provider: elasticbeanstalk region: "your-server-location"
app: "sample-docker-react" env: "SampleDockerReact-env" bucket_name: "elasticbeanstalk-us-east-2-XXXXXXXXXXXX" bucket_path: "sample-app" on: branch: master access_key_id: $AWS_ACCESS_KEY secret_access_key: secure: "$AWS_SECRET_KEY"
- deploy: Tells Travis-ci how to deploy your app
- provider: Platform to be used
- region: Where the server of your elastic beanstalk app environment exists(Update the file with yours)
- app: Then name you gave your application
- bucket_name: The s3 bucket generated for the server location used for your environment
- bucket_path: The folder we created on aws to receive the app sent from travis-ci
- on: Tells travis-ci which github branch update should trigger a build
- access_key_id: IAM access key generated in AWS but stored in travis ci
- secret_access_key: IAM secret key generated in IAM of AWS but stored in travis ci
Now our .travis.yml file should look something like:
Step 9: Push to git —
Cross check your files and setup to ensure you did all I talked about in this walkthrough then Add, commit and push your updates to the repo on github.
Since we’ve added a .travis.yml file, travis-ci would pick up the update in few seconds and trigger a build.
After a successful build, Go to your application on AWS and you should see it get updated with the new code from travis, build the docker image, and start up the application which can be access when you click the link provided.
Now anytime we update the master branch of our application, travis-ci picks up the changes and updates our application that lives in AWS.
If you made it here, thanks a lot for reading through! Here are little hints that you deserve ;)
- Using the
after_success
instruction in the .travis.yml, we could separate concerns by letting travis-ci handle all the docker builds and then push the docker image to docker hub and setup AWS to only pull the new image instead of having to send the whole app to AWS and get it to build it there. - All code for this can be gotten here: https://github.com/wilpat/sample-docker-react
- If you don’t want to get charged for using AWS, please delete the elastic beanstalk application.