This tutorial provides a step-by-step guide to creating a CI/CD pipeline, building a Docker image, pushing it to GitHub Container Registry (GHCR), provisioning an AWS EC2 instance with Terraform, and running your container on EC2.
- Install Docker Desktop and start it.
- Verify Docker installation by checking its version.
- Prepare your application Docker image by writing a Dockerfile that sets up the working directory, copies your source files, compiles Java files, exposes the required port, and sets the default command to launch your app.
- Build the Docker image locally and verify that it works.
- docker build -t . example devops-demo
- docker run -p : example: 8080:80
- Check code works locally
- javac src/handlers/.java src/.java
- java -cp src Launcher
- Create a GitHub Actions workflow file in your repository.
- Configure the workflow to trigger on push or pull request events for all branches.
- Add steps to checkout the repository code.
- Commit and push the workflow, then verify it runs in the GitHub Actions tab.
- You can pull the image and run locally with command or with docker desktop
- docker pull ghcr.io///devops-demo:latest
- Create a Terraform configuration to define the AWS provider and region.
- Generate an RSA key pair for SSH access to the EC2 instance.
- Save the private key file locally with restricted permissions.
- on ssh-ing I was getting Bad Permissions error and GPT told me to do this and it worked
- icacls id_rsa_tofu.pem /inheritance:r
- icacls id_rsa_tofu.pem /remove "NT AUTHORITY\Authenticated Users"
- icacls id_rsa_tofu.pem /remove "BUILTIN\Users"
- icacls id_rsa_tofu.pem /grant "${env:USERNAME}:F"
- icacls id_rsa_tofu.pem
- Define a security group to allow inbound HTTP and SSH traffic.
- Define an EC2 instance resource that references the key pair and security group, associates a public IP, and sets appropriate tags.
- Add outputs to retrieve the public IP and DNS of the EC2 instance.
- Initialize Terraform, run a plan to verify changes, and then apply the configuration to create the EC2 instance.
- terraform init
- terraform plan
- terraform apply
- Ensure your private key file has restricted permissions suitable for SSH.
- Use the
sshcommand with the key to log in to the EC2 instance as the default user (ec2-user). - Confirm you can access the instance without permission errors.
- ssh -i devops-demo-key.pem ubuntu@ _depends what the instance is running on, could be ec2-user@
- Install Docker on the EC2 instance if it is not already installed.
- Start the Docker service and enable it to start on boot.
- Pull the Docker image from GHCR.
- Run the container detached, mapping the container port to the instance port (e.g., port 80).
- sudo apt update
- sudo apt upgrade -y
- sudo apt install docker.io -y
- sudo systemctl start docker
- sudo systemctl enable docker
- docker pull ghcr.io//:latest
- docker run -d -p 80:80 ghcr.io//:latest In my case the latter two were:
- sudo docker pull ghcr.io/teodordichev/devopsrest/devops-demo:latest
- sudo docker run -d -p 80:80 ghcr.io/teodordichev/devopsrest/devops-demo:latest
- Verify the container is running and accessible locally.
- http:<public-ip>
- Open the EC2 public IP in a browser to verify the app is serving traffic.
- After all other steps are completed, and we have working EC2 instance we can run the playbook
- Run this command in the ansible directory
- ansible-playbook -i inventory.ini deploy.yml It will connect to the instance, install docker and run the container
This guide covers all steps from local development to deploying your containerized app on AWS EC2 with a CI/CD workflow in GitHub Actions. Check instances in the browser here: https://us-east-1.console.aws.amazon.com/