VOOZH about

URL: https://dev.to/guadalupe182/deploying-pos-lite-with-aws-ec2-docker-vercel-and-cloudflare-3bbo

⇱ Deploying POS Lite with AWS EC2, Docker, Vercel and Cloudflare - DEV Community


Introduction

In the previous posts, I shared an overview of POS Lite, explained how I designed the backend with Spring Boot and showed how I built the frontend with React, Next.js and Material UI.

In this fourth post, I want to focus on deployment.

Deploying a full stack application is an important step because it connects everything together: the frontend, the backend, the database, environment variables, domains, SSL and server configuration.

For POS Lite, I used the following deployment setup:

  • Backend deployed on AWS EC2
  • Backend containerized with Docker
  • Frontend deployed on Vercel
  • Domain and DNS managed with Cloudflare
  • Database using PostgreSQL

The goal was to move the project from local development to a production-like environment.

Deployment Goals

Before deploying the project, I wanted to define a few goals.

The deployment needed to be:

  • Simple enough to manage
  • Close to a real production setup
  • Separated between frontend and backend
  • Secure enough to use HTTPS
  • Easy to update as the project evolves
  • Good enough to present as a professional portfolio project

I did not want the project to only work locally on my machine.

I wanted to make it available online and learn what it takes to deploy a real full stack application.

Architecture Overview

The production setup looks like this:

User
 ↓
Cloudflare
 ↓
Vercel Frontend
 ↓
AWS EC2 Backend
 ↓
PostgreSQL Database

The frontend is hosted on Vercel.

The backend runs on an AWS EC2 instance using Docker.

Cloudflare manages the domain, DNS and SSL configuration.

The frontend communicates with the backend through HTTPS requests.

This setup helped me understand how different services work together in a real deployment flow.

Why I Used Vercel for the Frontend

The frontend of POS Lite was built with React and Next.js, so Vercel was a natural option for deployment.

Vercel made it easier to:

  • Connect the project from GitHub
  • Deploy the frontend automatically
  • Configure environment variables
  • Handle frontend builds
  • Serve the application globally

The deployment flow was simple:

  1. Push the frontend project to GitHub
  2. Import the repository into Vercel
  3. Configure environment variables
  4. Deploy the application

The most important frontend environment variable was the backend API URL.

Example:

NEXT_PUBLIC_API_URL=https://api.example.com

This allows the frontend to know where the backend is running.

Why I Used AWS EC2 for the Backend

For the backend, I wanted more control over the server environment.

That is why I decided to deploy the Spring Boot backend on AWS EC2.

Using EC2 helped me practice:

  • Creating a virtual server
  • Connecting through SSH
  • Installing dependencies
  • Running Docker containers
  • Configuring ports
  • Managing backend deployment manually

This was more challenging than deploying the frontend, but it helped me understand the infrastructure side of a full stack application.

Preparing the EC2 Instance

The backend runs on an Ubuntu EC2 instance.

The first step was to create the instance and open the required ports.

Some important ports are:

22 SSH
80 HTTP
443 HTTPS
8080 Backend application

After connecting to the instance through SSH, I installed Docker.

A simplified installation flow looks like this:

sudo apt update
sudo apt install docker.io -y
sudo systemctl enable docker
sudo systemctl start docker

Once Docker was running, the server was ready to run the backend container.

Dockerizing the Spring Boot Backend

To deploy the backend more consistently, I used Docker.

The idea was to package the Spring Boot application into a container so it could run the same way on the server.

A simplified Dockerfile looks like this:

FROM eclipse-temurin:17-jdk-alpine

WORKDIR /app

COPY target/pos-lite.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

This Dockerfile does a few important things:

  • Uses a Java runtime image
  • Creates an application directory
  • Copies the compiled JAR file
  • Exposes the backend port
  • Runs the Spring Boot application

Docker helped make the deployment process more predictable.

Building and Running the Backend Container

After creating the Dockerfile, the backend image can be built with:

docker build -t pos-lite-backend .

Then the container can be started with:

docker run -d \
 --name pos-lite-backend \
 -p 8080:8080 \
 --env-file .env \
 pos-lite-backend

The --env-file option is useful because sensitive configuration should not be hardcoded inside the application.

Environment Variables

Environment variables are very important in deployment.

For the backend, some of the main variables include:

SPRING_DATASOURCE_URL=jdbc:postgresql://host:5432/database
SPRING_DATASOURCE_USERNAME=username
SPRING_DATASOURCE_PASSWORD=password
JWT_SECRET=your-secret-key
SERVER_PORT=8080

Using environment variables keeps the application more flexible and safer.

It also makes it easier to use different configurations for local development and production.

PostgreSQL Database

POS Lite uses PostgreSQL as the database.

The backend connects to PostgreSQL through the datasource configuration.

For a project like this, there are different options:

  • Running PostgreSQL on the same EC2 instance
  • Using a managed database service
  • Using an external PostgreSQL provider

For this project, the important part was learning how the backend connects to a production database and how configuration changes between local and deployed environments.

Database configuration is one of the areas where deployment becomes more real because local assumptions often stop working once the app is online.

Cloudflare for Domain, DNS and SSL

Cloudflare was used to manage the domain, DNS and SSL.

This helped with:

  • Domain management
  • DNS records
  • HTTPS configuration
  • SSL/TLS encryption
  • Better security and performance

A simplified DNS setup can include:

Type Name Target
A api EC2 Public IP
CNAME www Vercel domain

The api subdomain can point to the backend running on EC2.

The frontend can point to the Vercel deployment.

This makes the project feel more professional because users access the app through real domains instead of raw deployment URLs.

Connecting Frontend and Backend

Once the backend was deployed and the domain was configured, the frontend needed to communicate with the backend.

The frontend API URL was configured using an environment variable:

NEXT_PUBLIC_API_URL=https://api.example.com

Then the frontend could call backend routes like:

https://api.example.com/api/products
https://api.example.com/api/sales
https://api.example.com/api/reports

This step was important because it connected the two main parts of the project.

A full stack app is not truly deployed until the frontend and backend can communicate correctly in the live environment.

Common Issues I Faced

Deployment came with several challenges.

Some of the common issues were:

  • Environment variables not configured correctly
  • Backend running locally but not on the server
  • Ports not open in the EC2 security group
  • CORS errors between frontend and backend
  • Wrong API URL in the frontend
  • Docker container stopping after an error
  • Database connection errors
  • HTTP vs HTTPS configuration issues

These problems were frustrating at times, but they helped me understand how deployment works beyond tutorials.

What I Learned

Deploying POS Lite helped me improve in several areas:

  • Working with AWS EC2
  • Running applications with Docker
  • Configuring environment variables
  • Deploying a Next.js frontend with Vercel
  • Managing DNS with Cloudflare
  • Connecting frontend and backend in production
  • Understanding CORS and HTTPS issues
  • Debugging server-side deployment problems

The biggest lesson was that deployment is not just about uploading code.

Deployment involves infrastructure, configuration, networking, security and debugging.

Key Takeaways

Some of my main takeaways were:

  • Docker makes backend deployment more consistent.
  • Environment variables are essential for production.
  • Vercel simplifies frontend deployment.
  • AWS EC2 provides control but requires more configuration.
  • Cloudflare helps with domain, DNS and SSL.
  • Small configuration mistakes can break the entire deployment.
  • A project feels much more real once it is available online.

This deployment setup helped me understand the full lifecycle of a full stack application, from local development to a production-like environment.

What’s Next

In the next and final post of this series, I will share the biggest lessons I learned while building POS Lite.

I will write about technical lessons, mistakes, improvements, project structure and how building a real full stack project helped me grow as a developer.

Thanks for reading.