diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..17bdce7 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,35 @@ +name: Deploy Backend (Blue-Green) + +on: + workflow_dispatch: + inputs: + image_tag: + description: '镜像tag,留空则使用commit短哈希' + required: false + +jobs: + deploy: + runs-on: deploy-host + steps: + - uses: actions/checkout@v4 + + - name: 确定镜像tag + id: vars + run: | + TAG="${{ github.event.inputs.image_tag }}" + [ -z "$TAG" ] && TAG=$(git rev-parse --short HEAD) + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: 构建镜像(从本仓库源码编译,非下载官方release) + run: docker build -t im-server:${{ steps.vars.outputs.tag }} -f docker/tinode/Dockerfile.build . + + - name: 蓝绿部署 + env: + MYSQL_DSN: ${{ secrets.MYSQL_DSN }} + REDIS_ADDR: ${{ secrets.REDIS_ADDR }} + REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }} + API_KEY_SALT: ${{ secrets.API_KEY_SALT }} + AUTH_TOKEN_KEY: ${{ secrets.AUTH_TOKEN_KEY }} + UID_ENCRYPTION_KEY: ${{ secrets.UID_ENCRYPTION_KEY }} + run: | + IMAGE=im-server:${{ steps.vars.outputs.tag }} /opt/apps/im-server/deploy.sh diff --git a/docker/tinode/Dockerfile.build b/docker/tinode/Dockerfile.build new file mode 100644 index 0000000..249c75d --- /dev/null +++ b/docker/tinode/Dockerfile.build @@ -0,0 +1,83 @@ +# Builds the Tinode server + tinode-db + tenant-db-migration tools from THIS +# repo's local source, instead of downloading a pre-built release from GitHub +# (the upstream docker/tinode/Dockerfile does that, so it never picks up the +# tenant/workbench/etc. customizations that live only in this repo's source). + +# ---- Stage 1: compile from local source ---- +FROM golang:1.26-alpine AS build + +RUN apk add --no-cache git +WORKDIR /src +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -tags mysql -o /out/tinode ./server +RUN CGO_ENABLED=0 go build -tags mysql -o /out/init-db ./tinode-db +# scripts/apply_hotgo_tenant_db.go is `//go:build ignore`-tagged (a standalone +# migration script, not part of any package) - build it by exact file path. +RUN CGO_ENABLED=0 go build -o /out/apply-hotgo-tenant-db ./scripts/apply_hotgo_tenant_db.go + +# ---- Stage 2: runtime image ---- +FROM alpine:3.22 + +LABEL maintainer="118im" +LABEL name="ImServer" + +# Runtime options (same names/semantics as upstream docker/tinode/Dockerfile). +ENV WAIT_FOR= +ENV RESET_DB=false +ENV UPGRADE_DB=false +ENV NO_DB_INIT=false +# Empty by default: do not load Tinode's canned demo users into a real deployment. +# Override explicitly if sample data is ever wanted. +ENV SAMPLE_DATA= +ENV DEFAULT_COUNTRY_CODE=US + +# DB connection is provided at deploy time via secret-backed env var. No default value. +ENV MYSQL_DSN= +ENV STORE_USE_ADAPTER=mysql + +# Tenant registry lives in the hotgo database (shared with im_manager); tenant +# DB routing resolves to the same tinode DB for the seeded "default" tenant. +ENV TENANT_REGISTRY_DB=hotgo + +ENV MEDIA_HANDLER=fs +ENV FS_CORS_ORIGINS='["*"]' +ENV AWS_CORS_ORIGINS='["*"]' +ENV SMTP_HOST_URL='http://localhost:6060' +ENV TLS_ENABLED=false +ENV FCM_PUSH_ENABLED=false +ENV FCM_INCLUDE_ANDROID_NOTIFICATION=true +ENV TNPG_PUSH_ENABLED=false +ENV WEBRTC_ENABLED=false +ENV SERVER_STATUS_PATH='' +ENV ACC_GC_ENABLED=false +ENV PLUGIN_PYTHON_CHAT_BOT_ENABLED=false + +# Secrets: intentionally NO default values. Must be injected at deploy time. +# An empty/missing value fails loudly at startup rather than silently falling +# back to Tinode's publicly-known demo keys. +ENV API_KEY_SALT= +ENV AUTH_TOKEN_KEY= +ENV UID_ENCRYPTION_KEY= + +RUN apk add --no-cache ca-certificates bash grep + +WORKDIR /opt/tinode + +COPY docker/tinode/config.template . +COPY docker/tinode/entrypoint.sh . +COPY tinode-db/credentials.sh . +COPY --from=build /out/tinode . +COPY --from=build /out/init-db . +COPY --from=build /out/apply-hotgo-tenant-db . + +RUN mkdir -p /botdata static \ + && chmod +x entrypoint.sh credentials.sh tinode init-db apply-hotgo-tenant-db + +HEALTHCHECK --interval=1m --timeout=3s --start-period=30s \ + CMD nc -z localhost 6060 || exit 1 + +ENTRYPOINT ["./entrypoint.sh"] + +EXPOSE 6060 16060 diff --git a/docker/tinode/config.template b/docker/tinode/config.template index b01ea70..4030d93 100644 --- a/docker/tinode/config.template +++ b/docker/tinode/config.template @@ -75,7 +75,13 @@ "adapters": { "mysql": { "database": "tinode", - "dsn": "$MYSQL_DSN" + "dsn": "$MYSQL_DSN", + "max_open_conns": 64, + "max_idle_conns": 64, + "conn_max_lifetime": 60, + "sql_timeout": 10, + "tenant_registry_db": "$TENANT_REGISTRY_DB", + "tenant_db_routing": true }, "postgres": { "database": "tinode", diff --git a/docker/tinode/entrypoint.sh b/docker/tinode/entrypoint.sh index 4f7b787..00856f5 100644 --- a/docker/tinode/entrypoint.sh +++ b/docker/tinode/entrypoint.sh @@ -127,6 +127,15 @@ if [ $? -ne 0 ]; then exit 1 fi +# Create/upgrade the hotgo tenant registry and the workbench/org/meetings/ +# reports/mailbox/etc. tables that init-db above does not manage. Idempotent +# (IF NOT EXISTS / ON DUPLICATE KEY UPDATE throughout), safe to run every start. +IM_MYSQL_DSN="${MYSQL_DSN}" ./apply-hotgo-tenant-db +if [ $? -ne 0 ]; then + echo "./apply-hotgo-tenant-db failed. Quitting." + exit 1 +fi + # If sample data was provided, try to find Tino password. if [ ! -z "$SAMPLE_DATA" ] ; then grep "usr;tino;" $init_stdout > /botdata/tino-password