diff --git a/Dockerfile b/Dockerfile index 1a375d305..93ac2505e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,51 +2,34 @@ # For users outside mainland China, feel free to modify or delete them :) # Use a base image with Python 3.9.17 slim version (Bullseye) -FROM python:3.9.17-slim-bullseye +FROM nikolaik/python-nodejs:python3.9-nodejs20-slim # Install Debian software needed by MetaGPT -RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list &&\ - apt update &&\ - apt install -y git curl wget build-essential gcc clang g++ make gnupg &&\ - curl -sL https://deb.nodesource.com/setup_19.x | bash - &&\ - apt install -y nodejs &&\ - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - &&\ - sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' &&\ - apt-get update &&\ - apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 --no-install-recommends &&\ - apt-get clean +RUN apt update &&\ + apt install -y git chromium fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 --no-install-recommends &&\ + apt clean # Set the working directory to /app WORKDIR /app -# Install Mermaid CLI globally and clone the MetaGPT repository -#ENV PUPPETEER_SKIP_DOWNLOAD='true' -RUN npm config set registry https://registry.npm.taobao.org &&\ - npm install -g @mermaid-js/mermaid-cli &&\ - npm cache clean --force &&\ - git clone https://github.com/geekan/metagpt +# Install Mermaid CLI globally +ENV CHROME_BIN="/usr/bin/chromium" +ENV AM_I_IN_A_DOCKER_CONTAINER Yes +ADD puppeteer-config.json /puppeteer-config.json +RUN npm install -g @mermaid-js/mermaid-cli &&\ + npm cache clean --force + +# Copy src to container the MetaGPT repository +COPY . /app/metagpt # Install Python dependencies and install MetaGPT RUN cd metagpt &&\ mkdir workspace &&\ - pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ &&\ pip install -r requirements.txt &&\ pip cache purge &&\ python setup.py install -# Add metagpt user so we don't need --no-sandbox when use puppeteer -RUN useradd -m metagpt -s /bin/bash &&\ - chown metagpt -R /app/metagpt &&\ - cp -r /root/.cache /home/metagpt/ &&\ - chown metagpt -R /home/metagpt/.cache &&\ - chrome_sandbox=$(find /root/.cache/puppeteer/chrome/ -name "chrome_sandbox") &&\ - cp $chrome_sandbox /usr/local/sbin/chrome-devel-sandbox &&\ - chmod 4755 /usr/local/sbin/chrome-devel-sandbox - -ENV CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox - WORKDIR /app/metagpt -USER metagpt # Running with an infinite loop using the tail command -CMD ["sh", "-c", "tail -f /dev/null"] \ No newline at end of file +CMD ["sh", "-c", "tail -f /dev/null"] diff --git a/README.md b/README.md index 8ade2339b..84f9ee293 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,9 @@ ## Examples (fully generated by GPT-4) It requires around **$0.2** (GPT-4 api's costs) to generate one example with analysis and design, around **$2.0** to a full project. ## Installation + ### Traditional Installation + ```bash # Step 1: Ensure that NPM is installed on your system. Then install mermaid-js. npm --version @@ -51,12 +53,13 @@ # Step 3: Clone the repository to your local machine, and install it. python setup.py install ``` -### Installation by Docker +### Installation by Docker + ```bash # Step 1: Download metagpt official image and prepare config.yaml -docker pull metagpt/metagpt:v0.2 -mkdir -p /opt/metagpt/{config,workspace} && chmod 777 -R /opt/metagpt -docker run --rm metagpt/metagpt:v0.2 cat /app/metagpt/config/config.yaml > /opt/metagpt/config/config.yaml +docker pull metagpt/metagpt:v0.3 +mkdir -p /opt/metagpt/{config,workspace} +docker run --rm metagpt/metagpt:v0.3 cat /app/metagpt/config/config.yaml > /opt/metagpt/config/config.yaml vim /opt/metagpt/config/config.yaml # Change the config # Step 2: Run metagpt demo with container @@ -64,7 +67,7 @@ # Step 2: Run metagpt demo with container --privileged \ -v /opt/metagpt/config:/app/metagpt/config \ -v /opt/metagpt/workspace:/app/metagpt/workspace \ - metagpt/metagpt:v0.2 \ + metagpt/metagpt:v0.3 \ python startup.py "Write a cli snake game" # You can also start a container and execute commands in it @@ -72,22 +75,24 @@ # You can also start a container and execute commands in it --privileged \ -v /opt/metagpt/config:/app/metagpt/config \ -v /opt/metagpt/workspace:/app/metagpt/workspace \ - metagpt/metagpt:v0.2 + metagpt/metagpt:v0.3 docker exec -it metagpt /bin/bash $ python startup.py "Write a cli snake game" ``` -The command `docker run ...` do the following things: +The command `docker run ...` do the following things: + - Run in privileged mode to have permission to run the browser -- Map host directory `/opt/metagtp/config` to container directory `/app/metagpt/config` -- Map host directory `/opt/metagpt/workspace` to container directory `/app/metagpt/workspace` +- Map host directory `/opt/metagpt/config` to container directory `/app/metagpt/config` +- Map host directory `/opt/metagpt/workspace` to container directory `/app/metagpt/workspace` - Execute the demo command `python startup.py "Write a cli snake game"` ### Build image by yourself + ```bash # You can also build metagpt image by yourself. -cd metagpt && docker build --network host -t metagpt:v0.1 . +cd metagpt && docker build --network host -t metagpt:v0.3 . ``` ## Configuration @@ -100,10 +105,10 @@ # Copy the configuration file and make the necessary modifications. cp config/config.yaml config/key.yaml ``` -| Variable Name | config/key.yaml | env | -|--------------------------------------------|-------------------------------------------|--------------------------------| -| OPENAI_API_KEY # Replace with your own key | OPENAI_API_KEY: "sk-..." | export OPENAI_API_KEY="sk-..." | -| OPENAI_API_BASE # Optional | OPENAI_API_BASE: "https:///v1" | export OPENAI_API_BASE="https:///v1" | +| Variable Name | config/key.yaml | env | +| ------------------------------------------ | ----------------------------------------- | ----------------------------------------------- | +| OPENAI_API_KEY # Replace with your own key | OPENAI_API_KEY: "sk-..." | export OPENAI_API_KEY="sk-..." | +| OPENAI_API_BASE # Optional | OPENAI_API_BASE: "https:///v1" | export OPENAI_API_BASE="https:///v1" | ## Tutorial: Initiating a startup diff --git a/metagpt/utils/mermaid.py b/metagpt/utils/mermaid.py index 35aceb2b9..edb09ffc7 100644 --- a/metagpt/utils/mermaid.py +++ b/metagpt/utils/mermaid.py @@ -6,12 +6,15 @@ @File : mermaid.py """ import subprocess +import os from pathlib import Path from metagpt.const import PROJECT_ROOT from metagpt.logs import logger from metagpt.utils.common import check_cmd_exists +IS_DOCKER = os.environ.get('AM_I_IN_A_DOCKER_CONTAINER', False) + def mermaid_to_file(mermaid_code, output_file_without_suffix, width=2048, height=2048) -> int: """suffix: png/svg/pdf @@ -34,7 +37,10 @@ def mermaid_to_file(mermaid_code, output_file_without_suffix, width=2048, height output_file = f'{output_file_without_suffix}.{suffix}' # Call the `mmdc` command to convert the Mermaid code to a PNG logger.info(f"Generating {output_file}..") - subprocess.run(['mmdc', '-i', str(tmp), '-o', output_file, '-w', str(width), '-H', str(height)]) + if IS_DOCKER: + subprocess.run(['mmdc', '-p', '/puppeteer-config.json', '-i', str(tmp), '-o', output_file, '-w', str(width), '-H', str(height)]) + else: + subprocess.run(['mmdc', '-i', str(tmp), '-o', output_file, '-w', str(width), '-H', str(height)]) return 0 diff --git a/puppeteer-config.json b/puppeteer-config.json new file mode 100644 index 000000000..7b2851c29 --- /dev/null +++ b/puppeteer-config.json @@ -0,0 +1,6 @@ +{ + "executablePath": "/usr/bin/chromium", + "args": [ + "--no-sandbox" + ] +} \ No newline at end of file