diff --git a/.gitignore b/.gitignore index 533f68a527..a166dcac13 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,9 @@ ## compressed **/*.tgz + +.gitcommands +.gitconfig +.bash-helpers +.gitcommands +.gitconfig diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e485cd3ef3..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -# Build local monorepo image -# docker build --no-cache -t flowise . - -# Run image -# docker run -d -p 3000:3000 flowise - -FROM node:18-alpine -RUN apk add --update libc6-compat python3 make g++ -# needed for pdfjs-dist -RUN apk add --no-cache build-base cairo-dev pango-dev - -# Install Chromium -RUN apk add --no-cache chromium - -ENV PUPPETEER_SKIP_DOWNLOAD=true -ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser - -WORKDIR /usr/src/packages - -# Copy root package.json and lockfile -COPY package.json yarn.loc[k] ./ - -# Copy components package.json -COPY packages/components/package.json ./packages/components/package.json - -# Copy ui package.json -COPY packages/ui/package.json ./packages/ui/package.json - -# Copy server package.json -COPY packages/server/package.json ./packages/server/package.json - -RUN yarn install - -# Copy app source -COPY . . - -RUN yarn build - -EXPOSE 3000 - -CMD [ "yarn", "start" ] diff --git a/README.md b/README.md index 25026237f7..4f8c56a83e 100644 --- a/README.md +++ b/README.md @@ -40,30 +40,9 @@ Download and Install [NodeJS](https://nodejs.org/en/download) >= 18.15.0 ## 🐳 Docker -### Docker Compose +**Go here for [Instructions](https://github.com/FlowiseAI/Flowise/blob/main/docker/README.md)** -1. Go to `docker` folder at the root of the project -2. Copy `.env.example` file, paste it into the same location, and rename to `.env` -3. `docker-compose up -d` -4. Open [http://localhost:3000](http://localhost:3000) -5. You can bring the containers down by `docker-compose stop` - -### Docker Image - -1. Build the image locally: - ```bash - docker build --no-cache -t flowise . - ``` -2. Run image: - - ```bash - docker run -d --name flowise -p 3000:3000 flowise - ``` - -3. Stop image: - ```bash - docker stop flowise - ``` + ## 👨‍💻 Developers @@ -88,31 +67,32 @@ Flowise has 3 different modules in a single mono repository. git clone https://github.com/FlowiseAI/Flowise.git ``` -2. Go into repository folder +2. Use Docker for a better Dev flow (see Docker [Instructions](https://github.com/FlowiseAI/Flowise/blob/main/docker/README.md), and skip the other steps) or Manually: + - Go into repository folder - ```bash - cd Flowise - ``` + ```bash + cd Flowise + ``` -3. Install all dependencies of all modules: + - Install all dependencies of all modules: - ```bash - yarn install - ``` + ```bash + yarn install + ``` -4. Build all the code: + - Build all the code: - ```bash - yarn build - ``` + ```bash + yarn build + ``` -5. Start the app: + - Start the app: - ```bash - yarn start - ``` + ```bash + yarn start + ``` - You can now access the app on [http://localhost:3000](http://localhost:3000) + - You can now access the app on [http://localhost:3000](http://localhost:3000) 6. For development build: diff --git a/docker/.env.example b/docker/.env.example index 967a1ab6b3..58887aa00e 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -1,11 +1,22 @@ -PORT=3000 -DATABASE_PATH=/root/.flowise -APIKEY_PATH=/root/.flowise -SECRETKEY_PATH=/root/.flowise -LOG_PATH=/root/.flowise/logs +#------------------------------------ +#-->Docker/codespace +# Avoids the use of 'root' for better compatibility and adherence +DOCKER_USER=flowise +DOCKER_USER_UID=1000 +DOCKER_USER_DIR="/home/${DOCKER_USER}" +DOCKER_WORKSPACE_DIR="${DOCKER_USER_DIR}" +#------------------------------------ +#-->Standard settings +PORT=3000 +APIKEY_PATH="${DOCKER_USER_DIR}/.flowise" +SECRETKEY_PATH="${DOCKER_USER_DIR}/.flowise" +LOG_PATH="${DOCKER_USER_DIR}/.flowise/logs" +DATABASE_PATH="${DOCKER_USER_DIR}/.flowise" # NUMBER_OF_PROXIES= 1 +#------------------------------------ +#-->DB [uncomment when in use] # DATABASE_TYPE=postgres # DATABASE_PORT="" # DATABASE_HOST="" @@ -13,6 +24,8 @@ LOG_PATH=/root/.flowise/logs # DATABASE_USER="" # DATABASE_PASSWORD="" +#------------------------------------ +#-->LangChain [uncomment when in use] # FLOWISE_USERNAME=user # FLOWISE_PASSWORD=1234 # FLOWISE_SECRETKEY_OVERWRITE=myencryptionkey @@ -21,7 +34,12 @@ LOG_PATH=/root/.flowise/logs # TOOL_FUNCTION_BUILTIN_DEP=crypto,fs # TOOL_FUNCTION_EXTERNAL_DEP=moment,lodash +#------------------------------------ +#-->LangChain [uncomment when in use] # LANGCHAIN_TRACING_V2=true # LANGCHAIN_ENDPOINT=https://api.smith.langchain.com # LANGCHAIN_API_KEY=your_api_key -# LANGCHAIN_PROJECT=your_project \ No newline at end of file +# LANGCHAIN_PROJECT=your_project + +# --> Note: +# --> when uncommenting the above, make sure to also uncomment the following in the docker-compose file diff --git a/docker/Dockerfile b/docker/Dockerfile index 1ad1bf5ee2..a9db3e1b11 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,21 +1,42 @@ -FROM node:18-alpine +# @knighttower - https://knighttower.io -USER root +# Use Node.js official base image +FROM node:20.2.0-slim -RUN apk add --no-cache git -RUN apk add --no-cache python3 py3-pip make g++ -# needed for pdfjs-dist -RUN apk add --no-cache build-base cairo-dev pango-dev +ARG DOCKER_WORKSPACE_DIR -# Install Chromium -RUN apk add --no-cache chromium +# Set environment variables +ENV PUPPETEER_SKIP_DOWNLOAD=true \ + PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser -ENV PUPPETEER_SKIP_DOWNLOAD=true -ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser +# Set working directory +WORKDIR $DOCKER_WORKSPACE_DIR -# You can install a specific version like: flowise@1.0.0 -RUN npm install -g flowise +# Install necessary packages to extend the dev environment and allow other integrations or manipulations +RUN apt-get update -y \ + && apt-get install -y --no-install-recommends \ + curl \ + build-essential \ + python3 \ + python3-pip \ + make \ + g++ \ + git \ + libcairo2-dev \ + libpango1.0-dev \ + chromium \ + bash \ + wget \ + nano \ + gcc \ + zip \ + unzip \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* -WORKDIR /data +# Ensure .bashrc exists for root and is executable +RUN touch ~/.bashrc && chmod +x ~/.bashrc +SHELL ["/bin/bash", "--login", "-c"] -CMD "flowise" \ No newline at end of file +# Expose port 3000 +EXPOSE 3000 diff --git a/docker/README.md b/docker/README.md index d3ad1c1970..d8303ca07a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,35 +1,38 @@ -# Flowise Docker Hub Image +# Docker User Guide -Starts Flowise from [DockerHub Image](https://hub.docker.com/repository/docker/flowiseai/flowise/general) +## 📦 Prerequisites +- NPM or CLI console that supports bash -## Usage +## 🌱 Env Variables +The Autosetup will copy the ENV file automatically, but if you want to customize the configuration, you can copy the `.env.example` file to `.env` and change the values. Otherwise, just skip this step. -1. Create `.env` file and specify the `PORT` (refer to `.env.example`) -2. `docker-compose up -d` -3. Open [http://localhost:3000](http://localhost:3000) -4. You can bring the containers down by `docker-compose stop` +Flowise also support different environment variables to configure your instance. Read [more](https://docs.flowiseai.com/environment-variables) + +## 🚀 Quick Start + +#### Method A: +From the root dir, run the following command: +`npm run docker:start` + +#### Method B: +From the root dir, run the following command: +`sh ./docker/start` + +Open [http://localhost:3000](http://localhost:3000) + +**Note**: Yarn install, yarn build and start, are automatically executed when you run the start script. If they are not or you need to add other packages or execute them manually, enter the container and run them from there. Do not run these commands outside of the container because they will not work or bring issues with docker performance. +Use: `npm run docker:cli` it will get you inside the docker container bash. ## 🔒 Authentication -1. Create `.env` file and specify the `PORT`, `FLOWISE_USERNAME`, and `FLOWISE_PASSWORD` (refer to `.env.example`) -2. Pass `FLOWISE_USERNAME` and `FLOWISE_PASSWORD` to the `docker-compose.yml` file: +1. Pass `FLOWISE_USERNAME` and `FLOWISE_PASSWORD` to the `docker-compose.yml` file: ``` environment: - PORT=${PORT} - FLOWISE_USERNAME=${FLOWISE_USERNAME} - FLOWISE_PASSWORD=${FLOWISE_PASSWORD} ``` -3. `docker-compose up -d` -4. Open [http://localhost:3000](http://localhost:3000) -5. You can bring the containers down by `docker-compose stop` - -## 🌱 Env Variables - -If you like to persist your data (flows, logs, apikeys, credentials), set these variables in the `.env` file inside `docker` folder: - -- DATABASE_PATH=/root/.flowise -- APIKEY_PATH=/root/.flowise -- LOG_PATH=/root/.flowise/logs -- SECRETKEY_PATH=/root/.flowise +2. Run `npm run docker:start` +3. Open [http://localhost:3000](http://localhost:3000) +5. You can bring the containers down by `npm run docker:stop` -Flowise also support different environment variables to configure your instance. Read [more](https://docs.flowiseai.com/environment-variables) diff --git a/docker/cli b/docker/cli new file mode 100644 index 0000000000..f6208231d7 --- /dev/null +++ b/docker/cli @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# @knighttower - https://github.com/knighttower +# ------------------ +# Docker Start Script +# ------------------ + +# DO NOT EDIT THIS FILE OR RUN IT DIRECTLY. +# --> Use it executing from the root directory of the project: npm run docker:start +# ------------------ + +rootDir="$(pwd)" +echo "$rootDir" +dockerDir="$rootDir/docker" +source "$dockerDir/helpers.sh" + +# ------------------ +# Run the docker command +dockerUser="$(getEnv DOCKER_USER)" +# Check if it is empty and set the default value if it is +# User and container will be the same. It avoid issues/confusions with permissions and allows easy access via bash cli. +if [ "$dockerUser" = "" ]; then + dockerUser="flowise" +fi +echo -e "\e[32m Using dockerUser ----> $dockerUser!\e[0m" +docker exec -it $dockerUser bash diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 8e0e1af50c..0000000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: '3.1' - -services: - flowise: - image: flowiseai/flowise - restart: always - environment: - - PORT=${PORT} - - FLOWISE_USERNAME=${FLOWISE_USERNAME} - - FLOWISE_PASSWORD=${FLOWISE_PASSWORD} - - DEBUG=${DEBUG} - - DATABASE_PATH=${DATABASE_PATH} - - DATABASE_TYPE=${DATABASE_TYPE} - - DATABASE_PORT=${DATABASE_PORT} - - DATABASE_HOST=${DATABASE_HOST} - - DATABASE_NAME=${DATABASE_NAME} - - DATABASE_USER=${DATABASE_USER} - - DATABASE_PASSWORD=${DATABASE_PASSWORD} - - APIKEY_PATH=${APIKEY_PATH} - - SECRETKEY_PATH=${SECRETKEY_PATH} - - FLOWISE_SECRETKEY_OVERWRITE=${FLOWISE_SECRETKEY_OVERWRITE} - - LOG_LEVEL=${LOG_LEVEL} - - LOG_PATH=${LOG_PATH} - ports: - - '${PORT}:${PORT}' - volumes: - - ~/.flowise:/root/.flowise - command: /bin/sh -c "sleep 3; flowise start" diff --git a/docker/docker-compose.yml.template b/docker/docker-compose.yml.template new file mode 100644 index 0000000000..39606b3c8c --- /dev/null +++ b/docker/docker-compose.yml.template @@ -0,0 +1,57 @@ +version: '3.8' +# ------------------- +# "Service", "image" and "container" named the same to easely access via bash cli +# Ex: docker exec -it flowise bash +# ------------------- +# Values commented out to avoid errors when running the docker container +# Uncomment when in use by the ENV +# ------------------- +services: + flowise: + build: + context: . + dockerfile: ./docker/Dockerfile + args: + DOCKER_WORKSPACE_DIR: ${DOCKER_WORKSPACE_DIR} + image: flowise + container_name: flowise + hostname: flowise + restart: always + tty: true + env_file: .env + working_dir: ${DOCKER_WORKSPACE_DIR} + environment: + - SERVICE_NAME=flowise + - PORT=${PORT} + # - FLOWISE_USERNAME=${FLOWISE_USERNAME} + # - FLOWISE_PASSWORD=${FLOWISE_PASSWORD} + # - DEBUG=${DEBUG} + - DATABASE_PATH=${DATABASE_PATH} + # - DATABASE_TYPE=${DATABASE_TYPE} + # - DATABASE_PORT=${DATABASE_PORT} + # - DATABASE_HOST=${DATABASE_HOST} + # - DATABASE_NAME=${DATABASE_NAME} + # - DATABASE_USER=${DATABASE_USER} + # - DATABASE_PASSWORD=${DATABASE_PASSWORD} + - APIKEY_PATH=${APIKEY_PATH} + - SECRETKEY_PATH=${SECRETKEY_PATH} + # - FLOWISE_SECRETKEY_OVERWRITE=${FLOWISE_SECRETKEY_OVERWRITE} + # - LOG_LEVEL=${LOG_LEVEL} + # - LOG_PATH=${LOG_PATH} + ports: + - '${PORT}:${PORT}' + volumes: + - /.flowise:${DOCKER_WORKSPACE_DIR}/.flowise:delegated + # Avoids the need to "copy" file into the container + - ./:${DOCKER_WORKSPACE_DIR}:cached + # Share this folder with the dev folder to continue work + - ./data:${DOCKER_WORKSPACE_DIR}/data:delegated + # Keep the node_modules inside the container to avoid performance issues + - node_modules:${DOCKER_WORKSPACE_DIR}/node_modules + networks: + - flowise__network +networks: + flowise__network: + driver: bridge +volumes: + node_modules: diff --git a/docker/helpers.sh b/docker/helpers.sh new file mode 100644 index 0000000000..355b051a34 --- /dev/null +++ b/docker/helpers.sh @@ -0,0 +1,41 @@ +# utility_functions.sh +# @knighttower - https://github.com/knighttower + +# This function retrieves the value of a given environment variable from the .env file. +function getEnv() { + local var=$1 + + if [[ -z "$var" ]]; then + echo "Error: No variable name specified." + exit 1 + fi + + VAR=$(grep -w "$var" "$rootDir/.env" | head -1) + IFS="=" read -ra VAR <<<"$VAR" + envVar="${VAR[1]}" + + envVar=${envVar%$'\n'} # Remove a trailing newline. + envVar=${envVar//$'\n'/} # Remove all newlines. + echo ${envVar} | tr -d '\040\011\012\015' +} + +function testDockerRunning() { + if docker info >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +# This function prompts the user for a yes/no confirmation. +function promptConfirmation() { + local message=$1 + while true; do + read -p $'\e[33m'"${message}"$'\e[0m :: (Y/N or Enter to skip) : ' response + case $response in + [Yy]*) return 0 ;; + [Nn]* | "") return 1 ;; + *) echo "Please answer yes or no." ;; + esac + done +} diff --git a/docker/start b/docker/start new file mode 100644 index 0000000000..8e89d41ba7 --- /dev/null +++ b/docker/start @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# @knighttower - https://github.com/knighttower +# ------------------ +# Docker Start Script +# ------------------ + +# DO NOT EDIT THIS FILE OR RUN IT DIRECTLY. +# --> Use it executing from the root directory of the project: npm run docker:start +# ------------------ + +rootDir="$(pwd)" +echo "$rootDir" +dockerDir="$rootDir/docker" +source "$dockerDir/helpers.sh" + +# ----------------------------------------------------- +# ----------------- Run the Start ----------------- +# ------------------ +# Copy the .env file +if [ -f "$rootDir/.env" ]; then + echo -e "\e[32m ENV detected. ---->!\e[0m" + echo -e "\e[33m Make sure the ENV has the VARS from the 'docker' env.example file...\e[0m" +else + cp "$rootDir/docker/.env.example" "$rootDir/.env" + echo -e "\e[32m ENV file created! ---->!\e[0m" +fi + +# ------------------ +# Copy the docker file +if [ -f "$rootDir/docker-compose.yml" ]; then + echo -e "\e[32m Docker file detected. ---->!\e[0m" +else + cp "$rootDir/docker/docker-compose.yml.template" "$rootDir/docker-compose.yml" + echo -e "\e[32m Docker file created! ---->!\e[0m" +fi + +# ------------------ +# Run the docker command +dockerUser="$(getEnv DOCKER_USER)" +# Check if it is empty and set the default value if it is +# User and container will be the same. It avoid issues/confusions with permissions and allows easy access via bash cli. +if [ "$dockerUser" = "" ]; then + dockerUser="flowise" +fi +echo -e "\e[32m Using dockerUser ----> $dockerUser!\e[0m" + +# Check if docker is running +if testDockerRunning; then + echo -e "\e[32mDocker is running.\e[0m" +else + echo -e "\e[91mDocker is not running.\e[0m" + echo -e "\e[91mDocker needs to be running to continue.\e[0m" + + echo -e "\e[91m Please confirm if docker is running...\e[0m" + if promptConfirmation "is docker running?"; then + if testDockerRunning; then + echo -e "\e[32mDocker is running.\e[0m" + break + else + echo -e "\e[91mDocker is not running.\e[0m" + echo -e "\e[91mDocker needs to be running to continue.\e[0m" + fi + else + echo -e "\e[91mInstallation aborted\e[0m" + exit 1 + fi +fi + +echo -e "\e[33m ---> STARTING DOCKER... Please wait...\e[0m" +docker-compose -p "$dockerUser" up -d +echo -e "\e[32m ===> READY TO GO! docker is running\n\e[0m" + +echo -e "\e[33m ---> Running YARN stuff... Please wait...\n\n\e[0m" +sleep 1 +docker exec -t $dockerUser bash -c 'yarn install && yarn build && yarn start' +echo -e "\e[32m ===> go to http://localhost:3000 \e[0m" diff --git a/docker/stop b/docker/stop new file mode 100644 index 0000000000..92285a58d4 --- /dev/null +++ b/docker/stop @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# @knighttower - https://github.com/knighttower +# ------------------ +# Docker Stop Script +# ------------------ +rootDir="$(pwd)" +dockerDir="$rootDir/docker" +source "$dockerDir/helpers.sh" + +# ------------------ +# Run the docker command +dockerUser="$(getEnv DOCKER_USER)" +# Check if it is empty and set the default value if it is +# User and container will be the same. It avoid issues/confusions with permissions and allows easy access via bash cli. +if [ "$dockerUser" = "" ]; then + dockerUser="flowise" +fi +echo -e "\e[32m Using dockerUser ----> $dockerUser!\e[0m" + +# When multiple containers are running, is better to use the container name. Otherwise, it may not stop the container. +docker-compose -p "$dockerUser" stop diff --git a/package.json b/package.json index 909eb34533..cabcc96254 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,10 @@ "lint-fix": "yarn lint --fix", "quick": "pretty-quick --staged", "postinstall": "husky install", - "migration:create": "yarn typeorm migration:create" + "migration:create": "yarn typeorm migration:create", + "docker:start": "sh ./docker/start", + "docker:stop": "sh ./docker/stop", + "docker:cli": "sh ./docker/cli" }, "lint-staged": { "*.{js,jsx,ts,tsx,json,md}": "eslint --fix"