A containerized modern web server serving a responsive developer portfolio using Nginx (Alpine), orchestrating the container lifecycle with Docker Compose, and integrating a validation pipeline with GitHub Actions.
This project implements Task 4 of the CodeAlpha DevOps Internship. It covers building optimized Docker images, writing custom server configurations, managing persistent logging volumes, checking container health, and validating builds via automated workflows.
- Web Content: HTML5, CSS3 (Outfit & JetBrains Mono typography), Vanilla JavaScript
- Web Server: Nginx (Alpine-based, ultra-lightweight ~23 MB image)
- Containerization: Docker 24+
- Orchestration: Docker Compose v2 (3.8 Schema)
- CI/CD: GitHub Actions (verifies build, runs container, tests server health, performs cleanup)
- Gzip Compression: Enabled for textual and JSON/XML files to heavily optimize network performance.
- Client Cache Control: Aggressive 30-day caching (
expires 30d) for static assets to reduce server load and latency. - SPA Fallback: Redirects
404errors back toindex.html. - Persistent Logging: Redirects server access and error logs to
/var/log/nginx/inside the container (mapped to host volumes via Compose).
- Alpine Base: Reduces security attack surface and drastically speeds up pull/push times.
- Health Check: Runs every 30 seconds using
wgetto verify that Nginx is actively responding. - Metadata Labels: Standardizes build metadata (
maintainer,version,description).
- Resource Limits: Protects the host node by restricting the container to
50% CPUand128Mmemory. - Named Volumes: Persists Nginx access/error log files locally via
nginx_logs.
- Docker Desktop installed and running on your host machine.
Docker Compose abstracts container parameters and automates mounting persistent volume logs.
-
Spin up the stack (rebuilds and runs in background):
docker compose up -d --build
-
Verify Serving: Open your web browser and navigate to 👉 http://localhost:8080
-
View live Nginx logging stream:
docker compose logs -f
-
Shut down the stack and delete persistent log volumes:
docker compose down -v
| Action | Command |
|---|---|
| Build Image | docker build -t nginx-portfolio:1.0 . |
| Run Container | docker run -d --name nginx-portfolio -p 8080:80 nginx-portfolio:1.0 |
| Stop | docker stop nginx-portfolio |
| Status / Health | docker ps -f name=nginx-portfolio |
Every time code is pushed to the main branch or a Pull Request is opened, the .github/workflows/docker-build.yml pipeline triggers:
- Builds the image from the
Dockerfile. - Starts the container mapping port
8080. - Pauses for initialization and runs a connection test via
curl. - Inspects container health status using
docker inspect. - Logs output stream and shuts down the test container cleanly.

