diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..7bd4c2eaa1e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,67 @@ +FROM node:22-alpine AS jsbuild +ENV PNPM_HOME=/pnpm +ENV PATH=/pnpm:/pnpm/bin:$PATH +ENV CI=1 +ENV TURBO_TELEMETRY_DISABLED=1 +RUN corepack enable +RUN apk add --no-cache libc6-compat +WORKDIR /app +COPY . . +RUN pnpm add -g turbo@2.9.18 +RUN pnpm install --frozen-lockfile +RUN turbo run build --filter=web --filter=admin --filter=live + +FROM python:3.12.10-alpine AS apibuild +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PIP_DISABLE_PIP_VERSION_CHECK=1 +WORKDIR /code +RUN apk add --no-cache libpq libxslt xmlsec ca-certificates openssl libffi-dev +COPY apps/api/requirements.txt ./requirements.txt +COPY apps/api/requirements ./requirements +RUN apk add --no-cache --virtual .build-deps \ + "bash~=5.2" g++ gcc cargo git make postgresql-dev libc-dev linux-headers \ + && pip install -r requirements.txt --compile --no-cache-dir \ + && apk del .build-deps \ + && rm -rf /var/cache/apk/* +COPY apps/api/manage.py manage.py +COPY apps/api/plane plane/ +COPY apps/api/templates templates/ +COPY apps/api/package.json package.json +COPY apps/api/bin ./bin/ +RUN apk add --no-cache "bash~=5.2" && mkdir -p /code/plane/logs && chmod +x ./bin/* + +FROM caddy:2.11.3-alpine AS caddyimg + +FROM python:3.12.10-alpine AS runner +WORKDIR /app +RUN apk add --no-cache libpq libxslt xmlsec ca-certificates openssl nss-tools bash curl + +COPY --from=jsbuild /usr/lib /usr/lib +COPY --from=jsbuild /usr/local/lib /usr/local/lib +COPY --from=jsbuild /usr/local/include /usr/local/include +COPY --from=jsbuild /usr/local/bin /usr/local/bin +COPY --from=apibuild /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/ +COPY --from=apibuild /usr/local/bin/ /usr/local/bin/ + +COPY --from=caddyimg /usr/bin/caddy /usr/bin/caddy + +COPY --from=apibuild /code /app/backend +COPY --from=jsbuild /app/apps/web/build/client /app/web +COPY --from=jsbuild /app/apps/admin/build/client /app/admin + +COPY --from=jsbuild /app/packages /app/live/packages +COPY --from=jsbuild /app/node_modules /app/live/node_modules +COPY --from=jsbuild /app/apps/live/dist /app/live/apps/live/dist +COPY --from=jsbuild /app/apps/live/node_modules /app/live/apps/live/node_modules +COPY --from=jsbuild /app/apps/live/package.json /app/live/apps/live/package.json + +RUN pip install supervisor --no-cache-dir +RUN mkdir -p /etc/supervisor/conf.d /app/logs /app/data /app/proxy + +COPY deploy/railway/Caddyfile /app/proxy/Caddyfile +COPY deploy/railway/supervisor.conf /etc/supervisor/conf.d/supervisor.conf +COPY deploy/railway/start.sh /app/start.sh +RUN chmod +x /app/start.sh + +CMD ["/app/start.sh"] diff --git a/deploy/railway/Caddyfile b/deploy/railway/Caddyfile new file mode 100644 index 00000000000..1f1bec4d919 --- /dev/null +++ b/deploy/railway/Caddyfile @@ -0,0 +1,42 @@ +{ + auto_https off + servers { + max_header_size 25MB + client_ip_headers X-Forwarded-For X-Real-IP + trusted_proxies static 0.0.0.0/0 + } +} + +:{$PORT} { + request_body { + max_size {$FILE_SIZE_LIMIT} + } + + handle /live/* { + reverse_proxy localhost:3005 + } + + handle /api/* { + reverse_proxy localhost:3004 + } + + handle /auth/* { + reverse_proxy localhost:3004 + } + + handle /static/* { + reverse_proxy localhost:3004 + } + + handle_path /god-mode* { + root * /app/admin + try_files {path} {path}/ /index.html + file_server + } + + handle_path /* { + root * /app/web + try_files {path} {path}/ /index.html + file_server + } +} diff --git a/deploy/railway/start.sh b/deploy/railway/start.sh new file mode 100644 index 00000000000..a10a72cb227 --- /dev/null +++ b/deploy/railway/start.sh @@ -0,0 +1,3 @@ +#!/bin/sh +export FILE_SIZE_LIMIT="${FILE_SIZE_LIMIT:-5242880}" +exec /usr/local/bin/supervisord -c /etc/supervisor/conf.d/supervisor.conf diff --git a/deploy/railway/supervisor.conf b/deploy/railway/supervisor.conf new file mode 100644 index 00000000000..83d378aa15b --- /dev/null +++ b/deploy/railway/supervisor.conf @@ -0,0 +1,66 @@ +[supervisord] +user=root +nodaemon=true +logfile=/app/logs/supervisord.log +pidfile=/tmp/supervisord.pid + +[program:migrator] +directory=/app/backend +command=sh -c "./bin/docker-entrypoint-migrator.sh" +autostart=true +autorestart=unexpected +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=10 + +[program:api] +directory=/app/backend +command=sh -c "./bin/docker-entrypoint-api.sh" +autostart=true +autorestart=true +environment=PORT=3004,HOSTNAME=0.0.0.0 +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=15 + +[program:worker] +directory=/app/backend +command=sh -c "./bin/docker-entrypoint-worker.sh" +autostart=true +autorestart=true +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=20 + +[program:beat] +directory=/app/backend +command=sh -c "./bin/docker-entrypoint-beat.sh" +autostart=true +autorestart=true +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=20 + +[program:live] +command=sh -c "node /app/live/apps/live" +autostart=true +autorestart=true +environment=PORT=3005,HOSTNAME=0.0.0.0,API_BASE_URL=http://localhost:3004 +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=20 + +[program:proxy] +directory=/app/proxy +command=sh -c "caddy run --config /app/proxy/Caddyfile" +autostart=true +autorestart=true +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +priority=30