인프라 / Self-hosted AI 플랫폼
Dify를 v1.9.2에서 v1.13.3으로 업그레이드할 때의 진행 방법과 주의점 #
Self-hosted Dify의 업그레이드는 기존 docker-compose.yaml에 커스텀 조정이 많이 들어가 있을수록 어려워집니다.
이번에는 Docker Compose로 운영 중인 Dify를 v1.9.2에서 v1.13.3으로 업데이트할 때의 진행 방법을,
공개용으로 민감 정보를 마스킹한 후 정리했습니다.
단순한 image tag 업데이트가 아니라, 공식 compose를 기반으로 교체한 후 환경 의존 설정을 복원하는 방식이 가장 안전했습니다.
이 글에 포함된 도메인, 이메일 주소, API key, 인증 정보, 인증서 경로, 호스트명, 볼륨 구성의 일부는 실제 환경이 특정되지 않도록 마스킹하거나 추상화했습니다.
왜 “image tag만 업데이트”는 위험한가 #
버전 차이가 클 경우, Dify는 단순한 컨테이너 이미지 업데이트만으로는 대응할 수 없는 경우가 있습니다. 실제로 차이를 비교해보면, 이번 업데이트에서는 다음과 같은 포인트가 있었습니다.
서비스 구성의 변화 #
새로운 공식 compose에서는 DB 서비스명이 db가 아닌 db_postgres를 전제로 하고 있거나,
worker_beat나 권한 초기화 처리가 포함되어 있는 등 구성 자체에 차이가 있었습니다.
주변 컴포넌트의 업데이트 #
Plugin Daemon, Sandbox, Weaviate 등 Dify 본체 이외의 주변 컴포넌트도 업데이트 대상입니다. 기존 설정 파일 그대로 사용하면 시작은 되지만 일부 기능만 고장나는 상태가 발생하기 쉽습니다.
독자적인 커스터마이징의 존재 #
오래 운영한 환경에서는 인증서 마운트, 독자적인 환경 변수, 플러그인 관련 설정 등이 추가되기 마련입니다. 이러한 것들은 공식 compose에 자동으로 반영되지 않으므로 다시 적용해야 합니다.
설정 파일의 드리프트 #
기존 compose를 직접 계속 편집하다 보면 어떤 설정이 공식 기본값이고 어떤 것이 자사 고유 설정인지 파악하기 어려워집니다. 이런 상태에서 일괄 업데이트는 복구하기 어려운 장애의 원인이 됩니다.
기존 compose를 연장하기보다는, 공식 v1.13.3 compose를 기반으로 교체하고 필요한 차이점만 복원하는 것이 업데이트 후의 가독성과 유지보수성도 높았습니다.
이번 업그레이드 방침 #
- 먼저
docker/volumes를 포함해 전체 백업을 수행한다 - 공식 v1.13.3을 별도 디렉터리에 가져와서 차이의 기준을 만든다
docker-compose.yaml은 공식 버전으로 교체한다.env와 TLS 마운트 등 환경 의존 설정만 복원한다- Sandbox 설정 파일을 새로운 전제에 맞춘다
- 시작 전에
docker compose config로 구문 검증한다 - 시작 후에는 UI뿐만 아니라 Knowledge / Plugin / Code 실행까지 확인한다
1. 먼저 백업을 수행한다 #
가장 중요한 것은 업데이트 전 compose와 volumes를 복원할 수 있는 상태로 만들어두는 것입니다. 특히 Weaviate나 PostgreSQL을 사용하고 있는 경우, 업데이트 후 롤백하고 싶은 상황은 충분히 발생할 수 있습니다.
cd /srv/dify/docker
TS=$(date +%Y%m%d%H%M%S)
cp -a docker-compose.yaml "docker-compose.yaml.${TS}.bak"
cp -a .env ".env.${TS}.bak"
[ -f volumes/sandbox/conf/config.yaml ] && \
cp -a volumes/sandbox/conf/config.yaml "volumes/sandbox/conf/config.yaml.${TS}.bak"
tar -czf "/root/dify-volumes-${TS}.tgz" volumes
경로는 어디까지나 공개용 예시입니다. 실제 운영 시에는 자사 환경의 배치에 맞춰 읽어주시기 바랍니다.
2. 공식 v1.13.3 가져오기 #
기존 디렉터리를 직접 수정하지 않고, 비교용으로 별도 디렉터리에 가져옵니다. 이 시점에서 기존 환경의 파일을 덮어쓰지 않는 것이 포인트입니다.
cd /tmp
rm -rf dify-1.13.3
git clone --branch 1.13.3 https://github.com/langgenius/dify.git dify-1.13.3
가져온 후에는 최소한 docker-compose.yaml, .env.example,
volumes/sandbox/conf/config.yaml.example 이 3개를 비교하면,
이번 업데이트에서 무엇을 반영해야 하는지 파악하기 쉬워집니다.
3. compose는 공식 버전으로 교체 #
이번에는 기존 compose를 계속 수정하기보다는, 공식 v1.13.3을 그대로 기반으로 삼는 구성을 택했습니다. 이를 통해 향후 업그레이드 시에도 “공식과의 차이점”을 추적하기 쉬워집니다.
cp /tmp/dify-1.13.3/docker/docker-compose.yaml /srv/dify/docker/docker-compose.yaml
cp /tmp/dify-1.13.3/docker/.env.example /srv/dify/docker/.env.example.1.13.3
cp /tmp/dify-1.13.3/docker/volumes/sandbox/conf/config.yaml.example \
/srv/dify/docker/volumes/sandbox/conf/config.yaml.example.1.13.3
여기서 중요한 것은, compose를 교체한 직후 바로 시작하지 않는 것입니다. 먼저
.env, 인증서 마운트, Sandbox 설정 등 환경 의존적인 값을 복원한 후 시작합니다.
4. 환경 의존 설정 복원 #
공식 compose를 채택한 후, 실제 운영에 필요한 설정만을 overlay하는 이미지로 복원합니다. 이번 환경에서는 주로 다음과 같은 항목이 중요했습니다.
반드시 확인해야 할 항목 #
DB_HOST가db_postgres로 되어 있는지- Weaviate의 API key와 gRPC 엔드포인트
- NGINX의 서버 이름과 인증서 경로
- 공개 URL과 내부용 files URL
- Plugin Daemon 관련 timeout
공개 시 숨겨야 할 항목 #
- 도메인 이름
- 이메일 주소
- API key / 시크릿
- 인증서의 실제 파일명
- 사내용 볼륨 구성이나 호스트명
DB_TYPE=postgresql
DB_HOST=db_postgres
DB_PORT=5432
VECTOR_STORE=weaviate
WEAVIATE_ENDPOINT=http://weaviate:8080
WEAVIATE_GRPC_ENDPOINT=grpc://weaviate:50051
WEAVIATE_API_KEY=<YOUR_WEAVIATE_API_KEY>
NGINX_SERVER_NAME=<YOUR_DOMAIN>
NGINX_HTTPS_ENABLED=true
NGINX_SSL_CERT_FILENAME=live/<YOUR_DOMAIN>/fullchain.pem
NGINX_SSL_CERT_KEY_FILENAME=live/<YOUR_DOMAIN>/privkey.pem
FILES_URL=https://<YOUR_DOMAIN>
INTERNAL_FILES_URL=http://api:5001
PLUGIN_MAX_EXECUTION_TIMEOUT=1800
포인트는, 기존 환경 변수를 모두 이어받는 것이 아니라, 새로운 공식 .env.example을 기준으로 필요한 항목만 재설정하는 것입니다.
특히 DB_HOST와 Weaviate 관련 설정은 기존 compose를 그대로 유용하면 시작 후 오류를 일으키기 쉬운 부분이었습니다.
5. NGINX의 인증서 마운트 복원 #
공식 compose로 교체한 후, 그대로 두면 TLS 관련 마운트 구성이 자사 환경과 어긋날 수 있습니다. 이번에는 인증서를 호스트 측의 기존 디렉터리에서 관리하고 있었기 때문에, NGINX 서비스만 마운트 정의를 재조정했습니다.
services:
nginx:
volumes:
- ./nginx/ssl:/etc/ssl
- /path/to/external/letsencrypt:/etc/letsencrypt
인증서를 Certbot 컨테이너에서 완결시키는 구성이라면, 그대로 공식 마운트로 문제없는 경우도 있습니다. 단, 외부 경로 관리를 하고 있는 경우는 교체 후 반드시 재검토하는 것이 안전합니다.
6. Sandbox 설정 업데이트 #
놓치기 쉬운 것이 Sandbox 측의 설정입니다.
버전이 올라가면 Python / Node.js의 경로 전제가 바뀔 수 있으며,
기존의 config.yaml은 자동 업데이트되지 않습니다.
app:
port: 8194
debug: true
key: dify-sandbox
python_path: /opt/python/bin/python3
nodejs_path: /usr/local/bin/node
오래된
config.yaml을 그대로 사용하면, UI는 기동되어 있어도 Code 실행계만 실패하는 상태가 되기 쉽습니다.
업데이트 후에는 Sandbox를 독립적으로 확인하는 것을 권장합니다.
7. 기동 전 구문 체크, 기동 후 로그 확인 #
compose를 교체한 후에는 먼저 구문 체크를 통과시킵니다. 그 다음 이미지를 가져오고, 서비스를 기동합니다.
docker compose --profile weaviate --profile postgresql config > /tmp/dify.check.yaml
docker compose --profile weaviate --profile postgresql pull
docker compose --profile weaviate --profile postgresql up -d --remove-orphans
docker compose ps
docker compose logs --tail=120 api worker worker_beat plugin_daemon sandbox weaviate nginx
업데이트 작업에서는 기동 가능 여부만 보고 안심하지 않는 것이 중요합니다.
특히 api, worker, worker_beat, plugin_daemon, sandbox의 로그는
기능 불량의 조기 발견에 도움이 됩니다.
8. 업데이트 후 확인 체크리스트 #
- 관리 화면에 정상 로그인할 수 있다
- 기존 앱의 채팅 응답이 정상적으로 반환된다
- Knowledge의 검색·재인덱싱이 통과된다
- Code 노드와 Sandbox 실행이 성공한다
- Plugin의 활성화·실행이 성공한다
- HTTPS 배포와 인증서 참조에 문제가 없다
이번과 같이 주변 컴포넌트의 차이가 큰 업데이트에서는, UI가 열리는 것과 실제 운용에 필요한 기능이 모두 작동하는 것은 별개의 문제입니다. 사용 중인 주요 기능에 따른 확인 항목을 처음부터 정해두면 롤백 판단도 하기 쉬워집니다.
주의사항 정리 #
DB_HOST 불일치 #
새로운 공식 compose에 맞추지 않으면 API나 Plugin Daemon이 DB에 접속하지 못해 중단됩니다.
db와 db_postgres의 차이는 특히 놓치기 쉬운 포인트였습니다.
worker_beat 간과 #
메인 API나 worker만 확인하면 정기 작업계 불량을 놓칠 수 있습니다. 업데이트 후에는 보조 서비스까지 포함하여 확인하는 것이 안전합니다.
TLS 마운트 복원 누락 #
compose를 공식 버전으로 교체하면 인증서 경로가 자사 환경의 전제에서 벗어날 수 있습니다. HTTP는 통하는데 HTTPS만 실패하는 증상으로 이어집니다.
오래된 Sandbox 설정 계속 사용 #
관리 화면이 열리므로 놓치기 쉽지만, Code 실행계 장애로 직결됩니다. UI와 Sandbox를 각각 별도로 검증하는 것이 포인트입니다.
이번에 배운 점 #
오랫동안 운영한 Dify 환경일수록, 업그레이드 시 영향을 미치는 것은 “버전 번호”보다 “축적된 독자적 차이”입니다. 이번에 다시 느낀 것은, 공식 compose를 가능한 건드리지 않고, 환경 종속 설정은 overlay로 관리하는 편이 그 후의 업그레이드와 장애 대응도 압도적으로 편하다는 것이었습니다.
현재 환경이 구버전 그대로 안정적으로 가동되고 있다면, 업데이트 전에 다음 3가지만이라도 정리해두면 훨씬 진행하기 쉬워집니다.
- 공식 유래의 설정과 자사 고유 설정을 구분하여 정리한다
- 롤백 가능한 백업을 반드시 취득한다
- 기동 확인이 아닌, 주요 기능의 확인 항목을 미리 정해둔다
Dify의 큰 버전 업데이트는 “오래된 compose의 연명”보다 “새로운 공식 compose로의 재베이스”로 진행하는 편이 결과적으로 안전하고, 나중에 다시 봐도 이해하기 쉬운 구성이 됩니다.