# syntax=docker/dockerfile:1.4 FROM calciumion/new-api:latest AS newapi-source FROM justlikemaki/aiclient-2-api:latest AS aiclient-source FROM ghcr.io/quorinex/kiro-go:latest AS kirogo-source # ───────────────────────────────────────────── FROM python:3.11-slim # 1. Системные зависимости + Node.js RUN apt-get update && apt-get install -y curl gnupg supervisor \ && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* # 2. zrok v2 — latest RUN ARCH=$(dpkg --print-architecture) \ && case "$ARCH" in \ amd64) GOARCH=amd64 ;; \ arm64) GOARCH=arm64 ;; \ *) echo "Unsupported arch: $ARCH"; exit 1 ;; \ esac \ && VERSION=$(curl -sSf https://api.github.com/repos/openziti/zrok/releases/latest | grep '"tag_name"' | cut -d'"' -f4) \ && curl -sSfL "https://github.com/openziti/zrok/releases/download/${VERSION}/zrok_${VERSION#v}_linux_${GOARCH}.tar.gz" \ | tar -xz -C /tmp \ && install -o root -g root /tmp/zrok2 /usr/local/bin/zrok2 \ && chmod +x /usr/local/bin/zrok2 # 3. Копируем из готовых образов COPY --from=newapi-source /new-api /usr/local/bin/new-api COPY --from=kirogo-source /app/kiro-go /usr/local/bin/kiro-go COPY --from=aiclient-source /app /app/aiclient2api RUN chmod +x /usr/local/bin/new-api /usr/local/bin/kiro-go # 4. Non-root пользователь RUN useradd -m -u 1000 user # 5. Директории RUN mkdir -p \ /data/kirogo \ /data/newapi \ /data/zrok-home \ /data/supervisor/conf.d \ /data/supervisor/run \ && chown -R user:user /app /data # 6. supervisord.conf RUN echo '[supervisord]' > /data/supervisor/conf.d/supervisord.conf \ && echo 'nodaemon=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'logfile=/dev/stdout' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'pidfile=/data/supervisor/run/supervisord.pid' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'user=root' >> /data/supervisor/conf.d/supervisord.conf \ && echo '' >> /data/supervisor/conf.d/supervisord.conf \ && echo '[program:newapi]' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'command=new-api --port 7860 --log-dir /data/newapi/logs' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'environment=TZ="UTC"' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'directory=/data/newapi' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autostart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autorestart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile=/dev/stdout' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile=/dev/stderr' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo '' >> /data/supervisor/conf.d/supervisord.conf \ && echo '[program:aiclient]' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'command=node /app/aiclient2api/src/core/master.js' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'environment=PORT=3000' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'directory=/app/aiclient2api' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autostart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autorestart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile=/dev/stdout' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile=/dev/stderr' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo '' >> /data/supervisor/conf.d/supervisord.conf \ && echo '[program:kirogo]' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'command=kiro-go' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'environment=PORT=8082' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'directory=/data/kirogo' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autostart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autorestart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile=/dev/stdout' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile=/dev/stderr' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo '' >> /data/supervisor/conf.d/supervisord.conf \ && echo '[program:zrok]' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'command=/app/start_zrok.sh' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autostart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'autorestart=true' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'startsecs=5' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'startretries=3' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile=/dev/stdout' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stdout_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile=/dev/stderr' >> /data/supervisor/conf.d/supervisord.conf \ && echo 'stderr_logfile_maxbytes=0' >> /data/supervisor/conf.d/supervisord.conf RUN echo '#!/bin/bash' > /app/start_zrok.sh && \ echo 'export HOME=/data/zrok-home' >> /app/start_zrok.sh && \ echo 'mkdir -p "$HOME"' >> /app/start_zrok.sh && \ echo 'cd "$HOME"' >> /app/start_zrok.sh && \ echo '# 1. Проверяем статус. Если среда жива — не трогаем её' >> /app/start_zrok.sh && \ echo 'if zrok2 status > /dev/null 2>&1; then' >> /app/start_zrok.sh && \ echo ' echo "[zrok] Environment healthy, reusing existing identity."' >> /app/start_zrok.sh && \ echo 'else' >> /app/start_zrok.sh && \ echo ' echo "[zrok] Environment invalid or missing. Cleaning and Re-enabling..."' >> /app/start_zrok.sh && \ echo ' rm -rf .zrok2' >> /app/start_zrok.sh && \ echo ' if [ -z "$ZROK2_TOKEN" ]; then echo "ERROR: ZROK2_TOKEN not set"; exit 1; fi' >> /app/start_zrok.sh && \ echo ' zrok2 enable "$ZROK2_TOKEN" --headless' >> /app/start_zrok.sh && \ echo 'fi' >> /app/start_zrok.sh && \ echo '# 2. Ждем API приложения' >> /app/start_zrok.sh && \ echo 'until curl -s http://127.0.0.1:7860/ > /dev/null; do sleep 2; done' >> /app/start_zrok.sh && \ echo '# 3. Запускаем шару. Если падает - пробуем снова через 5 секунд' >> /app/start_zrok.sh && \ echo 'while true; do' >> /app/start_zrok.sh && \ echo ' zrok2 share public http://127.0.0.1:7860' >> /app/start_zrok.sh && \ echo ' echo "[zrok] Share exited, restarting in 5s..."' >> /app/start_zrok.sh && \ echo ' sleep 5' >> /app/start_zrok.sh && \ echo 'done' >> /app/start_zrok.sh && \ chmod +x /app/start_zrok.sh # 8. Entrypoint RUN echo '#!/bin/bash' > /app/start.sh \ && echo 'exec /usr/bin/supervisord -c /data/supervisor/conf.d/supervisord.conf' >> /app/start.sh \ && chmod +x /app/start.sh EXPOSE 7860 CMD ["/app/start.sh"]