Bitbucket-Pipeline: How to deploy a docker image to Heroku using Springboot
Tags: bitbucketpipeline, docker, devops, continuosdelivery
Published: 2019-12-20 20:13:29

Hey, guys, how’s going!? Nowadays (2019-2020) the IT market has been growing, new technologies appeared, and, as tendencies, the CI - Continuous Integration -  and CD - Continuous Delivery (in some case Continuous Deploy).  

The following text has as a goal to explain how to deploy a docker image on Heroku platform using Bitbucket, using the bitbucket-pipeline. This way, it’ll be done a deploy after a commit be done on Bitbucket. The text has an academic context and as a programming language was choice Java, using Springboot with maven. It’s important to inform that it depends on you getting better and/or change what’s been informed here to help or support you.

Presume it here that for you came here the reader is a Bitbucket user, in this case, know use git, and, you know use Heroku. If you don’t know what is it, it’s recommended you search for both, as about the Bitbucket (https://bitbucket.org/ , https://pt.wikipedia.org/wiki/Bitbucket) as a Heroku  (https://www.heroku.com/ , https://en.wikipedia.org/wiki/Heroku).

let’s go! 

To do this example the Intellij Community was used as IDE and the Ubuntu 18.04 LTS was used as the operational system.

The project tree as like following:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/u9t029vru4i0errz1xd0.png)

Look that exists the “bitbucket-pipeline.yml” file in the root project and this is fundamental to get success. However, this will be talked about and some other points as follows. 

### 1. Heroku ###

At this point, the Heroku configuration will be done. The application will be created, the environment variable will be added and the “API key” will be generated. 

#### 1.1 Creating the application on Heroku ####

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ank2iz5k9pxzn5hvtgh4.png)

#### 1.2 Adding the environment variable ####

The reason to have the environment variable it's because it will be informed which “Profile” will be used to start the application on Heroku.  In this case, for example, it’s possible that you may want to have a test environment, or developer environment, or production environment and because of this, it’ll be passed this information through the environment variable.

To add a environment variable is necessary that you go in the page of project created, in “Settings”, click in “Reveal Config Vars” and following inform the variables, that in this case, it will be informed as key “SPRING_PROFILE” and as value will be informed “heroku”, and after inform, you have to click on “Add” button. 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/bm8nkzyufi9qc3yztpf6.png)

#### 1.3 API Key ####

At this moment you have to save the “API Key”. This key will make possible to do the deploy being out from Heroku platform. For this, you have to go in “Account settings” and following go to the field “API Key”, if the key doesn’t exist you must create it.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/mu6gx2yznwikp0jw8usz.png)

### 2. BitBucket ###

At this step, the Bitbucket Pipeline will be turned on and the environment variable will be added.

#### 2.1 Turn on Pipeline ####

At the Bitbucket platform, the pipeline will be turned on and for such, it’s necessary to go to settings from the project, go to option “Pipeline > Settings” and turned on this option.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1jarirnta43l968rlnur.png)

#### 2.2 Adding the environment variable ####

In the next step, the environment variables will be added into the project and for such, you have to return to the project configuration and to go to “Pipeline > Repository variables”. The environment variables that will be added are “HEROKU_API_KEY”, this one was generated into the “API Key” step from Heroku and it’ll be added “HEROKU_APP_NAME” too, this one which is the application name created on Heroku.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/0ko2d14bw7qy6vag54em.png)

### 3. Application ###

It’s time to configure the application to it could be possible to run the pipeline when a commit on branch master will be done and this way the deploy could be done on Heroku.
It’s important to say that Java with Springboot was chosen as the programming language, and the Intellij Community is used as IDE.

#### 3.1 Application.yml ####

Now it’ll be created the “application.yml” file inside the “resource” folder from the project at the same level that the “application.properties”. Into this file will be informed of the profile name and the port that the application will start. Realize that there are two profiles, one is for development (dev profile) and another one in which the Heroku (heroku profile) will use to start the application. 

    #redis
    #host: if you going to use docker you must change the host to work based on IP,
    # its mean that you musn't use localhost or 127.0.0.1
    #spring.redis.host=10.0.0.21
    spring:
      application:
        name: bbpipeline-heroku-api

    ---
    spring:
      profiles: dev
    server:
      port: 8081
    
    ---
    spring:
      profiles: heroku
    
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/luwwo7ygqqihmzpllj7h.png)

#### 3.2 Bitbucket-pipeline.yml ####

In this point is necessary to create the “bitbucket-pipeline.yml” file into the root project, because this one has the formula that will be read and execute inside the Bitbucket.

    # This is a sample build configuration for Java (Maven).
    # Check our guides at https://confluence.atlassian.com/x/zd-5Mw for more examples.
    # Only use spaces to indent your .yml configuration.
    # -----
    # You can specify a custom docker image from Docker Hub as your build environment.
    image: maven:3.6.1
    
    pipelines:
      branches:
        master:
          - step: #Its working
              name: Create Artifact
              caches:
                - maven
              script: # Modify the commands below to build your repository.
                - mvn -B package # -B batch mode makes Maven less verbose
              artifacts: # defining the artifacts to be passed to each future step.
                - target/**
    
          - step:
              name: Push docker image to the Heroku
              deployment: Production
              services:
                - docker
              script:
                - curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
                - heroku container:login
                - heroku container:push web -a $HEROKU_APP_NAME
                - heroku container:release web -a $HEROKU_APP_NAME

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/y11jibzpaxrh8h9o34gl.png)

Pay attention that there is “branch: master:”, in this case, the pipeline will be executed every single time that a commit will be done on branch master and inside this hierarchy, there are the steps, this steps that will be executed by script after the commit on branch master be done.

* Into step named by “Create Artifact” will be executed the “mvn -B package” command (if there are tests they will be executed) and following it’ll be created for a short time a folder named by “target”, this folder contains the files that will be used on application create on docker container.

* Into step called by “Push docker image to the Heroku” will be used “services’ from docker to create the image and the following will be executed the script. Into script, the first step is to install the “heroku standalone” (command used to install: curl https://cli-assets.heroku.com/install-ubuntu.sh | sh); after to do log in on Heroku system and in this moment it will be using the “API Key” (this one that was put as environment variable) as access key to the Heroku; and as follow the docker image created will be sent and the deploy will be done. 

#### 3.3 Dockerfile ####

At this step will be created the file that will be used to create the docker image. The Dockerfile has to be created into the root project and it doesn’t must to contain an extension, in other words, nothing like “Dockerfile.txt”, “Dockerfile.yml”, “Dockerfile.doc” or “Dockerfile.sh”.

    # https://spring.io/guides/gs/spring-boot-docker/
    #FROM openjdk:11
    FROM adoptopenjdk/openjdk11:latest
    VOLUME /tmp
    
    ARG DEPENDENCY_CLASS=target/dependency
    COPY ${DEPENDENCY_CLASS}/BOOT-INF/lib        /app/lib
    COPY ${DEPENDENCY_CLASS}/META-INF            /app/META-INF
    COPY ${DEPENDENCY_CLASS}/BOOT-INF/classes    /app
    
    CMD ["java","-Dspring.profiles.active=${SPRING_PROFILE}","-cp","app:app/lib/*","com.bbpipeline.BBPipelineApplication"]

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/hieu54qib82ci7tp2hxh.png)

Realize that the “target/dependency” folder is used into Dockerfile, because of this folder that into “bitbucket-pipeline.yml” is created the artifact “target/**” and has the “SPRING_PROFILE” as environment variable too, this variable that was informed as an environment variable on Heroku.

Look that, into the command line used to start the application into docker is used the “CMD”, this one is used because of Heroku can inform the environment variable, because if it was with “ENTRYPOINT” this doesn’t work.

#### 3.4 Application.properties ####

Into the “application.properties” will be added to the line “server.port=${PORT}”, this line allows that when the application starts the Heroku could inform what port the application will run. If the application is with the developer it will be used the profile “dev”, this line will be ignored and the port will be informed by the respective profile describe into “application.yml”.

    spring.profiles.active=dev
    # Server port
    server.port=${PORT}
    
    #logging
    logging.level.org.springframework.data=debug
    logging.level.=error
    
    spring.main.allow-bean-definition-overriding=true

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/hyf17cd8xuw31g9sn4vp.png)

After executing these steps, the application will start on Heroku and it will be possible to check into the log that the application started with the heroku profile.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/7vrq5l3wlxhmlpns789v.png)

It’s could say that the process flow is simple, basically, there is an entrance that is a commit, there is processing that will run inside on Bitbucket and an out that will be the deploy the docker image on Heroku.


![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/c96quca1fn6vug05b0am.png)

The project repository on Bitbucket:
* git clone https://MaironCosta@bitbucket.org/maironpublic/test-bitbucket-pipeline-heroku.git
* git clone git@bitbucket.org:maironpublic/test-bitbucket-pipeline-heroku.git

Thank you for following until the final and I hope that this can help you!