How to Deploy a Containerized App on AWS Using Jenkins
Published: 2023-08-21 17:56:32

In this project we are going to build on the multi-branch pipeline we set up in the previous project( see here https://shorturl.at/cuCJL). So the main focus for this article will be the deployment stage. Our objective is to connect to a remote server (EC2 Server) via from Jenkins using a SSH Agent and execute docker commands to create a container that runs an application.


**Prerequisites:**
- AWS account with EC2 instance.
- Docker Hub account with Docker image.

**Server 1: Jenkins Setup**

1. Launch an EC2 instance for Jenkins (Server 1).
we have already set up a Jenkins server in the previous tutorial. See the link above.

**Server 2: EC2 Instance Setup**

1. Launch another EC2 instance for your application (Server 2) Create a new key pair and store it in a secure and accessible location on your computer. I have chosen _.pem_ format as I am using Linux.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9d0xvhq27oke0n6wx00k.png)

 
2. SSH into the server using the private key and install Docker:

   ```
   sudo yum update
   sudo yum install docker.io
   ```
3. Start Docker service:
   ```
   sudo systemctl start docker
   sudo systemctl enable docker
   ```
4. Add ec2-user to docker group to be able to execute commands:
   ```
   sudo usermod -aG docker $USER
   ```
Log out and log back for it to take effect.

4. Login to docker

**Jenkins Configuration**

1. Install SSH Agent plugin. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3mfc4dwqdww8cmlqxoz.png)


2. Configure SSH agent in Jenkins:

Inside credentials  for multi-branch
   - Go to "Manage Jenkins" > "Manage Credentials" > "Global credentials" > "Add Credentials".

   - Choose "SSH Username with private key".

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wbtxcvld4q0gz9md6719.png)


   - Give it an ID, enter the username (`ec2-user`), paste the private key downloaded earlier (for server 2).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lbirix57u1pszq510q5.png)



3. Add SSH Agent credentials to the Jenkins file:

Jenkins has a cool feature that will generate the syntax needed for any plugin. Inside the Multi-branch pipeline go to 'Pipeline Syntax'

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rc0xkgp6kt67n0vymroe.png)

Choose the 'sshagent: SSH Agent', choose 'ec2-user' and generate.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y2n5t43p27palllyaqvq.png)

Now, lets paste the generated syntax in to our Jenkins file and add our logic.
 

  
   ```
stage("deploy") {
            
            steps {
                script {
                    echo 'Deploying docker image to EC2'
                    def dockerCmd = "docker run -p 8080:8080 -d shersi32/myapp:1"
                sshagent(['ec2-server']) {
                  sh "ssh -o StrictHostKeyChecking=no ec2-user@54.175.82.44 ${dockerCmd}"
                    }
                }
            }
                
   ```
 A few points about out the Jenkins file:
 1. We created a variable for the docker run command to make things easier.
 2. The "-o StrictHostKeyChecking=no" command suppresses pop ups (basically questions that may prevent the commands from executing)
 3. Finally, there is no need for 'docker login' since we have logged in already (see above)

Save the Jenkins file.

**Configure the Firewall on Server 2 (EC2)**
Add an inbound rule for server 2 to allow SSH access from the Jenkins server. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jibi1c6tx52gpbrl1jbk.png)


**Now lets see it in action**

1. Commit your code changes to the Git repository.
2. Trigger the Jenkins pipeline manually 
3. Jenkins will build your Docker image, push it to Docker Hub.
4. Then for the deploy stage, Jenkins will SSH in to the EC2 Server, pull the image from Docker Hub and start the container. 

Here is the stage view of the pipeline:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yu9fe9tgat0my29a7mn.png)


And the logs for the 'deploy' stage:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbkedt5y5gx4t9y6c31m.png)

Now lets check out the EC2 server:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdya2hl4x0eq9zep0ads.png)

And we did it! There is the container up and running!

All that's left now is to access our application using a browser. we just need the the public IP address and the port. 
So, for us it is 54.175.82.44:3080. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmms2x0a81s4bbrq0pa8.png)

And there it is, Brilliant!


So, That's all from me for now. I hope this blog is useful!

_Feel free to contact me with any feedback/questions/suggestions. _