This is the backend project of the video-sharing-application.
Here is the repository of the frontend.
Our client app need HTTP REST APIs and order services to be able to function. This project basically a backend and handle all background work.
Analyze the main features (requirements) for the application
- Authentication features (users)
- Registration
- Login
- Logout
- Videos related features
- Sharing video and send real-time notification
- View list of videos
Then for this backend project, we do support:
- API endpoints for authentication
- API endpoints for video sharing
- Broadcasting notification of video sharing to other logged-in users
- OS: macOS, Windows and Linux are supported
- Docker
- Npm: v10 is version recommended
No specific tool required for this project. For viewing and managing docker containers, can choose a docker UI client that support the OS. But using terminal should be enough.
Follow these step to have the project work locally
- Clone the repository from github
- Create
.env
file based on the.env.example
. TheDATABASE_URL
is the postgres connection uri that can be generated by prisma:prisma init
or manually prepared. TheGOOGLE_API_KEY
is the key of google project, you can create a new one or get from your exiting project. The instruction can be found hereAPP_ORIGIN
is the url of the client app (frontend project)JWT_TOKEN_SECRET
is needed for authentication (users) flows, make sure you prepared a string for it and keep it secret. - Create
docker.env
file based on thedocker-example.env
file. By using a separate env file for docker compose, we ensure that the docker-compose file will not expose sensitive information. - Make sure no local port that is defined in the docker-compose file is already in used in the local machine.
- Run
npm install
to install dependency, you can run the app directly if docker is too heavy for your local machine. But that's not recommended. - Start/ build the docker containers:
docker compose up
Make sure the postgres DB container is running, then can start migration and seeding.
Run migration for the defined schemas, after running, table videos
and users
should be created: npx prisma migrate dev
The project uses Prisma's seed feature to create the dummy data. Run it directly on the local machine: npx prisma db seed
.
After running this command, you should have 4 videos and 2 users accounts created:
User1: Email: user1@example.com Password: 123123
User2: Email: user2@example.com Password: 123123
Note that the DB_HOST
for local machine and for the docker container is different (Normally is localhost
for local machine).
After having all configuration set up. You can start the application and run it under the hood: docker compose up -d
. There are a lot of useful options for docker compose command. Can explore it in the official doc.
No need to care about the docker-compose.prod.yml
file, this is used for production environment only and will be mentioned in the Docker deployment section.
The project is based on NestJs, which helps the testing quite straightforward. There are 2 types of test are written in this project: Unit testing and End-to-End testing.
All the controller and services have their own test. To run the test: npm run test
.
NestJs also provide end to end test, this kind of test covers the interaction of classes at a more aggregate level -- closer to the kind of end-user's interaction will have with the production system.
To run test: npm run test:e2e
Set up tests with Continuous Integration (CI) is an important step. This is more or less belong to the development process/ management but not purely technical thing. Every opened PR must pass the test before getting merged. This is a standard approach.
Docker help to eliminate the pain when setting a project, no matter it's locally or for deployment. The Dockerfile gives instructions so docker can automatically build the image.
In our case, the backend and the frontend will be both deployed on the AWS EC2 instance. For this backend project, the step to have it deployed is quite simple:
- Create an AWS EC2 instance.
- (Create) assign a security group for that instance, config inbound rules for that security group to allow SSH, HTTP and port
3000
(Custom TCP) - as our default port for backend running is 3000. Can get rid of this but it's no need for now. - SSH to the EC2 instance, now you can control it via terminal.
- Clone the project from github, setup ssh key for the instance if need.
- Install
docker
and other required packages, depends on type of instance. In this project, Ubuntu OS was choosen - Create
.env
anddocker.env
file (For example:nano .env
) and then add sensitive environment variables to it. Make sure we're pointing to the correct frontend origin (APP_ORIGIN
) - Build and start the docker container: we use
docker-compose.prod.yml
file => Run:docker compose -f docker-compose.prod.yml up --build -d
. This step might takes time. - Verify if the service is up: access the URL via browser:
{Public IPv4 address}:3000/ping
, we should seepong
response. This endpoint in the project is for health checking.
Our deployed backend:
http://3.93.48.247:3000/ping (deprecated - server temporarily shutdown)
Our application:
http://3.93.48.247:3001/ (deprecated - server temporarily shutdown)
A full AWS solution but not a only EC2 should be applied for this when it come to the real world. RDS, Load balancer (ELB), Auto Scaling Group, Disaster prevention (multi AZ)...
After login, user can share video and other logged in users can expect to receive a real time the notification about it. This feature might not simple as it is for the scaling scenario.
- Access
http://3.93.48.247:3001/
- Login User1 or User2
- Share a video, for example User1 share:
https://youtu.be/eJ4i-QbXG54?si=fvjVF6SB-JN4Uv_I
. user 2 should receive a notification about a video that shared byuser1@example.com
.
- Can not build and start with docker (
docker compose up
):
- Check if the required ports are free on your local machine
- check the device space, if too many images are existing, then try delete them:
docker container rm 'container_id'
,docker image rm 'image_id'
or even rundocker system prune
- Check network connection (
npm ci
step)