In today’s article I will try to setup and explain complete workflow of creating some simple project from start, then how to create docker container for it and commit everything to your Github branch. In next step I will explain how to setup TravisCI for continuous deployment of your project to your hosting. (AWS ElasticBeanstalk in my case). For a basic project we will create simple React App. This article is not intended to explain in detail React, Docker, Github, TravisCI or AWS but only workflow of complete process of building some project.
So for start you need to have Github account, TravisCI account, AWS account and Docker installed and configured on your local machine. Complete code of this project is available on my Github.
First we need to create some workdir on our machine. For example:
then we go inside that directory and create simple basic react app with:
cd dockerreact create-react-app dockerizereact
After creating of react app is finished we can test installation. Go inside dockerizereact and run:
cd dockerizereact npm run start
So if everything is ok and your React App can run we can create Dockerfile.dev inside root of your app. We will use this Dockerfile only for our development purposes. For production we will use another Dockerfile.
FROM node:alpine WORKDIR '/app' COPY package.json . RUN npm install COPY . . CMD ["npm", "run", "start"]
As you see we will pull basic node:alpine image from docker hub, workdir inside our container is /app, then we copy our package.json from our root folder and then npm install is runing inside container. Next step is copy everything that we have in our root to container root ( COPY . . )
And here is Dockerfile for production. In this file we also pull nginx image from docker hub.
FROM node:alpine as builder WORKDIR '/app' COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx EXPOSE 80 COPY --from=builder /app/build /usr/share/nginx/html
After that we need to setup docker-compose.yml also in root folder of our app.
version: '3' services: web: build: context: . dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - /app/node_modules - .:/app tests: build: context: . dockerfile: Dockerfile.dev volumes: - /app/node_modules - .:/app command: ["npm", "run", "test"]
As you see we have two services here web & tests. Tests is only for testing our app ( command: [“npm”, “run”, “test”] ). In volumes we have reference inside container to everything in our root of project. On the other hand we see that /app/node_modules lies inside container so that means we can easily delete node_modules folder from our root after we create container with docker-compose up.
cd dockerizereact docker-compose up
After few minutes if everything is ok you can test your app. Go to localhost:3000 and you will see simple React App which is running from docker container.
Now we are ready to push everything to our Github. Create new repository on your Github. I will name my dockerizereact.
cd dockerizereact git init git add . git commit -m "first commit of dockerizereact" git remote add origin https://github.com/kristijanklepac/dockerizereact.git git push -u origin master
Our app is pushed to our Github repository (dockerizereact) in master branch. Now it’s time to setup everything in TravisCI. TravisCI will be synchronized with our Github master branch and every time we push something to master branch TravisCI will pull that change and automatically deploy new version of our app to our hosting ( in my case AWS, but you can set up TravisCI to deploy to Microsoft Azure or Digitalocean or many others).
First go to your TravisCI find your dockerizereact repository (TravisCI is synced with Github) and enable checkbox beside settings of your dockerizereact repo. See image bellow.
Now we need to create .travis.yml file inside our root. This file will tell TravisCI what to do with our app. Steps are:
- Tell Travis that we need a copy of docker running
- Build our image using Dockerfile.dev
- Tell Travis how to run our test suite
- Tell Travis how to deploy our code to AWS
sudo: required services: - docker before_install: - docker build -t kristijanklepac/dockerizereact -f Dockerfile.dev . scripts: - docker run kristijanklepac/dockerizereact npm run test -- --coverage
Please be sure to correctly tag your docker build. In my example kristijanklepac is my DockerID you must use yours ( <DockerID>/<Name of Github repo>). Also when you run npm run test add — –coverage. This will ensure that tests are runned once and then exit to console.
Now add everything to Github repo.
git add . git commit -m "added Travis YML file" git push origin master
When you push files to master TravisCi will synchronize files and try to build everything according to .travis.yml file. If build is successful you will see that your repo is green inside Travis.
Next you need to create instance of ElasticBeanstalk service on your AWS. ( configured as single Docker container ). For deployment we need to update our .travis.yml
... deploy: provider: elasticbeanstalk region: "<YOUR_CREATED_REGION_FROM_AWS_ELASTICBEANSTALK>" app: "<YOUR_CREATED_APP_NAME_FROM_AWS_ELASTICBEANSTALK>" env: "<YOUR_CREATED_ENV_NAME_FROM_AWS_ELASTICBEANSTALK>" bucket_name: "<YOUR_CREATED_BUCKET_NAME_FROM_AWS_ELASTICBEANSTALK>" bucket_path: "<YOUR_CREATED_BUCKET_PATH_FROM_AWS_ELASTICBEANSTALK>" on: branch: master
Please update above code with your own values from AWS. After that you need to create IAM user inside AWS and give user programmatic access and AWS Elasticbeanstalk Full policy access. Copy your access key and access secret somewhere because you will need those keys in TravisCI. Click More Options->Settings within yor repo inside TravisCI. Find area like on image bellow:
You need to create two key/value pairs for AWS_SECRET_KEY and AWS_ACCESS_KEY ( values are your copied values from IAM user). We use environment variables to protect it from expose to outside world. In .travis.yml we will use environment keys to set vars.
Next add this to your .travis.yml
... deploy: provider: elasticbeanstalk region: "<YOUR_CREATED_REGION_FROM_AWS_ELASTICBEANSTALK>" app: "<YOUR_CREATED_APP_NAME_FROM_AWS_ELASTICBEANSTALK>" env: "<YOUR_CREATED_ENV_NAME_FROM_AWS_ELASTICBEANSTALK>" bucket_name: "<YOUR_CREATED_BUCKET_NAME_FROM_AWS_ELASTICBEANSTALK>" bucket_path: "<YOUR_CREATED_BUCKET_PATH_FROM_AWS_ELASTICBEANSTALK>" on: branch: master access_key_id: $AWS_ACCESS_KEY secret_access_key: secure: "$AWS_SECRET_KEY"
As you see here we will pull environment vars from Travis and they are not exposed to public. After we commit this to Github master Travis will try to build this and deploy to AWS. When app is deployed (check in AWS Elasticbeanstalk) you can visit Elasticbeanstalk url and see your React App. In our example whenever you push something to master branch after few minutes you will see changes in your production ( check your app url )
When you work in teams you will probably have multiple branches inside your Github repo. For example let’s say you have feature branch and every time you push something you will push it into feature branch and then you will merge master and feature branch if everything is as expected in your app. After merge Travis CI will do the rest.
git checkout -b feature git add . git commit -m "added something to app" git push origin feature
Go to your Github, you will se your feature branch and then try to pull and merge branch. If all goes well you will see that Travis build everything and deploy to AWS…
Thanks for reading…