How to deploy to Elastic Beanstalk (Part 2)

- By Abhijit Kini

BACK TO BLOG HOME

In the previous part, we went over the steps of source code deployment to AWS Elastic Beanstalk using a simple Node.js app. We deployed the source code natively at first, then compared with deploying it through Shippable. The latter approach showed actions in the work flow executed automatically for you, by Shippable's unified CI/CD platform.

I'll take a similar approach for this part where we'll go through a deployment of a Docker container of a Node.js app to AWS Elastic Beanstalk. To fully understand this tutorial, complete the previous source code deployment to AWS Elastic Beanstalk first.

We'll first configure a simple Node.js application, manually build and push a Docker image with a tag, and deploy it to AWS Elastic Beanstalk. Next we'll configure Shippable's continuous deployment platform, to automatically execute several actions for you in the background, update and deploy the Docker image on AWS Elastic Beanstalk. The tutorial work flow is shown below:

Deploy to Elastic Beanstalk with Docker, natively

Deploy to Elastic Beanstalk with Docker, using Shippable

 

The specific actions Shippable automatically triggers, to deploy your application to Elastic Beanstalk, after a successful CI build are:

  • Builds the Docker image and tag as configured
  • Pushes the image to Docker Hub using the right credentials
  • Updates your Dockerrun.aws.json file with the IMAGE_NAME & TAG
  • Authenticates into the Elastic Beanstalk console using the right credentials
  • Zips your application files
  • Uploads the artifacts to Amazon S3
  • Updates the application version
  • Issues the Deploy command to update the Elastic Beanstalk from the right directory

In order for Shippable to perform the above actions, you'll need to configure Shippable for a successful deployment to Elastic Beanstalk.

It is important that you complete the Docker deployment of the Elastic Beanstalk natively and then configure Shippable to automate tasks to update your application. This approach will give you a good understanding of the clear delineation of what Shippable does automatically behind the scenes and what occurs outside of that context.

Let's get started.

Prerequisites

You'll need:

  • An AWS account to deploy your application to Elastic Beanstalk
  • A source control account (GitHub or Bitbucket)
    • For this tutorial, I'll use GitHub
  • A Docker Hub account to store your Docker images
  • A Shippable account
    • This can be done by simply logging into Shippable using your source control credentials (GitHub or Bitbucket)

Set up Git Repository

  1. Install the Elastic Beanstalk Command Line interface (EBCLI) on your local machine.
    • Verify that the EBCLI is installed correctly by running the eb --version command. You should see EBCLI 3.2.2 (Python 3.4.3) or higher, as a result.
  2. Fork this simple Node.js application to your GitHub repository as shown below:

    Fork the simple Node JS Docker application
  3. Clone your GitHub repository locally by running the following command:git clone git@github.com:abhijitkini/sample_node_eb_docker.git --branch tutorial --single-branch NodeJSDockerEB
    where github@github.com:abhijitkini/sample_node_eb_docker should be replaced by the fork you created in the previous step.
  4. In your Terminal, cdinto the 'NodeJSDockerEB' directory

Configure Elastic Beanstalk

To deploy your web application from a Docker container to Elastic Beanstalk, you'll need to:

  • Create a Dockerfile in the root of the repository (For this tutorial, it has already been created for you and exists in the root of the forked repository)
  • Create a Dockerrun.aws.json in the root of the repository (You'll need to create this file in the repo. This file is the configuration to deploy a Docker container from an existing Docker image to Elastic Beanstalk.)
    • Add the following to a new file and name the file Dockerrun.aws.json
      {
      "AWSEBDockerrunVersion": "1",
      "Image": {
        "Name": "abhijitkini/sample_node_eb_docker:nativeEBDeployment",
        "Update": "true"
      },
      "Ports": [
        {
          "ContainerPort": "80"
        }
      ],
      "Volumes": [
        ]
      }
      
    • Replace "abhijitkini/sample_node_eb_docker" with your Docker Hub Image name.
  • For more information on  Dockerfile and Dockerrun.aws.json  refer to the Elastic Beanstalk documentation.

Let's configure Elastic Beanstalk:

  1. In your Terminal, from the NodeJSDockerEBdirectory, run eb initcommand.
  2. Input values for the following prompts that show up:
    1. Select a default region:Input the number closest to your region.
    2. Select an application to use:Input the number to create a new application.
    3. Enter Application name:Input NodeJSDockerEB-app
    4. It appears you are using Docker. is this correct?Input y
    5. Select a platform version:Input the number corresponding to the version of Docker you are using. In my case it is 'Docker 1.9.1'
    6. Do you want to set up SSH for your instances?Input n
  3. Create your running environment by typing eb createcommand
  4. Input values for the following prompts that show up:
    1. Enter Environment Name:Hit 'Enter' for the default option (NodeJSDockerEB-app-dev)
    2. Enter DNS CNAME prefix:Hit 'Enter' for the default option
    3. Select a load balancer type:Hit 'Enter' for the default option (classic)
    4. Wait for few minutes until the environment has been created and you are back to the prompt in your Terminal.
    5. You will see the NodeJSDockerEB-app-dev running in the Elastic Beanstalk AWS console.
  5. Create a .ebignorefile at the root of your repository and add the code below to the file. This ensures that Elastic Beanstalk uploads only the Dockerrun.aws.jsonfile and ignores files with .ebextensions.
    *
    !Dockerrun.aws.json
    !.ebextensions/*
    
  6. Ensure the .gitignorefile at the root of the repository has the entries shown below. This ensures everything in .elasticbeanstalk folder will be ignored, except the files ending in cfg.ymland  global.yml
    node_modules
    npm-debug.log
    
    # Elastic Beanstalk Files
    .elasticbeanstalk/*
    !.elasticbeanstalk/*.cfg.yml
    !.elasticbeanstalk/*.global.yml
    

Build Docker Image and push to DockerHub

  1. In your Terminal, from the NodeJSDockerEBdirectory, run the following command to build the Docker image with a tag.
    docker build --rm=true -t abhijitkini/sample_node_eb_docker:nativeEBDeployment .
    • Depending on the size of the image and your internet connection, this step could take a few minutes.
  2. Next, push this image to Docker Hub by running the command:
    docker push abhijitkini/sample_node_eb_docker:nativeEBDeployment
    • Similarly, this step can take a few minutes to complete successfully.
  3. Upon completion, verify if the image and tag have been updated on your Docker Hub.

For more information on building an image and pushing it to DockerHub, refer the Docker tutorials.

Deploy and View the Application

  1. Run theeb deploycommand to deploy the application to Elastic Beanstalk.
    1. This process may take several minutes to complete. Elastic Beanstalk will provide status updates during the process. Once done, you'll see a similar pictures shown below.
    2. Notice the application version and the successful pulling of Docker image and tag specified in the AWS Elastic Beanstalk console.
    3. You can also check the image and tag updated on your Docker Hub.
  Successful deploy to Elastic BeanStalk as shown in TerminalSuccessful deploy to Elastic Beanstalk as shown in AWS Beanstalk console  

 

NOTE: It is important to understand that the above command will provision Elastic Beanstalk resources on AWS and you may incur charges.

From the NodeJSDockerEB directory, run the eb open command to view the application in your browser. You'll see the Shippable Mascot with the message "Congratulations Captain! You have successfully deployed Docker image of this NodeJS test app to Elastic Beanstalk".

Remember, any changes you make to your application, you'll need to go through all these steps to deploy the same successfully on Elastic Beanstalk.

Configure your Shippable environement

  1. Configure Docker and AWS Integrations. Follow these steps:
    1. Access your subscription and go to the 'Settings' tab
    2. On the 'Integrations' tab, click 'Add Integration'
    3. Give a name to your Docker Integration and select 'Docker Hub' from the drop down list of 'Account Integrations'.
    4. Click 'Save'
    5. Click the 'Add Integration' to add the AWS integration
    6. Give a name to your AWS integration and select your AWS integration from the drop down list of 'Account Integrations'.
    7. Click 'Save'
    8. See the gif below for reference.
      Add Docker and AWS integrations on Shippable
  2. Enable the sample_node_eb_docker project in the portal. To do so:
    1. Login to Shippable and access your subscription.
    2. On the 'CI' tab, click 'Enable project".
    3. View the list of projects and look for sample_node_eb_docker
    4. If it does not show up, type sample_node_eb_docker in the search field and click the 'Sync' button.
    5. Click the 'Enable' for sample_node_eb_docker thereby enabling your GitHub respository on Shippable.
    6. This will take you to the sample_node_eb_docker project page. You will see a 'master' and a 'tutorial' branch. We are working off the 'tutorial' branch.
    7. NOTE: If you trigger the build manually at this point, by clicking the 'Build' button, it will fail with the error "failed to find shippable yml file". The reason is because we have not completed the needed configurations.
      Enable a project on Shippable

  3. Configure the shippable.yml file in your local NodeJSDockerEB directory.
    1. For this tutorial, populate the simplified shippable.yml with the syntax given below:
      # Language settings
      language: node_js
      
      build:
        ci:
          - echo 'CI is running'
      
        post_ci:
            # DockerHub
            - docker build -t="abhijitkini/sample_node_eb_docker:$BRANCH.$BUILD_NUMBER" .
            - docker push abhijitkini/sample_node_eb_docker:$BRANCH.$BUILD_NUMBER
            # Addresses botocore version mismatch errors
            - pip install --upgrade botocore
      
      integrations:
        deploy:
          # AWS Integration to deploy Docker image
          - integrationName: "AWS-Abhijit"
            type: aws
            application_name: "NodeJSDockerEB-app"
            env_name: "NodeJSDockerEB-app-dev"
            region: "us-west-2"
            image_name: "abhijitkini/sample_node_eb_docker"
            image_tag: "$BRANCH.$BUILD_NUMBER"
      
        hub:
          - integrationName: "docker-int"
            type: docker
      
    2. Replace the following values, with your own in the above file:
      • abhijitkini/sample_node_eb_docker - Use your own Docker image name
      • integrationName - replace "AWS-Abhijit" with your account Integration in Shippable, set up for AWS (keep the double quotes)
      • region - replace with your region name used when configuring Elastic Beanstalk
      • hub integrationName - replace "docker-int" with your account Integration in Shippable, set up for Docker (keep the double quotes)
  4. Update the Dockerrun.aws.json. This ensures the Docker image name and tag are updated automatically based on the configurations in the shippable.yml file.
    {
    "AWSEBDockerrunVersion": "1",
    "Image": {
      "Name": "<IMAGE_NAME>:<TAG>",
      "Update": "true"
    },
    "Ports": [
      {
        "ContainerPort": "80"
      }
    ],
    "Volumes": [
      ]
    }
    
  5. Push the changes in steps 3 and 4 to your GitHub repository by running the following commands in your Terminal from your local NodeJSDockerEB directory:
    • git add .
    • git commit -m "added shippable yml and modified dockerrun files"
    • git push origin tutorial
    • As mentioned above, we are working on the 'tutorial' branch of the 'master'. This action will trigger continuous integration for Elastic Beanstalk within Shippable and successfully deploy your application to Elastic Beanstalk.
  6. Let us now verify the above step once the build completes successfully in Shippable:
    1. In your local machine Terminal & within the NodeJSDockerEB directory, run the eb status command.
    2. Pay particular attention to Deployed Version field. It is shippable.NodeJSDockerEB-app-dev.tutorial.1
    3. Then, check out the updated image and tag on Docker Hub and you'll see the tutorial.1 image and tag
    4. Next, let's look at the deployed version in the Shippable console logs for this build in the aws_eb_deploy > eb deploysection. It is shippable.NodeJSDockerEB-app-dev.tutorial.1
    5. Lastly, take a look in the AWS Elastic Beanstalk console. It is shippable.NodeJSDockerEB-app-dev.tutorial.1
  7. Bada Bing Bada Boom!
    Successful deploy to Elastic Beanstalk with Docker

We have successfully configured Shippable to automate several actions in the Docker deployment to AWS Elastic Beanstalk.

Shippable automates Elastic Beanstalk deployment

Now that we have configured Shippable to automate tasks in the Docker deployment to Elastic Beanstalk, update the application & watch Shippable's automation deploy the update and make it available to your end users.

  1. In your local NodeJSDockerEB directory, go into the 'views' folder & open 'index.ejs' file.
  2. At the end of the sentence 'You have successfully deployed this NodeJS test app to AWS Elastic Beanstalk', add "using Shippable"
  3. Save the files & push the changes to your GitHub repository 'sample_node_eb_docker'.
  4. The commit action in your GitHub sample_node_eb_docker repository will trigger the following within Shippable:
    1. Triggers a build automatically within the Shippable portal, by syncing with your GitHub repository.
    2. Performs Continuous Integration for Elastic Beanstalk - your code will be automatically built, tested and you will receive a notification with build results in the build console.
    3. Builds the Docker image, tags as configured and pushes the updated Docker image/tag to Docker Hub.
    4. Installs Elastic Beanstalk Command Line Interface (EBCLI) required to update your code on Elastic Beanstalk.
    5. Updates the dockerrun.aws.json file with the IMAGE_NAME and TAG.
    6. Authenticates into the Elastic Beanstalk console using the AWS credentials you have configured.
    7. Zips your application files in your repository.
    8. Uploads the zipped files to Amazon S3 for Elastic Beanstalk to access.
    9. Updates the application version
    10. Issues the Deploy command on Elastic Beanstalk from the right directory.
  5. Once the build on Shippable is successfully complete, let's verify if the end users can see the update we made.
    1. In your Terminal, within the NodeJSDockerEB directory, execute the eb open command.
    2. The web page is updated to show the below picture

 End_user_view_of_updated_application.png


Congratulations!

You have successfully enabled Shippable to automate repetitive developer tasks and update your Node.js application to deploy to Elastic Beanstalk, with Docker, as a frictionless deployment. You've seen the comparison of deploying it natively and using the Shippable platform.

Depending on your automated tests and deployments scenario, you can perform customization by configuring Elastic Beanstalk directly, outside of Shippable. Shippable will continue to automatically trigger deployments into Elastic Beanstalk upon a successful Shippable CI build and help you ship code faster.

If you have questions or feedback on this topic, reach out to us through our support channel.

Additional resources on this topic:

Next, let's look at Shippable Pipelines using AWS Elastic Beanstalk for a continuous deployment, the part 3 of this CI/CD pipelines for EBS series. Stay tuned.

 Try Shippable

Topics: Docker, nodejs, tutorial, Elastic Beanstalk, AWS