Docker与cpolar深度整合:构建高可用私人证件照服务系统

引言

证件照作为日常生活中高频使用的图像类型,其制作需求往往具有突发性和时效性。传统照相馆模式存在时间成本高、隐私风险大、重复修改不便等痛点。本文将介绍如何利用Docker容器化技术与cpolar内网穿透服务,搭建一套可随时随地访问的私人证件照制作系统。

这个方案特别适合以下场景:

  • 经常需要更新证件照的商务人士
  • 有多个家庭成员需要不同规格证件照的家庭
  • 对隐私保护有较高要求的用户
  • 希望降低长期证件照制作成本的技术爱好者

我们将从基础环境搭建开始,逐步深入到生产级部署的各个环节,重点解决临时地址不稳定、服务可靠性等实际问题。

1. 基础环境配置

1.1 Docker引擎安装与优化

在Ubuntu系统上安装Docker推荐使用官方脚本,但针对国内网络环境需要特别优化:

# 安装必要依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

# 添加Docker官方GPG密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 设置稳定版仓库
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker引擎
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

安装完成后,建议进行以下优化配置:

  1. 用户组配置:将当前用户加入docker组,避免每次使用sudo

    sudo usermod -aG docker $USER
    newgrp docker
    
  2. 日志限制:防止容器日志占用过多磁盘空间

    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "10m",
        "max-file": "3"
      },
      "registry-mirrors": ["https://docker.m.daocloud.io"]
    }
    EOF
    sudo systemctl restart docker
    

1.2 系统资源调优

为确保服务稳定运行,需要对系统参数进行调整:

# 增加系统最大文件描述符数量
echo "fs.file-max = 100000" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# 调整内核参数优化网络性能
echo "net.core.somaxconn = 65535" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 65535" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

2. HivisionIDPhotos容器化部署

2.1 容器启动与配置

使用官方镜像启动服务时,建议添加资源限制和健康检查:

docker run -d \
  --name hivision_idphotos \
  --restart unless-stopped \
  --memory 2g \
  --cpus 1.5 \
  -p 7860:7860 \
  --health-cmd "curl -f http://localhost:7860 || exit 1" \
  --health-interval 30s \
  --health-timeout 10s \
  --health-retries 3 \
  linzeyi/hivision_idphotos

关键参数说明:

  • --restart unless-stopped:确保容器异常退出后自动重启
  • --memory 2g:限制容器最大内存使用量
  • --cpus 1.5:限制容器CPU使用量
  • 健康检查配置:每30秒检查一次服务可用性

2.2 持久化存储配置

为防止容器重建时数据丢失,应该将重要目录挂载到宿主机:

mkdir -p ~/hivision_data/{config,output}

docker run -d \
  --name hivision_idphotos \
  -v ~/hivision_data/config:/app/config \
  -v ~/hivision_data/output:/app/output \
  -p 7860:7860 \
  linzeyi/hivision_idphotos

目录结构说明:

  • /app/config:保存应用配置
  • /app/output:存储生成的证件照

3. cpolar高级配置技巧

3.1 服务安装与系统集成

cpolar的安装可以通过官方脚本完成,但生产环境建议配置为系统服务:

# 安装cpolar
curl https://get.cpolar.sh | sudo bash

# 创建系统服务配置文件
sudo tee /etc/systemd/system/cpolar.service <<-'EOF'
[Unit]
Description=Cpolar Service
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/cpolar http 7860
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

# 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable cpolar
sudo systemctl start cpolar

3.2 隧道管理最佳实践

创建隧道时,建议使用配置文件而非Web UI,便于版本控制和批量管理:

# 创建配置文件目录
mkdir -p ~/cpolar_config

# 生成隧道配置文件
cat > ~/cpolar_config/hivision_tunnel.yml <<EOF
tunnels:
  hivision:
    addr: 7860
    proto: http
    region: hk
    hostname: myphotos.example.com
    auth:
      username: myuser
      password: mypassword
EOF

# 使用配置文件启动隧道
cpolar start-all -config ~/cpolar_config/hivision_tunnel.yml

配置文件优势:

  • 支持多个隧道集中管理
  • 可以纳入版本控制系统
  • 便于批量部署和迁移

4. 生产级部署方案

4.1 固定域名与HTTPS配置

要实现真正的生产级部署,需要配置固定域名和HTTPS加密:

  1. 域名准备

    • 注册一个专属域名(如yourdomain.com)
    • 在DNS服务商处添加CNAME记录指向cpolar提供的域名
  2. HTTPS配置

    # 使用Let's Encrypt获取SSL证书
    sudo apt-get install -y certbot
    sudo certbot certonly --standalone -d myphotos.yourdomain.com
    
    # 配置cpolar使用SSL证书
    cpolar http 7860 \
      -hostname=myphotos.yourdomain.com \
      -tls-cert=/etc/letsencrypt/live/myphotos.yourdomain.com/fullchain.pem \
      -tls-key=/etc/letsencrypt/live/myphotos.yourdomain.com/privkey.pem
    
  3. 证书自动续期

    # 创建续期脚本
    sudo tee /etc/cron.weekly/renew_certs <<'EOF'
    #!/bin/bash
    certbot renew --quiet --post-hook "systemctl restart cpolar"
    EOF
    sudo chmod +x /etc/cron.weekly/renew_certs
    

4.2 高可用架构设计

对于关键业务场景,可以考虑以下高可用方案:

方案一:多节点负载均衡

用户请求 → 负载均衡器 → [节点1, 节点2, 节点3]
                      ↘ 数据库集群

方案二:热备部署

  • 主节点:在线提供服务
  • 备节点:实时同步数据,主节点故障时自动切换

实现示例(使用Docker Swarm):

# 初始化Swarm集群
docker swarm init

# 部署服务
docker service create \
  --name hivision_idphotos \
  --replicas 3 \
  --publish published=7860,target=7860 \
  --mount type=bind,source=/path/to/shared/storage,target=/app/output \
  linzeyi/hivision_idphotos

4.3 监控与告警系统

完善的监控体系应包括:

  1. 基础资源监控

    • CPU、内存、磁盘使用率
    • 网络带宽利用率
  2. 服务健康监控

    • 服务响应时间
    • 错误率
    • 请求吞吐量
  3. 业务指标监控

    • 证件照生成数量
    • 平均处理时间
    • 用户满意度

推荐使用Prometheus+Grafana搭建监控平台:

# 启动Prometheus
docker run -d \
  --name=prometheus \
  -p 9090:9090 \
  -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

# 启动Grafana
docker run -d \
  --name=grafana \
  -p 3000:3000 \
  grafana/grafana

5. 安全加固措施

5.1 访问控制策略

  1. 基础认证

    # 启动带基础认证的cpolar隧道
    cpolar http 7860 \
      -auth="username:password"
    
  2. IP白名单

    # 使用iptables限制访问IP
    sudo iptables -A INPUT -p tcp --dport 7860 -s 192.168.1.100 -j ACCEPT
    sudo iptables -A INPUT -p tcp --dport 7860 -j DROP
    
  3. 速率限制

    # 使用nginx作为反向代理并配置限流
    docker run -d \
      --name nginx_proxy \
      -p 80:80 \
      -v /path/to/nginx.conf:/etc/nginx/nginx.conf \
      nginx
    

示例nginx.conf限流配置:

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

    server {
        location / {
            limit_req zone=one burst=20;
            proxy_pass http://hivision_idphotos:7860;
        }
    }
}

5.2 数据安全保护

  1. 加密存储

    # 使用eCryptFS创建加密目录
    sudo apt-get install -y ecryptfs-utils
    mkdir -p ~/encrypted_photos
    sudo mount -t ecryptfs ~/hivision_data/output ~/encrypted_photos
    
  2. 自动备份方案

    # 使用rsync进行增量备份
    rsync -avz --delete ~/hivision_data/ backup_server:/backup/hivision/
    
    # 设置定时任务
    (crontab -l 2>/dev/null; echo "0 3 * * * rsync -avz --delete ~/hivision_data/ backup_server:/backup/hivision/") | crontab -
    
  3. 敏感信息处理

    # 使用openssl加密配置文件
    openssl enc -aes-256-cbc -salt -in config.yml -out config.yml.enc
    

6. 性能优化技巧

6.1 容器资源调优

通过cgroups限制资源使用:

docker update \
  --cpus 2 \
  --memory 4g \
  --memory-swap 4g \
  hivision_idphotos

建议监控指标:

  • 容器CPU使用率(保持在70%以下)
  • 内存使用量(避免频繁交换)
  • 磁盘IOPS(特别是生成大量图片时)

6.2 网络性能优化

  1. TCP参数调优

    echo "net.ipv4.tcp_tw_reuse = 1" | sudo tee -a /etc/sysctl.conf
    echo "net.ipv4.tcp_fin_timeout = 30" | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p
    
  2. 启用BBR拥塞控制

    echo "net.core.default_qdisc = fq" | sudo tee -a /etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control = bbr" | sudo tee -a /etc/sysctl.conf
    sudo sysctl -p
    

6.3 图片处理加速

  1. GPU加速

    # 启用NVIDIA GPU支持
    docker run -d \
      --gpus all \
      -p 7860:7860 \
      linzeyi/hivision_idphotos
    
  2. 内存缓存优化

    # 使用tmpfs加速临时文件访问
    docker run -d \
      --tmpfs /tmp:rw,size=1g \
      -p 7860:7860 \
      linzeyi/hivision_idphotos
    

7. 扩展功能开发

7.1 API集成方案

HivisionIDPhotos可以通过API与其他系统集成:

import requests

def generate_id_photo(image_path, size="1inch"):
    url = "http://yourdomain.com/api/generate"
    files = {'image': open(image_path, 'rb')}
    data = {'size': size, 'background': 'white'}
    
    response = requests.post(url, files=files, data=data)
    if response.status_code == 200:
        with open('output.jpg', 'wb') as f:
            f.write(response.content)
        return True
    return False

7.2 批量处理功能

使用Shell脚本实现批量处理:

#!/bin/bash

INPUT_DIR="./input_photos"
OUTPUT_DIR="./output_photos"

for file in "$INPUT_DIR"/*.{jpg,jpeg,png}; do
    filename=$(basename -- "$file")
    curl -X POST \
      -F "image=@$file" \
      -F "size=1inch" \
      -F "background=blue" \
      "http://localhost:7860/api/generate" \
      > "$OUTPUT_DIR/${filename%.*}_idphoto.jpg"
done

7.3 自定义模板开发

通过修改容器内的模板文件实现个性化:

# 进入容器shell
docker exec -it hivision_idphotos /bin/bash

# 修改模板文件
vi /app/templates/default.html

# 重启容器使更改生效
docker restart hivision_idphotos

8. 故障排查指南

8.1 常见问题解决

问题1:容器启动失败

  • 检查日志:docker logs hivision_idphotos
  • 验证端口冲突:sudo netstat -tulnp | grep 7860
  • 测试基础镜像:docker run -it --rm linzeyi/hivision_idphotos /bin/bash

问题2:cpolar连接不稳定

  • 检查网络延迟:ping cpolar.cn
  • 验证防火墙设置:sudo ufw status
  • 测试不同区域:更换region参数为hkus

8.2 性能瓶颈分析

使用工具进行系统性能分析:

# 容器资源使用情况
docker stats hivision_idphotos

# 系统级监控
sudo apt-get install -y htop
htop

# 网络流量分析
sudo apt-get install -y iftop
sudo iftop -P -n -i eth0

8.3 日志分析技巧

集中管理容器日志:

# 使用json格式日志
docker run -d \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  linzeyi/hivision_idphotos

# 实时查看日志
docker logs -f --tail 100 hivision_idphotos

# 错误日志过滤
docker logs hivision_idphotos 2>&1 | grep -i error

9. 成本优化方案

9.1 资源使用评估

计算当前部署的资源消耗:

# CPU使用率
docker stats --no-stream --format "{{.Container}}: {{.CPUPerc}}" hivision_idphotos

# 内存占用
docker stats --no-stream --format "{{.Container}}: {{.MemUsage}}" hivision_idphotos

9.2 按需伸缩策略

根据负载自动调整资源:

# 创建自动伸缩脚本
cat > /usr/local/bin/scale_service <<'EOF'
#!/bin/bash
LOAD=$(awk '{print $1}' /proc/loadavg)
CPUS=$(nproc)

if (( $(echo "$LOAD > $CPUS*0.8" | bc -l) )); then
    docker update --cpus $(($CPUS+1)) hivision_idphotos
elif (( $(echo "$LOAD < $CPUS*0.3" | bc -l) )); then
    docker update --cpus $(($CPUS/2)) hivision_idphotos
fi
EOF

# 设置定时任务
(crontab -l 2>/dev/null; echo "*/5 * * * * /usr/local/bin/scale_service") | crontab -

9.3 备用方案对比

方案月成本可靠性维护复杂度
家庭服务器$10-50
云服务器(基础型)$20-100
容器服务(托管)$50-200很高

10. 用户体验优化

10.1 响应速度提升

前端优化技巧:

<!-- 预加载关键资源 -->
<link rel="preload" href="main.js" as="script">
<link rel="preload" href="styles.css" as="style">

<!-- 使用WebP格式减少图片大小 -->
<picture>
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="证件照示例">
</picture>

10.2 移动端适配

针对手机用户的特别优化:

/* 响应式布局调整 */
@media (max-width: 768px) {
  .photo-container {
    width: 100%;
    padding: 10px;
  }
  .control-panel {
    flex-direction: column;
  }
}

10.3 个性化设置

允许用户保存偏好配置:

// 使用localStorage保存用户设置
function savePreferences() {
  const preferences = {
    bgColor: document.getElementById('bg-color').value,
    photoSize: document.getElementById('photo-size').value
  };
  localStorage.setItem('userPreferences', JSON.stringify(preferences));
}

// 加载时恢复设置
window.addEventListener('load', () => {
  const saved = JSON.parse(localStorage.getItem('userPreferences'));
  if (saved) {
    document.getElementById('bg-color').value = saved.bgColor;
    document.getElementById('photo-size').value = saved.photoSize;
  }
});

11. 生态系统集成

11.1 与相册应用对接

通过WebDAV协议实现与相册应用的集成:

# 配置rclone访问证件照输出目录
rclone config create hivision_photos webdav \
  url=http://localhost:7860/output \
  vendor=other \
  user=myuser \
  pass=mypass

# 定时同步到相册应用
rclone sync ~/hivision_data/output hivision_photos:IDPhotos -P

11.2 办公软件集成

在Word中插入证件照的宏代码:

Sub InsertIDPhoto()
    Dim photoPath As String
    photoPath = "http://yourdomain.com/output/latest_photo.jpg"
    
    ActiveDocument.InlineShapes.AddPicture _
        FileName:=photoPath, _
        LinkToFile:=False, _
        SaveWithDocument:=True
End Sub

11.3 智能家居联动

通过Home Assistant自动化实现语音控制:

automation:
  - alias: "Print ID Photo"
    trigger:
      platform: event
      event_type: mobile_app_notification_action
      event_data:
        action: "PRINT_ID_PHOTO"
    action:
      - service: shell_command.take_id_photo
      - delay: "00:00:10"
      - service: mqtt.publish
        data:
          topic: "printer/command"
          payload: "PRINT"

12. 维护与升级策略

12.1 变更管理流程

  1. 测试环境验证

    # 创建测试容器
    docker run -d --name hivision_test -p 7861:7860 linzeyi/hivision_idphotos:beta
    
  2. 变更记录表

日期变更内容负责人回滚方案
2023-08-01升级到v1.2张三恢复v1.1镜像
2023-08-15新增蓝色背景李四回滚配置文件

12.2 备份与恢复

全量备份脚本示例:

#!/bin/bash
BACKUP_DIR="/backup/hivision_$(date +%Y%m%d)"

mkdir -p $BACKUP_DIR

# 备份数据卷
docker run --rm \
  -v hivision_data:/volume \
  -v $BACKUP_DIR:/backup \
  alpine tar cvf /backup/data.tar /volume

# 备份配置
docker inspect hivision_idphotos > $BACKUP_DIR/inspect.json
docker exec hivision_idphotos env > $BACKUP_DIR/env.list

12.3 版本升级方案

使用Docker标签管理版本:

# 平滑升级步骤
docker pull linzeyi/hivision_idphotos:latest
docker stop hivision_idphotos
docker rm hivision_idphotos
docker run -d \
  --name hivision_idphotos \
  -v ~/hivision_data:/app/data \
  -p 7860:7860 \
  linzeyi/hivision_idphotos:latest

# 验证新版本
curl -I http://localhost:7860

13. 法律与合规考量

13.1 隐私保护措施

  1. 数据加密传输

    # 强制使用HTTPS
    cpolar http 7860 -scheme=https -redirect-http=true
    
  2. 自动清除策略

    # 设置定时任务清除旧照片
    (crontab -l 2>/dev/null; echo "0 4 * * * find ~/hivision_data/output -type f -mtime +30 -delete") | crontab -
    

13.2 使用条款建议

建议在服务页面添加以下内容:

<div class="terms">
  <h3>服务条款</h3>
  <ol>
    <li>本服务仅限个人非商业用途</li>
    <li>用户需确保上传照片拥有合法权利</li>
    <li>生成的照片将在30天后自动删除</li>
    <li>禁止上传任何违法或侵权内容</li>
  </ol>
</div>

13.3 版权声明处理

在输出照片中添加水印:

// 使用Canvas添加版权信息
function addWatermark(image) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  
  canvas.width = image.width;
  canvas.height = image.height;
  
  ctx.drawImage(image, 0, 0);
  ctx.font = '16px Arial';
  ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
  ctx.fillText('© MyIDPhoto Service', 20, image.height - 20);
  
  return canvas.toDataURL('image/jpeg');
}

14. 社区与支持体系

14.1 知识库建设

使用Wiki系统构建文档:

# 启动Wiki.js容器
docker run -d \
  --name wiki \
  -p 3001:3000 \
  -v ~/wiki_data:/var/db/wiki \
  ghcr.io/requarks/wiki:2

文档结构建议:

1. 快速入门
   1.1 系统要求
   1.2 安装指南
2. 使用教程
   2.1 基本功能
   2.2 高级技巧
3. 故障排除
   3.1 常见问题
   3.2 错误代码

14.2 用户反馈机制

集成反馈表单:

<form action="/api/feedback" method="post">
  <label for="rating">满意度评分:</label>
  <select id="rating" name="rating">
    <option value="5">非常满意</option>
    <option value="4">满意</option>
    <option value="3">一般</option>
    <option value="2">不满意</option>
    <option value="1">非常不满意</option>
  </select>
  
  <label for="comments">建议:</label>
  <textarea id="comments" name="comments"></textarea>
  
  <button type="submit">提交反馈</button>
</form>

14.3 社区贡献指南

开源项目协作规范:

## 如何贡献

1. Fork项目仓库
2. 创建特性分支 (`git checkout -b feature/your-feature`)
3. 提交更改 (`git commit -am 'Add some feature'`)
4. 推送到分支 (`git push origin feature/your-feature`)
5. 创建Pull Request

## 代码规范
- 遵循PEP8标准
- 提交信息使用英文描述
- 新功能需附带测试用例

15. 商业价值拓展

15.1 增值服务设计

潜在收费点分析:

服务类型定价策略目标用户
高清输出按次收费专业用户
批量处理套餐包企业用户
模板商店单品销售普通用户

15.2 数据分析应用

收集的使用数据示例:

{
  "metrics": {
    "daily_active_users": 42,
    "popular_sizes": ["1inch", "2inch"],
    "average_processing_time": "3.2s",
    "conversion_rate": "68%"
  }
}

15.3 合作伙伴生态

可能的合作模式:

  • 照相设备厂商:预装软件
  • 打印服务商:API对接
  • 证件服务商:白标解决方案

16. 技术演进路线

16.1 短期改进计划

接下来3个月的重点:

  1. 实现GPU加速支持
  2. 添加更多证件类型模板
  3. 优化移动端用户体验

16.2 中期技术规划

未来6-12个月的方向:

  • 集成AI背景识别
  • 开发离线处理能力
  • 构建分布式处理集群

16.3 长期愿景

3-5年技术目标:

  • 全自动证件照质量评估
  • 区块链存证服务
  • AR实时预览功能

17. 替代方案评估

17.1 同类产品对比

产品开源Docker支持远程访问成本
HivisionIDPhotos需配置
商业方案A部分内置
开源方案B免费

17.2 自建vs托管服务

决策矩阵:

因素自建方案托管服务
初期成本
长期成本
可控性
维护负担
扩展性

17.3 技术栈替代方案

备选组件评估:

  1. 内网穿透替代

    • ngrok:简单但有限制
    • frp:配置复杂但功能强大
    • 自建中继服务器:成本高但完全可控
  2. 容器编排替代

    • Docker Compose:简单单机部署
    • Kubernetes:复杂但可扩展
    • Nomad:平衡选择

18. 真实案例分享

18.1 个人用户实践

"作为自由职业者,我经常需要为不同客户提交不同规格的证件照。这个方案让我在任何地方都能快速生成符合要求的照片,最近一次签证申请就省去了专门拍照的麻烦。"

18.2 小型企业应用

某咨询公司为50名员工部署了此系统:

  • 年节省照相费用约$5,000
  • 新员工入职流程从2天缩短到2小时
  • 统一了全公司证件照风格标准

18.3 教育机构部署

大学计算机实验室采用此方案:

  • 服务3000多名学生
  • 集成到校园门户网站
  • 高峰时段自动扩容应对负载

19. 资源推荐列表

19.1 学习资料

  • Docker官方文档:https://docs.docker.com/
  • cpolar使用指南:https://www.cpolar.com/docs
  • 图像处理优化技巧:https://imageoptim.com/guides

19.2 工具集合

必备开发工具:

  1. Docker扩展

    • Portainer:可视化容器管理
    • Dive:镜像分析工具
    • ctop:容器监控
  2. 网络调试

    • Wireshark:抓包分析
    • Postman:API测试
    • curl:命令行HTTP工具

19.3 社区资源

活跃的技术论坛:

  • Docker中文社区
  • Stack Overflow的docker标签
  • GitHub相关项目Issues区

20. 创新应用场景

20.1 智能证件照助手

结合语音交互:

import speech_recognition as sr

r = sr.Recognizer()
with sr.Microphone() as source:
    print("请说出您需要的证件照规格:")
    audio = r.listen(source)
    text = r.recognize_google(audio, language='zh-CN')
    print(f"即将生成: {text}规格的证件照")

20.2 自动化简历系统

集成到求职流程:

function generateResumeWithPhoto(userData) {
  return fetch('/api/generate_id_photo', {
    method: 'POST',
    body: JSON.stringify(userData)
  })
  .then(response => response.json())
  .then(photoUrl => {
    document.getElementById('resume-photo').src = photoUrl;
  });
}

20.3 虚拟活动应用

线上会议证件生成:

# 批量生成参会证件
for attendee in $(cat attendees.list); do
  curl -X POST \
    -F "image=@photos/$attendee.jpg" \
    -F "template=conference_badge" \
    http://localhost:7860/api/generate \
    > "badges/$attendee.jpg"
done

更多推荐