diff --git a/.github/workflows/dev-images.yml b/.github/workflows/dev-images.yml new file mode 100644 index 000000000..f01fb606a --- /dev/null +++ b/.github/workflows/dev-images.yml @@ -0,0 +1,46 @@ +name: Docker Multi-Stage Build on Push to Main + +# The workflow is triggered when a push is made to the main branch +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Check out the repository + - name: Checkout + uses: actions/checkout@v2 + + # Set up Docker + - name: Set up Docker + uses: docker/setup-buildx-action@v1 + + # Log in to GitHub Container Registry + - name: Log in to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build Docker images + - name: Build Docker images + run: | + cp .env.example .env + docker build -f Dockerfile.multi --target api-build -t librechat-dev-api . + docker build -f Dockerfile.multi --target prod-stage -t librechat-dev-client . + docker build -f Dockerfile -t librechat-dev . + + # Tag and push the images to GitHub Container Registry + - name: Tag and push images + run: | + docker tag librechat-dev-api:latest ghcr.io/${{ github.repository_owner }}/librechat-dev-api:${{ github.sha }} + docker push ghcr.io/${{ github.repository_owner }}/librechat-dev-api:${{ github.sha }} + docker tag librechat-dev-client:latest ghcr.io/${{ github.repository_owner }}/librechat-dev-client:${{ github.sha }} + docker push ghcr.io/${{ github.repository_owner }}/librechat-dev-client:${{ github.sha }} + docker tag librechat-dev:latest ghcr.io/${{ github.repository_owner }}/librechat-dev:${{ github.sha }} + docker push ghcr.io/${{ github.repository_owner }}/librechat-dev:${{ github.sha }} diff --git a/Dockerfile.multi b/Dockerfile.multi new file mode 100644 index 000000000..753a5fd7f --- /dev/null +++ b/Dockerfile.multi @@ -0,0 +1,33 @@ +# Build API, Client and Data Provider +FROM node:19-alpine AS base + +WORKDIR /app +COPY config/loader.js ./config/ +RUN npm install dotenv + +WORKDIR /app/api +COPY api/package*.json ./ +COPY api/ ./ +RUN npm install + +# React client build +FROM base AS client-build +WORKDIR /app/client +COPY ./client/ ./ + +RUN npm install +ENV NODE_OPTIONS="--max-old-space-size=2048" +RUN npm run build + +# Node API setup +FROM base AS api-build +COPY --from=client-build /app/client/dist /app/client/dist +EXPOSE 3080 +ENV HOST=0.0.0.0 +CMD ["NODE_ENV=production", "node", "server/index.js"] + +# Nginx setup +FROM nginx:1.21.1-alpine AS prod-stage +COPY --from=client-build /app/client/dist /usr/share/nginx/html +COPY ./client/nginx.conf /etc/nginx/conf.d/default.conf +CMD ["nginx", "-g", "daemon off;"] diff --git a/client/nginx.conf b/client/nginx.conf index 0f5204aae..e7fb06570 100644 --- a/client/nginx.conf +++ b/client/nginx.conf @@ -1,19 +1,13 @@ -events { - worker_connections 1024; -} +server { + listen 80; + server_name localhost; -http { - server { - listen 80; - server_name localhost; + location /api { + proxy_pass http://api:3080/api; + } - location /api { - proxy_pass http://api:3080/api; - } - - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - } + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; } } diff --git a/deploy-compose.yml b/deploy-compose.yml new file mode 100644 index 000000000..f35f3637f --- /dev/null +++ b/deploy-compose.yml @@ -0,0 +1,55 @@ +version: "3.8" +services: + api: + build: + context: . + dockerfile: Dockerfile.multi + target: api-build + container_name: LibreChat-API + ports: + - 9000:3080 + depends_on: + - mongodb + restart: always + extra_hosts: + - "host.docker.internal:host-gateway" + env_file: + - .env + environment: + - HOST=0.0.0.0 + - MONGO_URI=mongodb://mongodb:27017/LibreChat + - MEILI_HOST=http://meilisearch:7700 + - MEILI_HTTP_ADDR=meilisearch:7700 + client: + build: + context: . + dockerfile: Dockerfile.multi + target: prod-stage + ports: + - 80:80 + - 443:443 + depends_on: + - api + restart: always + mongodb: + container_name: chat-mongodb + ports: + - 27018:27017 + image: mongo + restart: always + volumes: + - ./data-node:/data/db + command: mongod --noauth + meilisearch: + container_name: chat-meilisearch + image: getmeili/meilisearch:v1.0 + ports: + - 7700:7700 + env_file: + - .env + environment: + - MEILI_HOST=http://meilisearch:7700 + - MEILI_HTTP_ADDR=meilisearch:7700 + - MEILI_NO_ANALYTICS=true + volumes: + - ./meili_data:/meili_data diff --git a/docs/dev/deploy-compose.yml b/docs/dev/deploy-compose.yml index 303eb5505..0971d8368 100644 --- a/docs/dev/deploy-compose.yml +++ b/docs/dev/deploy-compose.yml @@ -1,46 +1,30 @@ -version: "3.4" - +version: "3.8" services: - client: - image: nginx:latest - restart: always - ports: - - 80:80 - - 443:443 - volumes: - - ../../client/nginx.conf:/etc/nginx/nginx.conf - - /app/client/node_modules - depends_on: - - api api: + image: api container_name: LibreChat ports: - 9000:3080 depends_on: - mongodb - image: ghcr.io/danny-avila/librechat:latest - # image: librechat_deploy - # build: - # context: ../../ - # target: node restart: always extra_hosts: - "host.docker.internal:host-gateway" env_file: - - ../../.env + - .env environment: - HOST=0.0.0.0 - MONGO_URI=mongodb://mongodb:27017/LibreChat - MEILI_HOST=http://meilisearch:7700 - MEILI_HTTP_ADDR=meilisearch:7700 - volumes: - - /app/client/node_modules - - ../../api:/app/api - - ../../.env:/app/.env - - ../../.env.development:/app/.env.development - - ../../.env.production:/app/.env.production - - /app/api/node_modules - - ../../images:/app/client/public/images + client: + image: client + ports: + - 80:80 + - 443:443 + depends_on: + - api + restart: always mongodb: container_name: chat-mongodb ports: @@ -56,7 +40,7 @@ services: ports: - 7700:7700 env_file: - - ../../.env + - .env environment: - MEILI_HOST=http://meilisearch:7700 - MEILI_HTTP_ADDR=meilisearch:7700