Skip to content
Guides6 min read

서버에 Potato 배포하기

Docker, nginx, SSL과 AWS, GCP, Azure를 포함한 클라우드 플랫폼으로 Potato를 프로덕션에 배포합니다. systemd 서비스 구성과 확장 팁을 포함합니다.

Potato Team

이 가이드는 Potato를 프로덕션에서 실행하는 방법을 다룹니다. 서버 설정, Docker, 주요 클라우드 플랫폼, 그리고 무언가를 인터넷에 노출하기 전에 갖춰 두어야 할 보안 구성까지 살펴봅니다. GitHub의 배포 문서에서 이 주제들 중 일부를 더 깊이 다룹니다.

배포 옵션

방식적합한 용도복잡도
로컬개발, 테스트낮음
Docker재현 가능한 배포중간
클라우드 VM완전한 제어, 맞춤 설정중간
Docker Compose다중 컨테이너 구성중간
Kubernetes대규모 배포높음

기본 서버 배포

사전 요구 사항

bash
# Ubuntu/Debian server
sudo apt update
sudo apt install python3.9 python3-pip nginx certbot python3-certbot-nginx
 
# Create directory structure
mkdir -p /opt/potato/projects
cd /opt/potato

설치

bash
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
 
# Install Potato
pip install potato-annotation
 
# Verify installation
potato --version

Gunicorn으로 실행하기

bash
# Install production server
pip install gunicorn
 
# Run with gunicorn
gunicorn -w 4 -b 127.0.0.1:8000 \
  --chdir /opt/potato/projects/my_project \
  "potato.server:create_app(config_path='config.yaml')"

Systemd 서비스

/etc/systemd/system/potato.service를 만듭니다.

ini
[Unit]
Description=Potato Annotation Server
After=network.target
 
[Service]
Type=simple
User=potato
Group=potato
WorkingDirectory=/opt/potato/projects/my_project
Environment="PATH=/opt/potato/venv/bin"
ExecStart=/opt/potato/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 \
  "potato.server:create_app(config_path='config.yaml')"
Restart=always
RestartSec=10
 
[Install]
WantedBy=multi-user.target

활성화하고 시작합니다.

bash
sudo systemctl enable potato
sudo systemctl start potato
sudo systemctl status potato

Nginx 구성

기본 리버스 프록시

/etc/nginx/sites-available/potato를 만듭니다.

nginx
server {
    listen 80;
    server_name annotation.example.com;
 
    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
 
        # WebSocket support (if needed)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
 
    # Static files
    location /static/ {
        alias /opt/potato/projects/my_project/static/;
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
 
    # Upload size limit
    client_max_body_size 100M;
}

사이트를 활성화합니다.

bash
sudo ln -s /etc/nginx/sites-available/potato /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Let's Encrypt로 SSL 설정하기

bash
# Get SSL certificate
sudo certbot --nginx -d annotation.example.com
 
# Auto-renewal
sudo systemctl enable certbot.timer

Docker 배포

Dockerfile

dockerfile
FROM python:3.9-slim
 
WORKDIR /app
 
# Install dependencies
RUN pip install potato-annotation gunicorn
 
# Copy project files
COPY config.yaml .
COPY data/ ./data/
 
# Create directories
RUN mkdir -p annotations logs
 
# Expose port
EXPOSE 8000
 
# Run server
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", \
     "potato.server:create_app(config_path='config.yaml')"]

빌드 및 실행

bash
# Build image
docker build -t potato-annotation .
 
# Run container
docker run -d \
  --name potato \
  -p 8000:8000 \
  -v $(pwd)/annotations:/app/annotations \
  -v $(pwd)/logs:/app/logs \
  potato-annotation

Docker Compose

yaml
# docker-compose.yml
version: '3.8'
 
services:
  potato:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ./data:/app/data:ro
      - ./annotations:/app/annotations
      - ./logs:/app/logs
    environment:
      - POTATO_ENV=production
    restart: unless-stopped
 
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - potato
    restart: unless-stopped

클라우드 플랫폼 배포

AWS EC2

bash
# Launch EC2 instance (Ubuntu 22.04)
# Configure security group: ports 22, 80, 443
 
# SSH to instance
ssh -i your-key.pem ubuntu@your-instance-ip
 
# Follow basic server deployment steps above
 
# For persistent storage, attach EBS volume
sudo mount /dev/xvdf /opt/potato/data

Google Cloud Platform

bash
# Create VM instance
gcloud compute instances create potato-server \
  --zone=us-central1-a \
  --machine-type=e2-medium \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud
 
# Configure firewall
gcloud compute firewall-rules create allow-http \
  --allow tcp:80,tcp:443

DigitalOcean

bash
# Create droplet via CLI
doctl compute droplet create potato-server \
  --size s-2vcpu-4gb \
  --image ubuntu-22-04-x64 \
  --region nyc1

프로덕션 구성

프로덕션 설정

yaml
# config.yaml
annotation_task_name: "Production Annotation Task"
 
# Note: Server settings (host, port, workers) are CLI flags:
#   potato -p 8000 --host 0.0.0.0 config.yaml
# Or use gunicorn for production with multiple workers
 
# Logging
logging:
  level: INFO
  file: logs/potato.log
  format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
  rotation:
    max_size: 10MB
    backup_count: 5
 
# Data
data_files:
  - items.jsonl
 
item_properties:
  id_key: id
  text_key: text
 
# Output
output_annotation_dir: annotations/
export_annotation_format: jsonl

환경 변수

bash
# /opt/potato/.env
POTATO_SECRET_KEY=your-secure-random-key-here
POTATO_ENV=production
OPENAI_API_KEY=sk-...  # If using AI features

systemd에서 로드합니다.

ini
[Service]
EnvironmentFile=/opt/potato/.env

보안 모범 사례

프로젝트를 오픈소스로 공개하거나 일반 대중으로부터 데이터를 수집하는 경우, 이 섹션에서 다루지 않는 개인정보 및 라이선스 부분에 대해 오픈소싱 가이드도 함께 읽어 보십시오.

인증

yaml
user_config:
  auth_type: password
 
  # Strong password requirements
  password_policy:
    min_length: 12
    require_uppercase: true
    require_number: true
 
  # Session security
  session:
    secure_cookie: true
    http_only: true
    same_site: strict

HTTPS 구성

nginx
server {
    listen 443 ssl http2;
    server_name annotation.example.com;
 
    ssl_certificate /etc/letsencrypt/live/annotation.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/annotation.example.com/privkey.pem;
 
    # Modern SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
 
    # Security headers
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
 
    # ... rest of config
}

방화벽

bash
# UFW configuration
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Nginx Full'
sudo ufw enable

모니터링

헬스 체크 엔드포인트

bash
# Check server health
curl http://localhost:8000/health
 
# Expected response
{"status": "healthy", "version": "2.0.0"}

로그 모니터링

bash
# View logs
sudo journalctl -u potato -f
 
# Or check log file
tail -f /opt/potato/logs/potato.log

Prometheus 메트릭(선택)

yaml
# config.yaml
monitoring:
  prometheus:
    enabled: true
    port: 9090

백업 전략

자동화된 백업

bash
# backup.sh
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=/opt/potato/backups
 
# Backup annotations
tar -czf $BACKUP_DIR/annotations_$DATE.tar.gz /opt/potato/projects/*/annotations/
 
# Backup configs
tar -czf $BACKUP_DIR/configs_$DATE.tar.gz /opt/potato/projects/*/config.yaml
 
# Remove old backups (keep 7 days)
find $BACKUP_DIR -mtime +7 -delete
 
# Optional: sync to cloud storage
# aws s3 sync $BACKUP_DIR s3://your-bucket/potato-backups/

crontab에 추가합니다.

bash
# Run daily at 2am
0 2 * * * /opt/potato/backup.sh

확장

다중 워커

bash
# Increase gunicorn workers based on CPU cores
gunicorn -w $((2 * $(nproc) + 1)) -b 0.0.0.0:8000 ...

로드 밸런싱

nginx
upstream potato_servers {
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
    server 127.0.0.1:8003;
}
 
server {
    location / {
        proxy_pass http://potato_servers;
    }
}

문제 해결

자주 발생하는 문제

포트가 이미 사용 중:

bash
sudo lsof -i :8000
sudo kill -9 <PID>

권한 거부됨:

bash
sudo chown -R potato:potato /opt/potato

메모리 부족:

bash
# Add swap space
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

추가 도움이 필요하면 전체 문서GitHub 토론을 참조하십시오.