# Single-image build for goChat. # # Stage 1 builds the frontend, stage 2 builds the Go backend, and the runtime # stage (nginx) serves the frontend statically while reverse proxying /api to # the backend, which runs in the same container on loopback. # --- frontend build ---------------------------------------------------------- FROM node:22-alpine AS frontend WORKDIR /app COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci COPY frontend/ ./ RUN npm run build # --- backend build ----------------------------------------------------------- FROM golang:1.26-alpine AS backend WORKDIR /src # go-sqlite3 is a cgo package, so a C toolchain is required. RUN apk add --no-cache gcc musl-dev COPY backend/go.mod backend/go.sum ./ RUN go mod download COPY backend/ ./ RUN go build -o /out/server ./cmd/server # --- runtime ----------------------------------------------------------------- FROM nginx:1.27-alpine # supervisord runs nginx and the backend together; gettext provides envsubst, # which the nginx image already uses for /etc/nginx/templates. ca-certificates # and tzdata are needed by the Go server (TLS to Jitsi, time zones). RUN apk add --no-cache supervisor ca-certificates tzdata COPY --from=backend /out/server /app/server COPY --from=frontend /app/dist /usr/share/nginx/html COPY docker/nginx.conf /etc/nginx/templates/default.conf.template COPY docker/supervisord.conf /etc/supervisord.conf COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh && mkdir -p /data # Defaults. docker-compose overrides ADDR/DB_PATH/BACKEND_* explicitly and can # override any of these via `environment`/`env_file`. COOKIE_SECURE defaults to # true so the app is safe behind an SSL-terminating reverse proxy; set it to # false only for plain-HTTP local use. ENV ADDR=127.0.0.1:8080 \ DB_PATH=/data/gochat.db \ BACKEND_HOST=127.0.0.1 \ BACKEND_PORT=8080 \ COOKIE_SECURE=true VOLUME ["/data"] EXPOSE 80 ENTRYPOINT ["/entrypoint.sh"]