Преглед на файлове

allow running app as root (#1651)

* allow running app as root

* better entrypoint mgmt

* add nosetup option

* remove comments

* create docker group if it doesnt exist

* better docker group mgmt

* cast bools better

* fix playwright

* fix playwright for root

* fix root source ~/.bashrc hangs by create clean bashrc

---------

Co-authored-by: Xingyao Wang <xingyao6@illinois.edu>
Robert Brennan преди 1 година
родител
ревизия
1cbb16cfc2
променени са 3 файла, в които са добавени 52 реда и са изтрити 25 реда
  1. 5 1
      containers/app/Dockerfile
  2. 39 24
      containers/app/entrypoint.sh
  3. 8 0
      opendevin/runtime/plugins/mixin.py

+ 5 - 1
containers/app/Dockerfile

@@ -73,4 +73,8 @@ COPY --chown=opendevin:app --chmod=770 --from=frontend-builder /app/dist ./front
 COPY --chown=opendevin:app --chmod=770 ./containers/app/entrypoint.sh /app/entrypoint.sh
 
 USER root
-CMD ["/app/entrypoint.sh"]
+
+WORKDIR /app
+
+ENTRYPOINT ["/app/entrypoint.sh"]
+CMD ["uvicorn", "opendevin.server.listen:app", "--host", "0.0.0.0", "--port", "3000"]

+ 39 - 24
containers/app/entrypoint.sh

@@ -1,5 +1,13 @@
 #!/bin/bash
-# check user is root
+set -eo pipefail
+
+echo "Starting OpenDevin..."
+if [[ $NO_SETUP == "true" ]]; then
+  echo "Skipping setup, running as $(whoami)"
+  "$@"
+  exit 0
+fi
+
 if [ "$(id -u)" -ne 0 ]; then
   echo "The OpenDevin entrypoint.sh must run as root"
   exit 1
@@ -11,30 +19,37 @@ if [ -z "$SANDBOX_USER_ID" ]; then
 fi
 
 if [[ "$SANDBOX_USER_ID" -eq 0 ]]; then
-  echo "SANDBOX_USER_ID cannot be 0. Please run with a different user id."
-  exit 1
-fi
-
-# change uid of opendevin user to match the host user
-# but the group id is not changed, so the user can still access everything under /app
-if ! useradd -l -m -u $SANDBOX_USER_ID -s /bin/bash enduser; then
-  echo "Failed to create user enduser with id $SANDBOX_USER_ID. Moving opendevin user."
-  incremented_id=$(($SANDBOX_USER_ID + 1))
-  usermod -u $incremented_id opendevin
+  echo "Running OpenDevin as root"
+  export RUN_AS_DEVIN=false
+  mkdir -p /root/.cache/ms-playwright/
+  mv /home/opendevin/.cache/ms-playwright/ /root/.cache/
+  "$@"
+else
+  echo "Setting up enduser with id $SANDBOX_USER_ID"
   if ! useradd -l -m -u $SANDBOX_USER_ID -s /bin/bash enduser; then
-    echo "Failed to create user enduser with id $SANDBOX_USER_ID for a second time. Exiting."
-    exit 1
+    echo "Failed to create user enduser with id $SANDBOX_USER_ID. Moving opendevin user."
+    incremented_id=$(($SANDBOX_USER_ID + 1))
+    usermod -u $incremented_id opendevin
+    if ! useradd -l -m -u $SANDBOX_USER_ID -s /bin/bash enduser; then
+      echo "Failed to create user enduser with id $SANDBOX_USER_ID for a second time. Exiting."
+      exit 1
+    fi
+  fi
+  usermod -aG app enduser
+  # get the user group of /var/run/docker.sock and set opendevin to that group
+  DOCKER_SOCKET_GID=$(stat -c '%g' /var/run/docker.sock)
+  echo "Docker socket group id: $DOCKER_SOCKET_GID"
+  if getent group $DOCKER_SOCKET_GID; then
+    echo "Group with id $DOCKER_SOCKET_GID already exists"
+  else
+    echo "Creating group with id $DOCKER_SOCKET_GID"
+    groupadd -g $DOCKER_SOCKET_GID docker
   fi
-fi
-
-usermod -aG app enduser
-mkdir -p /home/enduser/.cache/ms-playwright/
-mv /home/opendevin/.cache/ms-playwright/ /home/enduser/.cache/
 
-# get the user group of /var/run/docker.sock and set opendevin to that group
-DOCKER_SOCKET_GID=$(stat -c '%g' /var/run/docker.sock)
-echo "Docker socket group id: $DOCKER_SOCKET_GID"
-usermod -aG $DOCKER_SOCKET_GID enduser
+  mkdir -p /home/enduser/.cache/ms-playwright/
+  mv /home/opendevin/.cache/ms-playwright/ /home/enduser/.cache/
 
-# switch to the user and start the server
-su enduser -c "cd /app && uvicorn opendevin.server.listen:app --host 0.0.0.0 --port 3000"
+  usermod -aG $DOCKER_SOCKET_GID enduser
+  echo "Running as enduser"
+  su enduser /bin/bash -c "$*"
+fi

+ 8 - 0
opendevin/runtime/plugins/mixin.py

@@ -18,6 +18,14 @@ class PluginMixin:
 
     def init_plugins(self: SandboxProtocol, requirements: list[PluginRequirement]):
         """Load a plugin into the sandbox."""
+
+        # clean-up ~/.bashrc and touch ~/.bashrc
+        exit_code, output = self.execute('rm -f ~/.bashrc && touch ~/.bashrc')
+        if exit_code != 0:
+            raise RuntimeError(
+                f'Failed to clean-up ~/.bashrc with exit code {exit_code} and output {output}'
+            )
+
         for requirement in requirements:
             # copy over the files
             self.copy_to(requirement.host_src, requirement.sandbox_dest, recursive=True)