1. 为什么选择Docker部署Vue项目?
在当今的前端开发领域,Docker已经成为现代化部署的标准工具之一。我最初接触Docker部署Vue项目是在2018年,当时团队面临开发环境与生产环境不一致导致的"在我机器上能跑"的经典问题。经过多次尝试,我们发现Docker能完美解决这个痛点。
Docker的核心优势在于它提供了标准化的运行环境。想象一下,你开发时用的是Node 14,但服务器上是Node 12;或者本地npm install顺利通过,但CI环境却报错。这些问题在Docker容器面前都不复存在,因为容器内外的环境完全隔离且可精确控制。
对于Vue项目而言,Docker化部署还有几个特别的价值:
- 构建产物的一致性:避免了因构建机器不同导致的chunk hash变化
- 依赖隔离:不同项目可以使用不同版本的node-sass等容易冲突的依赖
- 快速回滚:通过镜像版本可以秒级回退到任意历史版本
- 资源利用:相比虚拟机,容器更轻量,特别适合前端这种无状态应用
提示:即使你是个人开发者,使用Docker部署也能避免"项目半年后跑不起来"的尴尬,因为所有环境依赖都被固化在Dockerfile中。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工具选型
2.1 Docker环境搭建
在开始之前,我们需要确保本机已安装Docker。根据我的经验,不同操作系统下的安装注意事项有所不同:
Windows用户:
- 确保系统版本为Windows 10专业版/企业版/教育版(家庭版需升级)
- 在BIOS中开启虚拟化支持(VT-x)
- 推荐使用WSL2作为后端(性能更好)
- 安装Docker Desktop时勾选"Use WSL 2 based engine"
Mac用户:
- 2010年后的Intel芯片Mac直接安装Docker Desktop
- M1/M2芯片需下载Apple Silicon版本
- 建议分配至少4GB内存给Docker(在Preferences → Resources中设置)
Linux用户(以Ubuntu为例):
bash复制# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
# 添加Docker官方GPG密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 设置仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 验证安装
sudo docker run hello-world
2.2 Vue项目结构检查
一个标准的Vue项目在Docker化前需要确认以下结构:
code复制my-vue-project/
├── public/ # 静态资源
├── src/ # 源代码
├── package.json # 项目依赖
├── vue.config.js # Vue CLI配置
└── babel.config.js # Babel配置
关键检查点:
- 确保package.json中包含build脚本
- 检查vue.config.js中publicPath配置(建议设为'/'或'./')
- 确认没有硬编码的绝对路径(特别是API地址)
3. 编写Dockerfile:从基础到优化
3.1 基础版Dockerfile
我们先从最简单的Dockerfile开始:
dockerfile复制# 使用官方Node镜像作为构建环境
FROM node:16-alpine as builder
# 设置工作目录
WORKDIR /app
# 复制依赖定义文件
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制源代码
COPY . .
# 构建生产环境代码
RUN npm run build
# 使用Nginx作为生产服务器
FROM nginx:alpine
# 复制构建产物到Nginx目录
COPY --from=builder /app/dist /usr/share/nginx/html
# 暴露80端口
EXPOSE 80
# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]
这个基础版本已经能工作,但存在几个问题:
- 每次代码变更都会导致所有层重建
- 没有利用Docker的缓存机制
- 缺少必要的健康检查
- Nginx配置是默认的,不够优化
3.2 优化版Dockerfile
改进后的版本:
dockerfile复制# 第一阶段:构建
FROM node:16-alpine as builder
WORKDIR /app
# 先单独复制package文件以利用缓存
COPY package.json package-lock.json ./
# 安装依赖(使用ci命令保持一致性)
RUN npm ci --production
# 复制其余文件
COPY . .
# 构建
RUN npm run build
# 第二阶段:运行
FROM nginx:1.21-alpine
# 复制自定义Nginx配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 从构建阶段复制产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 添加健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:80 || exit 1
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
对应的nginx.conf:
nginx复制server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# 启用gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 静态资源缓存
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# 禁止访问.git等隐藏文件
location ~ /\. {
deny all;
}
}
优化点解析:
- 分阶段构建减小最终镜像体积(从~330MB降到~22MB)
- 使用npm ci代替npm install确保依赖一致性
- 单独复制package.json以利用Docker缓存
- 自定义Nginx配置提升性能
- 添加健康检查便于容器编排
- 静态资源设置长期缓存
4. 构建与运行:实战细节
4.1 构建镜像
在项目根目录执行:
bash复制docker build -t my-vue-app .
构建过程中的常见问题及解决方案:
问题1:npm install时网络超时
- 解决方案:更换国内镜像源
dockerfile复制RUN npm config set registry https://registry.npmmirror.com && \
npm ci --production
问题2:构建时内存不足
- 解决方案:增加Node内存限制
dockerfile复制ENV NODE_OPTIONS="--max-old-space-size=4096"
问题3:文件权限问题
- 解决方案:在Dockerfile中明确设置用户
dockerfile复制RUN chown -R nginx:nginx /usr/share/nginx/html
USER nginx
4.2 运行容器
基础运行命令:
bash复制docker run -d -p 8080:80 --name vue-container my-vue-app
高级运行参数示例:
bash复制docker run -d \
-p 8080:80 \
--name vue-container \
--restart unless-stopped \
--memory 512m \
--cpus 1 \
my-vue-app
参数说明:
--restart unless-stopped:容器意外退出时自动重启--memory 512m:限制内存使用--cpus 1:限制CPU使用
4.3 查看运行状态
检查容器日志:
bash复制docker logs -f vue-container
查看资源使用:
bash复制docker stats vue-container
进入容器调试:
bash复制docker exec -it vue-container sh
5. 进阶配置与生产实践
5.1 多环境配置
实际项目中,我们通常需要区分开发、测试、生产环境。可以通过环境变量实现:
- 在Vue项目中创建.env文件:
code复制VUE_APP_API_URL=https://api.example.com
VUE_APP_ENV=production
- 修改Dockerfile支持环境变量:
dockerfile复制ARG ENV=production
ENV VUE_APP_ENV=$ENV
# 构建时传入环境变量
RUN npm run build -- --mode $ENV
- 构建时指定环境:
bash复制docker build --build-arg ENV=production -t my-vue-app .
5.2 使用Docker Compose
对于复杂项目,推荐使用docker-compose.yml:
yaml复制version: '3.8'
services:
web:
image: my-vue-app
build:
context: .
args:
ENV: production
ports:
- "8080:80"
environment:
- VUE_APP_API_URL=https://api.example.com
networks:
- frontend
# 可以添加后端服务
api:
image: my-api-service
ports:
- "3000:3000"
networks:
- frontend
networks:
frontend:
driver: bridge
启动命令:
bash复制docker-compose up -d --build
5.3 镜像优化技巧
- 使用多阶段构建减少最终镜像大小
- 选择alpine等轻量级基础镜像
- 合并RUN命令减少镜像层数
- 使用.dockerignore文件排除无关文件
示例.dockerignore:
code复制node_modules
.git
*.md
.vscode
dist
5.4 监控与日志
生产环境建议添加:
- 日志收集:
bash复制docker run --log-driver=syslog --log-opt syslog-address=udp://logserver:514 my-vue-app
- 性能监控(需配合Prometheus):
dockerfile复制# 在Nginx镜像中添加状态模块
FROM nginx:1.21-alpine
RUN echo "load_module modules/ngx_http_status_module.so;" > /etc/nginx/load_modules.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
然后在nginx.conf中添加:
nginx复制location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
6. 常见问题排查
6.1 容器启动后访问空白页
可能原因及解决方案:
- 路径问题:检查vue.config.js中的publicPath,应设为'./'
- 文件权限:在Dockerfile中添加
RUN chmod -R 755 /usr/share/nginx/html - Nginx配置错误:检查nginx.conf中的root路径是否正确
- 构建失败:查看构建日志
docker logs vue-container
6.2 热更新失效
开发环境下如需热更新,需特殊配置:
- docker-compose.dev.yml:
yaml复制version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
volumes:
- ./src:/app/src
- ./public:/app/public
environment:
- CHOKIDAR_USEPOLLING=true
- Dockerfile.dev:
dockerfile复制FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["npm", "run", "serve"]
6.3 跨域问题
解决方案:
- 开发环境:配置vue.config.js中的devServer.proxy
- 生产环境:在nginx.conf中添加代理配置:
nginx复制location /api {
proxy_pass https://api.example.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
6.4 镜像构建缓慢
优化建议:
- 使用国内镜像源
- 合理利用缓存(如分离COPY package.json和COPY .)
- 使用BuildKit:
bash复制DOCKER_BUILDKIT=1 docker build -t my-vue-app .
- 考虑使用--no-cache参数定期完全重建
7. 安全最佳实践
7.1 镜像安全
- 定期更新基础镜像
dockerfile复制FROM node:16-alpine@sha256:具体SHA值
- 使用非root用户运行
dockerfile复制RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
- 扫描镜像漏洞
bash复制docker scan my-vue-app
7.2 运行时安全
- 限制容器权限
bash复制docker run --read-only --tmpfs /tmp -p 8080:80 my-vue-app
- 设置资源限制
bash复制docker run --memory 512m --cpus 1 -p 8080:80 my-vue-app
- 使用秘密管理
bash复制docker secret create api-key ./api-key.txt
7.3 网络安全
- 仅暴露必要端口
- 使用内部网络隔离服务
- 考虑添加WAF(如Nginx的ModSecurity模块)
8. 部署到云平台
8.1 上传镜像到仓库
- 登录Docker Hub:
bash复制docker login -u yourusername
- 打标签:
bash复制docker tag my-vue-app yourusername/my-vue-app:1.0
- 推送:
bash复制docker push yourusername/my-vue-app:1.0
8.2 AWS ECS部署示例
- 创建task-definition.json:
json复制{
"family": "vue-app",
"networkMode": "awsvpc",
"executionRoleArn": "arn:aws:iam::account-id:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "web",
"image": "yourusername/my-vue-app:1.0",
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"essential": true
}
],
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024"
}
- 注册任务定义:
bash复制aws ecs register-task-definition --cli-input-json file://task-definition.json
- 创建服务:
bash复制aws ecs create-service --cluster my-cluster --service-name vue-service \
--task-definition vue-app:1 --desired-count 2 --launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-1234],securityGroups=[sg-1234]}"
8.3 Kubernetes部署示例
deployment.yaml:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: vue-app
spec:
replicas: 3
selector:
matchLabels:
app: vue
template:
metadata:
labels:
app: vue
spec:
containers:
- name: web
image: yourusername/my-vue-app:1.0
ports:
- containerPort: 80
resources:
limits:
cpu: "500m"
memory: "512Mi"
service.yaml:
yaml复制apiVersion: v1
kind: Service
metadata:
name: vue-service
spec:
selector:
app: vue
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
应用配置:
bash复制kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
9. 持续集成与交付(CI/CD)
9.1 GitHub Actions示例
创建.github/workflows/deploy.yml:
yaml复制name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: yourusername/my-vue-app:latest,yourusername/my-vue-app:${{ github.sha }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Install kubectl
uses: azure/setup-kubectl@v1
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/vue-app web=yourusername/my-vue-app:${{ github.sha }}
9.2 GitLab CI示例
.gitlab-ci.yml:
yaml复制stages:
- build
- deploy
variables:
DOCKER_IMAGE: registry.gitlab.com/yourgroup/yourproject
build:
stage: build
script:
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
only:
- main
deploy:
stage: deploy
script:
- echo "$KUBE_CONFIG" > kubeconfig.yaml
- export KUBECONFIG=kubeconfig.yaml
- kubectl set image deployment/vue-app web=$DOCKER_IMAGE
only:
- main
10. 性能优化实战
10.1 镜像构建优化
- 使用BuildKit并行构建:
bash复制DOCKER_BUILDKIT=1 docker build --progress=plain .
- 利用缓存挂载:
dockerfile复制RUN --mount=type=cache,target=/root/.npm \
npm ci --production
- 多阶段构建的精细控制:
dockerfile复制# 第一阶段:依赖安装
FROM node:16-alpine as deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# 第二阶段:开发环境(带devDependencies)
FROM node:16-alpine as dev
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm install
# 第三阶段:构建
FROM dev as builder
RUN npm run build
# 第四阶段:生产
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
10.2 运行时优化
- 启用Nginx的gzip和brotli压缩:
nginx复制gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
- 配置长期缓存:
nginx复制location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
- 启用HTTP/2:
nginx复制listen 443 ssl http2;
10.3 前端代码优化
- 代码分割:
javascript复制// vue.config.js
module.exports = {
chainWebpack: config => {
config.optimization.splitChunks({
chunks: 'all'
})
}
}
- 预加载关键资源:
html复制<link rel="preload" href="/fonts/important.woff2" as="font" type="font/woff2" crossorigin>
- 使用WebP格式图片:
dockerfile复制RUN apk add --no-cache libwebp-tools && \
find /app/public -type f -name '*.jpg' -exec cwebp -q 80 {} -o {}.webp \;
11. 现代化部署方案
11.1 Serverless部署
使用AWS Lambda + API Gateway:
- 安装serverless框架:
bash复制npm install -g serverless
- 创建serverless.yml:
yaml复制service: vue-app
provider:
name: aws
runtime: nodejs14.x
region: us-east-1
memorySize: 512
timeout: 10
functions:
app:
handler: server.handler
events:
- http: ANY /
- http: ANY /{proxy+}
plugins:
- serverless-finch
- serverless-single-page-app-plugin
custom:
client:
bucketName: my-vue-app-bucket
distributionFolder: dist
- 部署命令:
bash复制sls deploy
11.2 边缘计算部署
使用Cloudflare Workers:
- 安装Wrangler CLI:
bash复制npm install -g @cloudflare/wrangler
- 配置wrangler.toml:
toml复制name = "vue-app"
type = "javascript"
account_id = "your_account_id"
workers_dev = true
route = "example.com/*"
[site]
bucket = "./dist"
entry-point = "worker"
- worker.js内容:
javascript复制import manifest from '__STATIC_CONTENT_MANIFEST'
import { getAssetFromKV } from '@cloudflare/kv-asset-handler'
addEventListener('fetch', event => {
event.respondWith(handleEvent(event))
})
async function handleEvent(event) {
try {
return await getAssetFromKV(event, {
mapRequestToAsset: req => new Request(`${new URL(req.url).origin}/index.html`, req)
})
} catch (e) {
return new Response(e.message || e.toString(), { status: 500 })
}
}
- 部署:
bash复制wrangler publish
12. 监控与告警
12.1 基础监控配置
- 添加Prometheus监控:
dockerfile复制FROM nginx:1.21-alpine
RUN apk add --no-cache nginx-mod-http-stub-status
COPY nginx.conf /etc/nginx/conf.d/default.conf
nginx.conf添加:
nginx复制location /metrics {
stub_status on;
access_log off;
}
- Prometheus配置:
yaml复制scrape_configs:
- job_name: 'vue-app'
static_configs:
- targets: ['your-container-ip:80']
12.2 日志分析
使用ELK Stack收集日志:
- docker-compose.yml添加:
yaml复制services:
web:
logging:
driver: "fluentd"
options:
fluentd-address: "localhost:24224"
tag: "vue-app"
fluentd:
image: fluent/fluentd
ports:
- "24224:24224"
volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf
elasticsearch:
image: elasticsearch:7.9.3
environment:
- discovery.type=single-node
ports:
- "9200:9200"
kibana:
image: kibana:7.9.3
ports:
- "5601:5601"
- fluentd.conf配置:
xml复制<source>
@type forward
port 24224
</source>
<match vue-app>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix vue-app
</match>
12.3 性能告警
使用Grafana设置告警:
- 创建仪表盘监控:
- 请求成功率
- 响应时间P99
- 容器内存/CPU使用率
- HTTP错误率
- 设置告警规则示例:
json复制{
"alert": "HighErrorRate",
"expr": "sum(rate(nginx_http_requests_total{status=~\"5..\"}[1m])) by (service) / sum(rate(nginx_http_requests_total[1m])) by (service) > 0.05",
"for": "5m",
"annotations": {
"description": "{{ $labels.service }} has high error rate: {{ $value }}"
}
}
13. 成本优化策略
13.1 资源利用率优化
- 自动扩缩容配置(Kubernetes示例):
yaml复制apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: vue-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vue-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- 使用Spot实例(AWS示例):
yaml复制# ECS task-definition.json
"requiresCompatibilities": ["FARGATE", "EC2"],
"capacityProviderStrategy": [
{
"capacityProvider": "FARGATE_SPOT",
"weight": 1
}
]
13.2 存储优化
- 使用CDN缓存静态资源:
nginx复制location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header X-CDN "Cloudflare";
}
- 镜像仓库清理策略:
bash复制# 保留最近5个标签,删除其余
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
spotify/docker-gc --keep-tags=5
13.3 网络成本优化
- 启用压缩:
nginx复制gzip on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript;
- 使用HTTP/3(QUIC):
nginx复制listen 443 quic reuseport;
listen [::]:443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';
14. 备份与灾难恢复
14.1 数据备份策略
- 定期备份Docker镜像:
bash复制docker save my-vue-app | gzip > my-vue-app-backup-$(date +%Y%m%d).tar.gz
- 使用Volume备份:
bash复制docker run --rm --volumes-from vue-container -v $(pwd):/backup busybox \
tar cvf /backup/nginx-data-$(date +%Y%m%d).tar /usr/share/nginx/html
14.2 恢复流程
- 镜像恢复:
bash复制docker load < my-vue-app-backup-20230501.tar.gz
- 数据恢复:
bash复制docker run --rm --volumes-from vue-container -v $(pwd):/backup busybox \
tar xvf /backup/nginx-data-20230501.tar
14.3 多区域部署
AWS多区域部署示例:
bash复制# 主区域
aws ecs create-service --cluster us-east-1-cluster --service-name vue-app \
--task-definition vue-app:1 --desired-count 3
# 备用区域
aws ecs create-service --cluster eu-west-1-cluster --service-name vue-app \
--task-definition vue-app:1 --desired-count 1
使用Route53故障转移路由:
json复制{
"Failover": "FAILOVER",
"Type": "CNAME",
"SetIdentifier": "Primary",
"Name": "app.example.com",
"ResourceRecords": ["us-east-1.elb.amazonaws.com"],
"HealthCheckId": "healthcheck-id",
"Failover": "PRIMARY"
},
{
"Failover": "FAILOVER",
"Type": "CNAME",
"SetIdentifier": "Secondary",
"Name": "app.example.com",
"ResourceRecords": ["eu-west-1.elb.amazonaws.com"],
"Failover": "SECONDARY"
}
15. 本地开发与生产一致性
15.1 开发环境容器化
docker-compose.dev.yml:
yaml复制version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
volumes:
- ./src:/app/src
- ./public:/app/public
environment:
- CHOKIDAR_USEPOLLING=true
- NODE_ENV=development
networks:
- frontend
api:
image: mock-api
ports:
- "3000:3000"
networks:
- frontend
networks:
frontend:
driver: bridge
Dockerfile.dev:
dockerfile复制FROM node:16-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["npm", "run", "serve"]
15.2 使用Telepresence调试
- 安装Telepresence:
bash复制# Mac
brew install datawire/blackbird/telepresence
# Linux
sudo apt install --no-install-recommends telepresence
- 拦截生产流量到本地:
bash复制telepresence intercept vue-app --port 8080:80
15.3 环境变量管理
使用.env文件与Docker结合:
- .env.production:
code复制VUE_APP_API_URL=https://api.example.com
VUE_APP_GA_ID=UA-XXXXX-Y
- docker-compose.yml中引用:
yaml复制services:
web:
env_file:
- .env.production
- Vue代码中使用:
javascript复制axios.get(process.env.VUE_APP_API_URL)
16. 微前端架构下的部署
16.1 作为微前端子应用
- 修改vue.config.js:
javascript复制module.exports = {
publicPath: '/vue-app/',
configureWebpack: {
output: {
library: 'vueApp',
libraryTarget: 'umd'
}
}
}
- 添加生命周期钩子:
javascript复制// public/entry.js
import('./bootstrap')
export async function bootstrap() {
console.log('vue app bootstraped')
}
export async function mount(props) {
console.log('vue app mount', props)
render(props)
}
export async function unmount() {
console.log('vue app unmount')
destroy()
}
- 调整Dockerfile构建:
dockerfile复制RUN npm run build && \
echo "export default window.vueApp = { bootstrap, mount, unmount }" >> dist/entry.js
16.2 使用Module Federation
- 配置webpack:
javascript复制// vue.config.js
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin
module.exports = {
configureWebpack: {
plugins: [
new ModuleFederationPlugin({
name: 'vueApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button.vue'
},
shared: {
vue: { singleton: true }
}
})
]
}
}
- Nginx配置添加CORS支持:
nginx复制location /vue-app/ {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
}
17. 安全加固进阶
17.1 内容安全策略(CSP)
在nginx.conf中添加:
nginx复制add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://*.example.com; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'none'; form-action 'self'; base-uri 'self';";
17.2 安全头设置
完整的安全头配置:
nginx复制add_header X-Frame-Options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
17.3 容器运行时保护
- 使用只读文件系统:
bash复制docker run --read-only --tmpfs /tmp -p 8080:80 my-vue-app
- 禁用特权模式:
bash复制docker run --security-opt=no-new-privileges -p 8080:80 my-vue-app
- 使用用户命名空间:
bash复制dockerd --userns-remap=default
18. 自动化测试集成
18.1 单元测试
Dockerfile.test:
dockerfile复制FROM node:16-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["npm", "test"]
运行测试:
bash复制docker build -t vue-app-test -f Dockerfile.test .
docker run -it vue-app-test
18.2 E2E测试
docker-compose.test.yml:
yaml复制version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
test:
build:
context: .
dockerfile: Dockerfile.test
depends_on:
- web
environment:
- BASE_URL=http://web:80
command: ["npm", "run", "test:e2e"]
18.3 可视化测试
集成Storybook:
- Dockerfile.storybook:
dockerfile复制FROM
