Dockerfile 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # ========================================================
  2. # Stage: Frontend (Vite)
  3. # ========================================================
  4. # web/dist/ is .gitignored and embedded into the Go binary via
  5. # //go:embed all:dist in web/web.go, so the SPA bundle MUST be built
  6. # before the Go compile step. We build it in its own stage so the
  7. # Go builder image doesn't need Node installed.
  8. FROM node:22-alpine AS frontend
  9. WORKDIR /src/frontend
  10. COPY frontend/package.json frontend/package-lock.json ./
  11. RUN npm ci
  12. COPY frontend/ ./
  13. RUN npm run build
  14. # Vite outDir is set to ../web/dist (see frontend/vite.config.js), so
  15. # the bundle lands at /src/web/dist — that's what we copy into the
  16. # next stage.
  17. # ========================================================
  18. # Stage: Builder
  19. # ========================================================
  20. FROM golang:1.26-alpine AS builder
  21. WORKDIR /app
  22. ARG TARGETARCH
  23. RUN apk --no-cache --update add \
  24. build-base \
  25. gcc \
  26. curl \
  27. unzip
  28. COPY . .
  29. COPY --from=frontend /src/web/dist ./web/dist
  30. ENV CGO_ENABLED=1
  31. ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE"
  32. RUN go build -ldflags "-w -s" -o build/x-ui main.go
  33. RUN ./DockerInit.sh "$TARGETARCH"
  34. # ========================================================
  35. # Stage: Final Image of 3x-ui
  36. # ========================================================
  37. FROM alpine
  38. ENV TZ=Asia/Tehran
  39. WORKDIR /app
  40. RUN apk add --no-cache --update \
  41. ca-certificates \
  42. tzdata \
  43. fail2ban \
  44. bash \
  45. curl \
  46. openssl
  47. COPY --from=builder /app/build/ /app/
  48. COPY --from=builder /app/DockerEntrypoint.sh /app/
  49. COPY --from=builder /app/x-ui.sh /usr/bin/x-ui
  50. # Configure fail2ban
  51. RUN rm -f /etc/fail2ban/jail.d/alpine-ssh.conf \
  52. && cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local \
  53. && sed -i "s/^\[ssh\]$/&\nenabled = false/" /etc/fail2ban/jail.local \
  54. && sed -i "s/^\[sshd\]$/&\nenabled = false/" /etc/fail2ban/jail.local \
  55. && sed -i "s/#allowipv6 = auto/allowipv6 = auto/g" /etc/fail2ban/fail2ban.conf
  56. RUN chmod +x \
  57. /app/DockerEntrypoint.sh \
  58. /app/x-ui \
  59. /usr/bin/x-ui
  60. ENV XUI_ENABLE_FAIL2BAN="true"
  61. EXPOSE 2053
  62. VOLUME [ "/etc/x-ui" ]
  63. CMD [ "./x-ui" ]
  64. ENTRYPOINT [ "/app/DockerEntrypoint.sh" ]