Docker를 활용하여 Telegram에 ChatGPT Bot 구성 가이드
Docker로 Telegram 봇과 OpenAI 공식 API를 연결하는 구성 가이드입니다. 비공식 access token 방식 대신 Responses API, Bot API, Docker Compose 구조로 정리했습니다.
Docker를 사용해 Telegram 봇과 OpenAI API를 연결하는 방법입니다. 실습은 예전 ChatGPT 웹 세션의 accessToken과 비공식 reverse proxy를 사용하는 방식이었지만, 그런 방식은 안정성, 보안, 약관, 유지보수 측면에서 권장하기 어렵습니다. 지금은 Telegram Bot API와 OpenAI 공식 API 키를 사용해 서버에서 직접 요청하는 구조로 만드는 것이 맞습니다.
구성 구조
Telegram 사용자
-> Telegram Bot API
-> Docker 컨테이너의 bot app
-> OpenAI Responses API
-> bot app
-> Telegram Bot API sendMessage- Telegram token은 BotFather에서 발급합니다.
- OpenAI API key는 서버의 환경 변수로만 주입합니다.
- 브라우저 세션 access token, 비공식 proxy URL, 계정 비밀번호를 사용하지 않습니다.
- 컨테이너 로그에 토큰이나 사용자 민감 정보를 남기지 않습니다.
Telegram BotFather에서 봇 생성
- Telegram에서
@BotFather를 엽니다. /newbot명령을 입력합니다.- 봇 표시 이름과 username을 지정합니다.
- 발급된 bot token을 안전하게 보관합니다.
Telegram 공식 문서에 따르면 bot token은 Bot API에서 봇을 인증하는 문자열이며, BotFather에서 폐기하고 재발급할 수 있습니다. 토큰은 절대 Git, 블로그, 채팅, 로그에 평문으로 올리지 않습니다.
프로젝트 파일 구성
telegram-openai-bot/
├── app.py
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└──.env.env
TELEGRAM_BOT_TOKEN=replace_with_telegram_token
OPENAI_API_KEY=replace_with_openai_api_key
OPENAI_MODEL=gpt-5.4-mini
ALLOWED_USER_IDS=ALLOWED_USER_IDS에 Telegram user id를 쉼표로 넣으면 특정 사용자만 사용할 수 있게 제한할 수 있습니다. 공개 봇으로 열어두면 비용과 스팸 문제가 생길 수 있으므로 처음에는 제한을 두는 편이 좋습니다.
requirements.txt
openai
requestsapp.py
import os
import time
import requests
from openai import OpenAI
TELEGRAM_BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
OPENAI_MODEL = os.environ.get("OPENAI_MODEL", "gpt-5.4-mini")
ALLOWED_USER_IDS = {
int(value)
for value in os.environ.get("ALLOWED_USER_IDS", "").split(",")
if value.strip()
}
telegram_api = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}"
client = OpenAI()
def allowed(user_id: int) -> bool:
return not ALLOWED_USER_IDS or user_id in ALLOWED_USER_IDS
def send_message(chat_id: int, text: str) -> None:
requests.post(
f"{telegram_api}/sendMessage",
json={"chat_id": chat_id, "text": text[:3900]},
timeout=20,
).raise_for_status()
def ask_openai(prompt: str) -> str:
response = client.responses.create(
model=OPENAI_MODEL,
input=prompt,
)
return response.output_text.strip()
def handle_message(message: dict) -> None:
chat_id = message["chat"]["id"]
user_id = message.get("from", {}).get("id")
text = message.get("text", "").strip()
if not text:
return
if user_id is not None and not allowed(user_id):
send_message(chat_id, "허용되지 않은 사용자입니다.")
return
if text in {"/start", "/help"}:
send_message(chat_id, "메시지를 보내면 OpenAI API로 답변합니다.")
return
try:
answer = ask_openai(text)
except Exception:
send_message(chat_id, "처리 중 오류가 발생했습니다. 서버 로그를 확인하세요.")
raise
send_message(chat_id, answer or "빈 응답입니다.")
def main() -> None:
offset = None
while True:
params = {"timeout": 30}
if offset is not None:
params["offset"] = offset
res = requests.get(f"{telegram_api}/getUpdates", params=params, timeout=40)
res.raise_for_status()
data = res.json()
for update in data.get("result", []):
offset = update["update_id"] + 1
message = update.get("message")
if message:
handle_message(message)
time.sleep(1)
if __name__ == "__main__":
main()Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt.
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py.
CMD ["python", "app.py"]docker-compose.yml
services:
telegram-openai-bot:
build:.
restart: unless-stopped
env_file:
-.env실행
docker compose build
docker compose up -d
docker compose logs -f봇에게 /start 또는 /help를 보내고, 일반 메시지를 보내 응답이 돌아오는지 확인합니다.
운영 시 주의사항
- OpenAI API key와 Telegram bot token은
.env로만 주입하고 Git에 올리지 않습니다. - 공개 봇이면 user allowlist, rate limit, 비용 제한을 반드시 둡니다.
- 긴 답변은 Telegram 메시지 길이 제한에 맞게 분할해야 합니다.
- 운영형 서비스는 long polling 대신 webhook과 HTTPS endpoint를 사용할 수 있습니다.
- 대화 이력을 저장할 경우 개인정보와 보관 기간을 명확히 정합니다.