From 64404c27ed376260c6e98674a0e750adb8321a9e Mon Sep 17 00:00:00 2001 From: th-kim0823 Date: Sat, 25 Apr 2026 19:35:44 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Docker=20=ED=8C=A8=ED=82=A4=EC=A7=95=20?= =?UTF-8?q?(=EB=A1=9C=EC=BB=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20+=20?= =?UTF-8?q?=ED=99=88=EC=84=9C=EB=B2=84=20=EB=B0=B0=ED=8F=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile: python:3.12-slim 베이스, headless streamlit - docker-compose.yml: ADMIN_TOKEN 환경변수, votes.db 영속 볼륨, participants.json read-only mount - .dockerignore: 빌드 컨텍스트 최소화 테스트: - docker compose build OK - 컨테이너 실행 후 http://localhost:8501 200 OK 확인 Co-Authored-By: Claude Opus 4.7 (1M context) --- .dockerignore | 14 ++++++++++++++ Dockerfile | 20 ++++++++++++++++++++ README.md | 33 +++++++++++++++++++++++---------- docker-compose.yml | 20 ++++++++++++++++++++ 4 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..86e2991 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +.git +.gitignore +*.db +*.sqlite +*.pyc +__pycache__/ +.venv/ +venv/ +.env +README.md +docker-compose.yml +Dockerfile +.dockerignore +teams.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7e765d1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY app.py assign_teams.py ./ +COPY participants.json ./ + +EXPOSE 8501 + +ENV VOTE_DB=/data/votes.db \ + PARTICIPANTS=/app/participants.json + +CMD ["streamlit", "run", "app.py", \ + "--server.address=0.0.0.0", \ + "--server.port=8501", \ + "--server.headless=true", \ + "--browser.gatherUsageStats=false"] diff --git a/README.md b/README.md index 59e7ed2..4dcf293 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,35 @@ 2. `app.py` 실행 → 참가자가 본인 이름 선택 → 자동 본인 팀 매핑 → 다른 6팀에 3분야 투표 3. 어드민 페이지에서 분야별 1위와 2위 차이만 공개 (하위 표수는 expander 내부) -## 실행 +## 실행 — Docker (권장) ```bash -# 1. 의존성 설치 -pip install -r requirements.txt - -# 2. 팀 배정 (시드 고정 = 재현 가능) +# 1. 팀 배정 (호스트에서 1회, participants.json 생성) python3 assign_teams.py -# → participants.json 저장됨 -# 3. 환경변수 (선택) +# 2. 컨테이너 실행 export ADMIN_TOKEN="강한-토큰-아무거나" -export VOTE_DB="votes.db" -export PARTICIPANTS="participants.json" +docker compose up -d --build -# 4. 홈서버 실행 (외부 접속 허용) +# 로그 +docker compose logs -f + +# 종료 +docker compose down + +# DB 영속 데이터까지 삭제 +docker compose down -v +``` + +- 투표 DB는 docker volume `vote-data`에 영속 → 컨테이너 재시작해도 유지 +- `participants.json`은 호스트→컨테이너 read-only mount → 재배정 시 호스트에서 변경하고 컨테이너만 재시작 + +## 실행 — 로컬 (Docker 없이) + +```bash +pip install -r requirements.txt +python3 assign_teams.py +export ADMIN_TOKEN="강한-토큰-아무거나" streamlit run app.py --server.address 0.0.0.0 --server.port 8501 ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..af9b6d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + vote: + build: . + image: hackathon-vote:latest + container_name: hackathon-vote + ports: + - "${PORT:-8501}:8501" + environment: + ADMIN_TOKEN: ${ADMIN_TOKEN:-change-me} + VOTE_DB: /data/votes.db + PARTICIPANTS: /app/participants.json + volumes: + # 호스트의 participants.json 변경 즉시 반영 (재배정 시) + - ./participants.json:/app/participants.json:ro + # 투표 DB는 호스트에 영속 (컨테이너 재시작해도 유지) + - vote-data:/data + restart: unless-stopped + +volumes: + vote-data: