ci: Add docker images build

This commit is contained in:
deytenit committed 2026-01-13 22:57:26 +03:00
1 parent 2d5b157a21
commit 0a31031965
12 files changed
+1539

No files matched your search

+394
View File
@@ -0,0 +1,394 @@
# Container Deployment Guide
This guide covers the containerized deployment setup for the www.ermnvldmr.com website, including both the main Astro site and the Storybook component library.
## Overview
The project uses Docker containers to package and deploy:
- **Main Site**: Astro static website served via nginx
- **Storybook**: Component library served via nginx
- **Registry**: GitHub Container Registry (ghcr.io)
- **CI/CD**: GitHub Actions with semantic versioning
## Container Architecture
### Multi-stage Build Strategy
Both containers follow a multi-stage build pattern:
1. **Builder Stage**: Node.js 20 Alpine with pnpm for building assets
2. **Production Stage**: nginx:1.25-alpine for serving static content
### Security Features
- **Non-root user**: Containers run as `nginx-user` (UID 1001)
- **Non-privileged ports**: Expose port 8080 instead of 80
- **Security headers**: CSP, HSTS, and other security headers configured
- **Signal handling**: dumb-init for proper signal handling
### Images
- **Main Site**: `ghcr.io/deytenit/www.ermnvldmr.com`
- **Storybook**: `ghcr.io/deytenit/www.ermnvldmr.com/storybook`
## Tagging Strategy
### Release Tags (from `release/semantic-dispatch`)
For both images:
- `vX.X.X` - Full version (e.g., `v1.2.3`)
- `vX.X` - Minor version (e.g., `v1.2`)
- `vX` - Major version (e.g., `v1`)
- `latest` - Latest stable release
- `{sha}` - Commit SHA for traceability
### Pre-release Tags (from `next/semantic-dispatch`)
For both images:
- `vX.X.X-next.X` - Full prerelease version (e.g., `v1.2.3-next.1`)
- `vX.X.X-next` - Latest prerelease for that version
- `vX.X-next` - Latest prerelease for minor version
- `vX-next` - Latest prerelease for major version
- `latest-next` - Latest prerelease overall
- `{sha}` - Commit SHA for traceability
## Local Development
### Using Docker Compose
Start both services locally:
```bash
# Start both containers
docker-compose up
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
```
Access points:
- **Main Site**: http://localhost:3000
- **Storybook**: http://localhost:6006
### Building Individual Images
```bash
# Build Astro site
docker build -f docker/astro/Dockerfile -t www-astro .
# Build Storybook
docker build -f docker/storybook/Dockerfile -t www-storybook .
# Run containers
docker run -p 3000:8080 www-astro
docker run -p 6006:8080 www-storybook
```
## Production Deployment
### Manual Container Deployment
Pull and run the latest images:
```bash
# Pull latest stable images
docker pull ghcr.io/deytenit/www.ermnvldmr.com:latest
docker pull ghcr.io/deytenit/www.ermnvldmr.com/storybook:latest
# Run main site
docker run -d \
--name www-ermnvldmr-astro \
-p 3000:8080 \
--restart unless-stopped \
ghcr.io/deytenit/www.ermnvldmr.com:latest
# Run storybook
docker run -d \
--name www-ermnvldmr-storybook \
-p 6006:8080 \
--restart unless-stopped \
ghcr.io/deytenit/www.ermnvldmr.com/storybook:latest
```
### Environment Variables
The containers are designed to be stateless and don't require runtime environment variables. Configuration is baked into the build.
### Health Checks
Both containers include health check endpoints:
```bash
# Check container health
curl http://localhost:3000/health # Astro site
curl http://localhost:6006/health # Storybook
```
### Resource Requirements
**Recommended minimums per container:**
- **CPU**: 0.1 cores
- **Memory**: 64MB
- **Storage**: 100MB
**Production recommendations:**
- **CPU**: 0.25 cores
- **Memory**: 128MB
- **Storage**: 500MB (for logs and cache)
## Reverse Proxy Configuration
### nginx Configuration Example
```nginx
server {
listen 80;
server_name www.ermnvldmr.com;
location / {
proxy_pass http://astro-container:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name storybook.ermnvldmr.com;
location / {
proxy_pass http://storybook-container:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### Traefik Configuration Example
```yaml
# docker-compose.yml with Traefik
version: '3.8'
services:
astro:
image: ghcr.io/deytenit/www.ermnvldmr.com:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.astro.rule=Host(`www.ermnvldmr.com`)"
- "traefik.http.services.astro.loadbalancer.server.port=8080"
storybook:
image: ghcr.io/deytenit/www.ermnvldmr.com/storybook:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.storybook.rule=Host(`storybook.ermnvldmr.com`)"
- "traefik.http.services.storybook.loadbalancer.server.port=8080"
```
## Troubleshooting
### Common Issues
#### Container Won't Start
```bash
# Check logs
docker logs container-name
# Common causes:
# - Missing dependencies in build
# - Permission issues
# - Port conflicts
```
#### Build Failures
```bash
# Check build logs
docker build -f docker/astro/Dockerfile -t test .
# Common causes:
# - Node version mismatch
# - pnpm cache issues
# - Missing build dependencies
```
#### Permission Denied
```bash
# Check if running as correct user
docker exec container-name whoami
# Should output: nginx-user
```
### Debugging
Enable debug mode in nginx:
```bash
# Create debug container
docker run -it --entrypoint=/bin/sh ghcr.io/deytenit/www.ermnvldmr.com:latest
# Check nginx config
nginx -t
# Check file permissions
ls -la /usr/share/nginx/html/
```
### Performance Tuning
#### nginx Optimization
For high-traffic deployments, consider:
- Adjusting worker processes
- Enabling gzip compression levels
- Tuning keepalive settings
- Adding rate limiting
#### Container Resources
Monitor and adjust:
```bash
# Check resource usage
docker stats
# Update container limits
docker run --memory=256m --cpus=0.5 ...
```
## Security Considerations
### Container Security
- Containers run as non-root user
- Minimal attack surface with Alpine base
- Regular security updates via base image updates
- No sensitive data in containers
### Network Security
- Expose only necessary ports
- Use internal networks for service communication
- Implement proper firewall rules
- Enable HTTPS with reverse proxy
### Registry Security
- Images are signed and scanned
- Access controlled via GitHub permissions
- Automatic vulnerability scanning
- Regular base image updates
## Monitoring
### Health Monitoring
```bash
# Simple health check script
#!/bin/bash
if curl -f http://localhost:3000/health >/dev/null 2>&1; then
echo "Astro site: healthy"
else
echo "Astro site: unhealthy"
exit 1
fi
```
### Log Management
```bash
# View logs
docker-compose logs -f astro
docker-compose logs -f storybook
# Log rotation (configure docker daemon)
# /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
```
### Metrics Collection
Consider integrating with:
- Prometheus + Grafana
- nginx prometheus exporter
- Container metrics exporters
- Application performance monitoring
## CI/CD Integration
The containers are automatically built and pushed when:
1. **Pre-release**: Merge to `next` branch triggers prerelease
2. **Release**: Manual workflow dispatch creates stable release
### Workflow Outputs
Each workflow provides:
- `new_release_published`: Boolean indicating if release was created
- `new_release_version`: The version number of the release
### Manual Triggers
```bash
# Trigger release workflow via GitHub CLI
gh workflow run "release/semantic-dispatch" --ref main
# Trigger prerelease via merge to next branch
git checkout next
git merge feature-branch
git push origin next
```
## Maintenance
### Regular Updates
1. **Base Image Updates**: Rebuild monthly for security patches
2. **Dependency Updates**: Follow project dependency update schedule
3. **Configuration Review**: Quarterly review of nginx and security settings
### Backup Strategy
Since containers are stateless:
- Source code is backed up in Git repository
- Container images are versioned in registry
- No persistent data to backup
### Rollback Procedure
```bash
# Rollback to previous version
docker pull ghcr.io/deytenit/www.ermnvldmr.com:v1.2.2
docker stop current-container
docker run -d --name new-container ghcr.io/deytenit/www.ermnvldmr.com:v1.2.2
# Or use docker-compose with specific version
docker-compose down
# Edit docker-compose.yml to specify version
docker-compose up -d
```
---
For additional support or questions, refer to the project repository issues or documentation.
+303
View File
@@ -0,0 +1,303 @@
# Container Development Guide
This guide covers development workflow with the containerized setup.
## Quick Start
### Prerequisites
- Docker and Docker Compose installed
- pnpm v9.12.3+
- Node.js v20+
### Local Development
1. **Clone and setup**:
```bash
git clone https://github.com/deytenit/www.ermnvldmr.com.git
cd www.ermnvldmr.com
pnpm install
```
2. **Start development servers** (non-containerized):
```bash
pnpm dev # Astro dev server on :4321
pnpm storybook # Storybook dev server on :6006
```
3. **Test containerized build**:
```bash
docker-compose up --build
```
### Container Development Workflow
#### Building Images Locally
```bash
# Build both images
docker-compose build
# Build specific image
docker-compose build astro
docker-compose build storybook
# Build with no cache
docker-compose build --no-cache
```
#### Testing Container Changes
```bash
# Start containers
docker-compose up -d
# Check logs
docker-compose logs -f astro
docker-compose logs -f storybook
# Test health endpoints
curl http://localhost:3000/health
curl http://localhost:6006/health
# Stop containers
docker-compose down
```
### Debugging Containers
#### Interactive Shell Access
```bash
# Access running container
docker-compose exec astro sh
docker-compose exec storybook sh
# Or start debug container
docker run -it --entrypoint=/bin/sh $(docker-compose config | grep image: | head -1 | cut -d: -f2-)
```
#### Common Debug Commands
```bash
# Inside container:
whoami # Check user
nginx -t # Test nginx config
ls -la /usr/share/nginx/html/ # Check files
ps aux # Check processes
netstat -tlnp # Check ports
```
## Docker Configuration
### File Structure
```
docker/
├── astro/
│ └── Dockerfile # Astro site container
├── storybook/
│ └── Dockerfile # Storybook container
└── nginx/
├── nginx.conf # Main nginx config
├── astro.conf # Astro site config
└── storybook.conf # Storybook config
```
### Build Context
The `.dockerignore` file optimizes build context:
- Excludes `node_modules/`, `dist/`, build artifacts
- Includes source files, package files, configs
- Reduces build time and image size
### Multi-stage Build Benefits
1. **Smaller Images**: Only runtime dependencies in final image
2. **Security**: No build tools in production image
3. **Caching**: Efficient layer caching for faster builds
4. **Consistency**: Same build environment across all environments
## nginx Configuration
### Security Features
- Non-root user execution
- Security headers (HSTS, CSP, etc.)
- Rate limiting capabilities
- Access controls for sensitive paths
### Performance Optimizations
- Gzip compression for assets
- Caching headers for static files
- Connection keep-alive
- Efficient static file serving
### Configuration Customization
Edit files in `docker/nginx/`:
- `nginx.conf`: Global nginx settings
- `astro.conf`: Astro-specific server block
- `storybook.conf`: Storybook-specific server block
## CI/CD Integration
### GitHub Actions Workflow
The workflows are triggered by semantic versioning:
1. **Development**: Push to feature branches
2. **Pre-release**: Merge to `next` branch
3. **Release**: Manual dispatch or release branch
### Build Process
1. Install dependencies with pnpm
2. Build Astro static site
3. Build Storybook static site
4. Create semantic release
5. Build and push Docker images (if release created)
### Image Tagging
Images follow semantic versioning:
- Release: `latest`, `v1.2.3`, `v1.2`, `v1`
- Pre-release: `latest-next`, `v1.2.3-next.1`, etc.
## Testing
### Container Testing
```bash
# Test image builds
docker build -f docker/astro/Dockerfile -t test-astro .
docker build -f docker/storybook/Dockerfile -t test-storybook .
# Test containers run
docker run -p 3000:8080 test-astro &
docker run -p 6006:8080 test-storybook &
# Test endpoints
curl -f http://localhost:3000/
curl -f http://localhost:6006/
curl -f http://localhost:3000/health
curl -f http://localhost:6006/health
# Cleanup
docker stop $(docker ps -q)
```
### Security Testing
```bash
# Scan images for vulnerabilities
docker scout cves test-astro
docker scout cves test-storybook
# Check for non-root execution
docker run --rm test-astro whoami # Should output: nginx-user
# Test file permissions
docker run --rm test-astro ls -la /usr/share/nginx/html/
```
## Performance Optimization
### Image Size Optimization
Current optimizations:
- Multi-stage builds
- Alpine Linux base images
- Minimal runtime dependencies
- Optimized layer ordering
### Build Performance
- Layer caching in GitHub Actions
- Efficient `.dockerignore`
- Parallel builds for multiple platforms
- Registry cache utilization
### Runtime Performance
- nginx optimizations for static content
- Gzip compression
- Proper caching headers
- Health check optimizations
## Troubleshooting
### Common Build Issues
1. **pnpm version mismatch**:
```bash
# Update Dockerfile pnpm version
RUN corepack prepare pnpm@9.12.3 --activate
```
2. **Permission issues**:
```bash
# Check user creation in Dockerfile
RUN adduser -S -D -H -u 1001 nginx-user
```
3. **Missing dependencies**:
```bash
# Ensure all deps in package.json
pnpm install --frozen-lockfile
```
### Common Runtime Issues
1. **Container won't start**:
```bash
docker logs container-name
# Check nginx config: nginx -t
```
2. **404 errors**:
```bash
# Check file permissions and paths
docker exec container ls -la /usr/share/nginx/html/
```
3. **Health check failures**:
```bash
# Test health endpoint manually
curl -v http://localhost:8080/health
```
### Performance Issues
```bash
# Monitor resource usage
docker stats
# Check nginx access logs
docker exec container tail -f /var/log/nginx/access.log
# Profile application
docker exec container top
```
## Contributing
### Making Changes to Containers
1. Modify Docker configurations
2. Test locally with `docker-compose up --build`
3. Validate with security and performance tests
4. Update documentation
5. Create pull request
### Release Process
1. Changes merged to `next` create pre-releases
2. Manual workflow dispatch creates stable releases
3. Both trigger automated container builds
4. Images are automatically tagged and pushed
---
For more detailed deployment information, see [container-deployment.md](./container-deployment.md).