{"id":50460210,"url":"https://github.com/meetgaurang/todo","last_synced_at":"2026-06-01T04:04:33.649Z","repository":{"id":358455196,"uuid":"1221465425","full_name":"meetgaurang/todo","owner":"meetgaurang","description":"The Dockerised full stack app being deployed on AWS with Terraform.","archived":false,"fork":false,"pushed_at":"2026-05-17T12:39:28.000Z","size":53,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-17T14:40:00.698Z","etag":null,"topics":["aws-ec2","docker","dockerhub-image","expressjs","nginx","reactjs","sqlite-database","terraform"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meetgaurang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-26T08:43:25.000Z","updated_at":"2026-05-17T12:57:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/meetgaurang/todo","commit_stats":null,"previous_names":["meetgaurang/todo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/meetgaurang/todo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meetgaurang%2Ftodo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meetgaurang%2Ftodo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meetgaurang%2Ftodo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meetgaurang%2Ftodo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meetgaurang","download_url":"https://codeload.github.com/meetgaurang/todo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meetgaurang%2Ftodo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33759209,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-ec2","docker","dockerhub-image","expressjs","nginx","reactjs","sqlite-database","terraform"],"created_at":"2026-06-01T04:04:32.914Z","updated_at":"2026-06-01T04:04:33.644Z","avatar_url":"https://github.com/meetgaurang.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Todo App — Dockerised Full Stack App on AWS with Terraform\n\nA full stack todo application built to showcase how to containerise and deploy a multi-service app to AWS EC2 using Terraform and Docker Hub.\n\n## Stack\n\n| Layer | Technology |\n|---|---|\n| Frontend | React (Vite), served by Nginx |\n| Backend | Node.js, Express |\n| Database | SQLite (persisted via Docker volume) |\n| Containerisation | Docker, Docker Compose |\n| Image Registry | Docker Hub |\n| Infrastructure | AWS EC2, provisioned with Terraform |\n\n## Architecture\n\n```\nBrowser → EC2 :8080 → Nginx (frontend container)\n                           ↓ /api/*\n                       Express (backend container)\n                           ↓\n                       SQLite (Docker volume)\n```\n\nNginx serves the React app and proxies all `/api/*` requests to the backend container. The two containers communicate over Docker's internal network — only port 8080 is exposed publicly.\n\n## Project Structure\n\n```\n.\n├── backend/              # Express API + SQLite\n├── frontend/             # React app + Nginx config\n├── infra/                # Terraform configs\n│   ├── main.tf           # EC2 instance, security group, deploy provisioner\n│   ├── variables.tf      # Input variables\n│   ├── outputs.tf        # App URL and SSH command\n│   ├── user_data.sh      # Bootstraps Docker + Compose on first boot\n│   └── docker-compose.prod.tpl  # Production compose template (pull-only)\n├── build-push.sh         # Builds images for linux/amd64 and pushes to Docker Hub\n└── docker-compose.yml    # Local development compose file\n```\n\n## Prerequisites\n\n- [Docker Desktop](https://www.docker.com/products/docker-desktop/)\n- [Terraform](https://developer.hashicorp.com/terraform/install) (`brew install hashicorp/tap/terraform`)\n- [AWS CLI](https://aws.amazon.com/cli/) configured with credentials (`aws configure`)\n- A Docker Hub account\n- An AWS key pair (`.pem` file)\n\n## Deployment\n\n### 1. Configure AWS credentials\n\n```bash\naws configure\n```\n\n### 2. Build and push images to Docker Hub\n\n```bash\nexport DOCKERHUB_USERNAME=your_dockerhub_username\nchmod +x build-push.sh\n./build-push.sh\n```\n\nThis builds the frontend and backend images for `linux/amd64` (required for EC2) and pushes them to Docker Hub.\n\n### 3. Provision infrastructure and deploy\n\n```bash\ncd infra\nterraform init\nterraform apply \\\n  -var=\"private_key_path=~/path/to/keypair.pem\" \\\n  -var=\"dockerhub_username=your_dockerhub_username\"\n```\n\nTerraform will:\n1. Create a security group (ports 22 and 8080)\n2. Launch an Amazon Linux 2023 EC2 instance (`t2.micro`)\n3. Bootstrap Docker and Docker Compose via `user_data.sh`\n4. Copy the production compose file to the instance\n5. Pull images from Docker Hub and start the containers\n\nAfter `apply` completes, the app URL is printed:\n```\napp_url = \"http://ec2-xx-xx-xx-xx.compute-1.amazonaws.com:8080\"\n```\n\n### 4. Tear down\n\n```bash\nterraform destroy \\\n  -var=\"private_key_path=~/path/to/keypair.pem\" \\\n  -var=\"dockerhub_username=your_dockerhub_username\"\n```\n\n## Re-deploying After Code Changes\n\n```bash\n# 1. Push updated images\n./build-push.sh\n\n# 2. SSH into the instance and pull + restart\nssh -i ~/path/to/keypair.pem ec2-user@\u003cpublic-dns\u003e\ncd ~/todo\nsudo docker compose pull\nsudo docker compose up -d\n```\n\n## Local Development\n\n### Prerequisites\n\n- [Docker Desktop](https://www.docker.com/products/docker-desktop/) running\n\n### Run the app\n\n```bash\ndocker compose up --build\n```\n\nThis builds both images locally and starts the containers. The app is available at `http://localhost:8080`.\n\n### What runs locally\n\n| Container | Role | Port |\n|---|---|---|\n| frontend | Nginx serving the React build, proxies `/api/*` | 8080 (host) |\n| backend | Express API with SQLite | internal only |\n\nSQLite data is stored in a Docker volume (`sqlite-data`) so it persists across restarts.\n\n### Stop the app\n\n```bash\ndocker compose down\n```\n\nTo also delete the database volume:\n```bash\ndocker compose down -v\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeetgaurang%2Ftodo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeetgaurang%2Ftodo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeetgaurang%2Ftodo/lists"}