diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..f04f41d98c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +Dockerfile +.dockerignore +node_modules +npm-debug.log +.next +.git +scripts +docs +.github +*.md diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000000..9751f0de36 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,45 @@ +name: Publish Docker image + +on: + workflow_dispatch: + release: + types: [published] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_REGISTRY_USER }} + password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: lobehub/lobe-chat + tags: | + type=raw,value=latest + type=ref,event=tag + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..6998710377 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +FROM node:20-slim AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +## Install dependencies only when needed +FROM base AS builder +WORKDIR /app + +COPY package.json ./ + +RUN pnpm i -g bun +# If you want to build docker in China +#RUN npm config set registry https://registry.npmmirror.com/ +RUN bun i + +COPY . . +RUN pnpm run build:docker # run build standalone for docker version + +## Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +# set hostname to localhost +ENV HOSTNAME "0.0.0.0" + +ENV ACCESS_CODE "lobe66" +ENV OPENAI_API_KEY "" +ENV OPENAI_PROXY_URL "" + +CMD ["node", "server.js"] diff --git a/next.config.mjs b/next.config.mjs index 1576788a40..c1d56653f7 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -2,6 +2,7 @@ import analyzer from '@next/bundle-analyzer'; import nextPWA from 'next-pwa'; const isProd = process.env.NODE_ENV === 'production'; +const buildWithDocker = process.env.DOCKER === 'true'; const withBundleAnalyzer = analyzer({ enabled: process.env.ANALYZE === 'true', @@ -38,6 +39,8 @@ const nextConfig = { AGENTS_INDEX_URL: process.env.AGENTS_INDEX_URL, PLUGINS_INDEX_URL: process.env.PLUGINS_INDEX_URL, }, + + output: buildWithDocker ? 'standalone' : undefined, }; export default isProd ? withBundleAnalyzer(withPWA(nextConfig)) : nextConfig; diff --git a/package.json b/package.json index d8582aa5bd..8aead262b8 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "scripts": { "build": "next build", "build:analyze": "ANALYZE=true next build", + "build:docker": "DOCKER=true next build", "dev": "next dev -p 3010", "i18n": "npm run i18n:workflow && lobe-i18n", "i18n:workflow": "ts-node --project ./tsconfig.json scripts/i18nWorkflow/index.ts",