
This portfolio website is a DevOps project deployed on an AWS EC2 instance using Docker, Docker Compose, and Nginx. It supports HTTPS via Let's Encrypt and automates deployments with GitHub Actions CI/CD.
create-react-app and containerized.my-portfolio/
āāā app/ # React app and Dockerfile
ā āāā Dockerfile
ā āāā src/
ā āāā public/
āāā reverse-proxy/ # Nginx + SSL setup
ā āāā nginx.conf
ā āāā init-letsencrypt.sh
āāā docker-compose.yml # Container orchestration[User]
ā HTTPS
[my-portfolio.zapto.org]
ā DNS
[EC2 Ubuntu Instance]
ā Reverse Proxy
[Nginx ā React Container][GitHub Push to main]
ā
[GitHub Actions Workflow]
ā
[Docker Build ā Push Image to Docker Hub]
ā
[SSH into EC2 ā Pull & Restart Container]FROM node:18 as builder
WORKDIR /app
COPY . .
RUN npm ci && PUBLIC_URL=/ npm run build
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/htmlservices:
app:
build: ./app
container_name: react-app
expose:
- "80"
nginx:
image: nginx:latest
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./reverse-proxy/nginx.conf:/etc/nginx/conf.d/default.conf
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- app
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
entrypoint: sh -c
command: >
"certbot certonly --webroot
--webroot-path=/var/lib/letsencrypt
--email [email protected]
--agree-tos
--no-eff-email
-d my-portfolio.zapto.org
--rsa-key-size 4096"
volumes:
certbot-etc:
certbot-var:server {
listen 80;
server_name my-portfolio.zapto.org;
location /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name my-portfolio.zapto.org;
ssl_certificate /etc/letsencrypt/live/my-portfolio.zapto.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-portfolio.zapto.org/privkey.pem;
location / {
proxy_pass http://react-app:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}nginx to respond to challengesPipeline defined in .github/workflows/main.yml (not shown) builds, pushes, and deploys the container automatically.
Live app at: https://my-portfolio.zapto.org