feat: add Docker support with multi-stage build and CI/CD workflow
- Introduced Dockerfile for multi-stage application build and deployment using Nginx. - Added .dockerignore to exclude unnecessary files from the Docker context. - Created nginx.conf for server configuration, including Gzip compression and SPA routing. - Implemented Gitea CI/CD workflow for building and pushing Docker images on version tags.
This commit is contained in:
		
							
								
								
									
										62
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| # 依赖 | ||||
| node_modules | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
| pnpm-debug.log* | ||||
|  | ||||
| # 构建产物 | ||||
| dist | ||||
| dist-ssr | ||||
| *.local | ||||
|  | ||||
| # 编辑器 | ||||
| .vscode | ||||
| .idea | ||||
| *.swp | ||||
| *.swo | ||||
| *~ | ||||
|  | ||||
| # 操作系统 | ||||
| .DS_Store | ||||
| Thumbs.db | ||||
|  | ||||
| # Git | ||||
| .git | ||||
| .gitignore | ||||
| .gitattributes | ||||
|  | ||||
| # CI/CD | ||||
| .gitea | ||||
| .github | ||||
| .gitlab-ci.yml | ||||
|  | ||||
| # Docker | ||||
| Dockerfile | ||||
| .dockerignore | ||||
| docker-compose.yaml | ||||
| docker-compose.*.yaml | ||||
| compose*yaml | ||||
|  | ||||
| # 测试 | ||||
| coverage | ||||
| .nyc_output | ||||
|  | ||||
| # 环境变量 | ||||
| .env | ||||
| .env.local | ||||
| .env.*.local | ||||
|  | ||||
| # 日志 | ||||
| logs | ||||
| *.log | ||||
|  | ||||
| # 临时文件 | ||||
| tmp | ||||
| temp | ||||
|  | ||||
| # 文档 | ||||
| README.md | ||||
| LICENSE | ||||
| *.md | ||||
|  | ||||
							
								
								
									
										48
									
								
								.gitea/workflows/build.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.gitea/workflows/build.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| name: Build and Push Docker Image | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     tags: | ||||
|       - 'v*' | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|      | ||||
|     steps: | ||||
|       - name: 检出代码 | ||||
|         uses: actions/checkout@v4 | ||||
|          | ||||
|       - name: 设置 Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|          | ||||
|       - name: 登录到 Gitea Container Registry | ||||
|         uses: docker/login-action@v3 | ||||
|         with: | ||||
|           registry: ${{ env.GITEA_INSTANCE_URL }} | ||||
|           username: ${{ env.GITEA_ACTOR }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|        | ||||
|       - name: 提取 Docker 元数据 | ||||
|         id: meta | ||||
|         uses: docker/metadata-action@v5 | ||||
|         with: | ||||
|           images: | | ||||
|             ${{ env.GITEA_INSTANCE_URL }}/${{ env.GITEA_REPOSITORY_OWNER }}/litek | ||||
|           tags: | | ||||
|             type=semver,pattern={{version}} | ||||
|             type=semver,pattern={{major}}.{{minor}} | ||||
|             type=semver,pattern={{major}} | ||||
|             type=raw,value=latest | ||||
|        | ||||
|       - name: 构建并推送 Docker 镜像 | ||||
|         uses: docker/build-push-action@v5 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: ${{ steps.meta.outputs.tags }} | ||||
|           labels: ${{ steps.meta.outputs.labels }} | ||||
|           cache-from: type=gha | ||||
|           cache-to: type=gha,mode=max | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|  | ||||
							
								
								
									
										36
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| # 第一阶段: 构建应用 | ||||
| FROM node:22-alpine AS builder | ||||
|  | ||||
| # 安装 pnpm | ||||
| RUN corepack enable && corepack prepare pnpm@latest --activate | ||||
|  | ||||
| # 设置工作目录 | ||||
| WORKDIR /app | ||||
|  | ||||
| # 复制依赖配置文件 | ||||
| COPY package.json pnpm-lock.yaml ./ | ||||
|  | ||||
| # 安装依赖 | ||||
| RUN pnpm install --frozen-lockfile | ||||
|  | ||||
| # 复制源代码 | ||||
| COPY . . | ||||
|  | ||||
| # 构建应用 | ||||
| RUN pnpm build | ||||
|  | ||||
| # 第二阶段: 运行应用 | ||||
| FROM nginx:alpine | ||||
|  | ||||
| # 复制自定义 nginx 配置 | ||||
| COPY nginx.conf /etc/nginx/nginx.conf | ||||
|  | ||||
| # 从构建阶段复制构建产物 | ||||
| COPY --from=builder /app/dist /usr/share/nginx/html | ||||
|  | ||||
| # 暴露端口 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # 启动 nginx | ||||
| CMD ["nginx", "-g", "daemon off;"] | ||||
|  | ||||
							
								
								
									
										73
									
								
								nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| user nginx; | ||||
| worker_processes auto; | ||||
| error_log /var/log/nginx/error.log warn; | ||||
| pid /var/run/nginx.pid; | ||||
|  | ||||
| events { | ||||
|     worker_connections 1024; | ||||
| } | ||||
|  | ||||
| http { | ||||
|     include /etc/nginx/mime.types; | ||||
|     default_type application/octet-stream; | ||||
|  | ||||
|     log_format main '$remote_addr - $remote_user [$time_local] "$request" ' | ||||
|                     '$status $body_bytes_sent "$http_referer" ' | ||||
|                     '"$http_user_agent" "$http_x_forwarded_for"'; | ||||
|  | ||||
|     access_log /var/log/nginx/access.log main; | ||||
|  | ||||
|     sendfile on; | ||||
|     tcp_nopush on; | ||||
|     tcp_nodelay on; | ||||
|     keepalive_timeout 65; | ||||
|     types_hash_max_size 2048; | ||||
|  | ||||
|     # Gzip 压缩配置 | ||||
|     gzip on; | ||||
|     gzip_vary on; | ||||
|     gzip_proxied any; | ||||
|     gzip_comp_level 6; | ||||
|     gzip_types text/plain text/css text/xml text/javascript  | ||||
|                application/json application/javascript application/xml+rss  | ||||
|                application/rss+xml font/truetype font/opentype  | ||||
|                application/vnd.ms-fontobject image/svg+xml; | ||||
|  | ||||
|     server { | ||||
|         listen 80; | ||||
|         server_name localhost; | ||||
|         root /usr/share/nginx/html; | ||||
|         index index.html; | ||||
|  | ||||
|         # 安全头 | ||||
|         add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|         add_header X-Content-Type-Options "nosniff" always; | ||||
|         add_header X-XSS-Protection "1; mode=block" always; | ||||
|  | ||||
|         # 静态资源缓存 | ||||
|         location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|         } | ||||
|  | ||||
|         # SPA 路由支持 - 所有请求都返回 index.html | ||||
|         location / { | ||||
|             try_files $uri $uri/ /index.html; | ||||
|         } | ||||
|  | ||||
|         # 健康检查端点 | ||||
|         location /health { | ||||
|             access_log off; | ||||
|             return 200 "healthy\n"; | ||||
|             add_header Content-Type text/plain; | ||||
|         } | ||||
|  | ||||
|         # 错误页面 | ||||
|         error_page 404 /index.html; | ||||
|         error_page 500 502 503 504 /50x.html; | ||||
|         location = /50x.html { | ||||
|             root /usr/share/nginx/html; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 typist
					typist