Przeglądaj źródła

O3DE Docker support (#17998)

Signed-off-by: Steve Pham <[email protected]>
Steve Pham 1 rok temu
rodzic
commit
5336271b9c
4 zmienionych plików z 388 dodań i 0 usunięć
  1. 132 0
      Docker/Dockerfile
  2. 105 0
      Docker/README.md
  3. 74 0
      Docker/build.sh
  4. 77 0
      Docker/entrypoint.sh

+ 132 - 0
Docker/Dockerfile

@@ -0,0 +1,132 @@
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+
+# The cpu architecture 
+ARG INPUT_ARCHITECTURE=amd64
+
+# The root docker image 
+ARG INPUT_IMAGE=ubuntu
+
+# The root docker tag 
+ARG INPUT_TAG=jammy
+
+# Pull in the base ubuntu docker
+FROM ${INPUT_ARCHITECTURE}/${INPUT_IMAGE}:${INPUT_TAG}
+
+ARG INPUT_IMAGE
+ARG INPUT_TAG
+
+ENV INPUT_IMAGE=$INPUT_IMAGE
+ENV WORKSPACE=/data/workspace
+
+WORKDIR $WORKSPACE
+
+# O3DE Arguments
+ARG O3DE_REPO=https://github.com/o3de/o3de
+ARG O3DE_BRANCH=development
+ARG O3DE_COMMIT=HEAD
+
+# O3DE Environment
+ENV O3DE_REPO=$O3DE_REPO
+ENV O3DE_BRANCH=$O3DE_BRANCH
+ENV O3DE_COMMIT=$O3DE_COMMIT
+ENV O3DE_ROOT=$WORKSPACE/o3de
+
+ENV LANG=en_US.UTF-8
+
+# Validate the tag if the image is 'ubuntu'
+RUN if [ "$INPUT_IMAGE" = "ubuntu" ]; then \
+        if [ "$INPUT_TAG" != "jammy" ] && [ "$INPUT_TAG" != "nobel" ]; then \
+            echo "ERROR: Unsupported ubuntu tag: ${INPUT_TAG}. Must be either 'jammy' or 'nobel'"; \
+            exit 1;\
+        fi \
+    fi
+
+# Validate the tag if the image is 'ros'
+RUN if [ "$INPUT_IMAGE" = "ros" ]; then \
+        if [ "$INPUT_TAG" != "humble" ] && [ "$INPUT_TAG" != "jazzy" ]; then \
+            echo "ERROR: Unsupported ros tag: ${INPUT_TAG}. Must be either 'humble' or 'jazzy'"; \
+            exit 1;\
+        fi \
+    fi
+
+# Setup time zone and locale data (necessary for SSL and HTTPS packages)
+RUN apt-get update \
+    && DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata locales keyboard-configuration curl \
+    && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
+    && dpkg-reconfigure --frontend=noninteractive locales \
+    && update-locale LANG=en_US.UTF-8 \
+    && rm -rf /var/lib/apt/lists/*
+
+# Install the required ubuntu packages
+RUN apt-get update \
+    && apt-get install -y \
+            binutils \
+            clang \
+            cmake \
+            cmake-qt-gui \
+            git \
+            git-lfs \
+            libglu1-mesa-dev \
+            libxcb-xinerama0 \
+            libfontconfig1-dev \
+            libnvidia-gl-470 \
+            libxcb-xkb-dev \
+            libxkbcommon-x11-dev \
+            libxkbcommon-dev \
+            libxcb-xfixes0-dev \
+            libxcb-xinput-dev \
+            libxcb-xinput0 \
+            libxcb-icccm4-dev \
+            libxcb-image0-dev \
+            libxcb-keysyms1-dev \
+            libxcb-render-util0-dev \
+            libpcre2-16-0 \
+            libunwind-dev \
+            libzstd-dev \
+            ninja-build \
+            python3-pip \
+            software-properties-common \
+            mesa-common-dev \
+            libvulkan1 \
+            gedit \
+            xdg-utils \
+            desktop-file-utils \
+            nautilus \
+            sudo
+
+# If this is a 'ros' image, add additional ros packages that are used by the current ros project templates.
+RUN if [ "$INPUT_IMAGE" = "ros" ]; then \
+     apt-get install -y ros-${ROS_DISTRO}-ackermann-msgs \
+                        ros-${ROS_DISTRO}-control-toolbox \
+                        ros-${ROS_DISTRO}-nav-msgs \
+                        ros-${ROS_DISTRO}-gazebo-msgs \
+                        ros-${ROS_DISTRO}-xacro \
+                        ros-${ROS_DISTRO}-moveit \
+                        ros-${ROS_DISTRO}-moveit-resources \
+                        ros-${ROS_DISTRO}-depth-image-proc; \
+    fi
+
+# Setup the 'o3de' user for this image (with a default group id, which will be updated in the entrypoint)
+ENV O3DE_USER=o3de 
+
+RUN addgroup --gid 1000 "$O3DE_USER" \
+    && adduser --gid 1000 --gecos "" --disabled-password "$O3DE_USER" \
+    && usermod -a -G sudo $O3DE_USER \
+    && echo "$O3DE_USER ALL=(ALL:ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/$O3DE_USER
+
+COPY build.sh $WORKSPACE/
+COPY entrypoint.sh $WORKSPACE/
+
+# Run the script to clone, build, and install O3DE as an SDK installer
+RUN cd $WORKSPACE \
+   && ./build.sh \
+   && rm build.sh
+
+ENV NVIDIA_VISIBLE_DEVICES all
+ENV NVIDIA_DRIVER_CAPABILITIES all
+
+ENTRYPOINT ["/bin/bash", "-c", "/data/workspace/entrypoint.sh"]

+ 105 - 0
Docker/README.md

@@ -0,0 +1,105 @@
+# Docker support for O3DE
+
+O3DE supports construction of a Docker image on the Linux environment. The following instructions will allow you to build and launch O3DE through a Docker container, with project data being persisted on your local machine.
+
+## Prerequisites
+
+* [Hardware requirements of o3de](https://www.o3de.org/docs/welcome-guide/requirements/)
+* Any Linux distribution that supports Docker and the NVIDIA container toolkit (see below)
+* At least 60 GB of free disk space
+* Docker installed and configured
+  * **Note** It is recommended to have Docker installed correctly and in a secure manner so that the Docker commands in this guide do not require elevated priviledges (sudo) in order to run them. See [Docker Engine post-installation steps](https://docs.docker.com/engine/install/linux-postinstall/) for more details.
+* [NVidia container toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)
+
+# Building the Docker image
+The Docker script provides the following arguments for building the Docker image, with each argument provide a default value.
+
+| Argument                | Description                                                                | Default
+|-------------------------|----------------------------------------------------------------------------|-------------
+| INPUT_IMAGE             | The base ubuntu docker image to base the build on                          | ubuntu
+| INPUT_TAG               | The base ubuntu docker image tag to base the build on                      | jammy
+| INPUT_ARCHITECTURE      | The CPU architecture (amd64/aarch64). Will require QEMU if cross compiling | amd64
+| O3DE_REPO               | The git repo for O3DE                                                      | https://github.com/o3de/o3de
+| O3DE_BRANCH             | The branch for O3DE                                                        | development
+| O3DE_COMMIT             | The commit on the branch for O3DE (or HEAD)                                | HEAD
+
+## Examples
+The following example build commands are based on the general use case for O3DE. 
+
+If there are any ROS2 gem based projects that will be created or used by the image, then you will need to follow the **ROS Example** section below.
+
+You can build a minimal Docker image that can create or use non-simulation projects using the `ubuntu` input image and either the `jammy` or `noble` input tag. To build a Docker image that supports robotic simulations using ROS, you must use the `ros` input image and either the `humble` or `jazzy` input tag. (Refer to the [Docker distribution of ROS](https://hub.docker.com/_/ros/))
+
+### Locally
+
+To build the Docker image from the local O3DE Docker context, run the following command from the `Docker` subfolder inside the o3de root folder.
+
+#### General
+```
+docker build -f Dockerfile --build-arg INPUT_IMAGE=ubuntu --build-arg INPUT_TAG=jammy -t amd64/o3de:ubuntu.jammy .
+```
+#### ROS2 enabled
+```
+docker build -f Dockerfile --build-arg INPUT_IMAGE=ros --build-arg INPUT_TAG=humble -t amd64/o3de:ros.humble .
+```
+
+### From github
+You can also build the Docker image from the O3DE Docker context directly from github with the following command (based on the development branch)
+
+#### General
+```
+docker build -t amd64/o3de:ubuntu.jammy https://github.com/o3de/o3de.git#development:Docker
+```
+
+#### ROS2 enabled
+```
+docker build --build-arg INPUT_IMAGE=ros --build-arg INPUT_TAG=humble -t amd64/o3de:ros.humble https://github.com/o3de/o3de.git#development:Docker
+```
+
+
+# Running the Docker image locally
+Docker containers by themselves are stateless, so in order for the container to act as a stateful container, some local preparations and additional runtime arguments are needed to be passed into the Docker run command.
+
+## Setting up O3DE-specific folders
+O3DE will use two folders for its runtime environment. The manifest folder (\$HOME/.o3de) and the O3DE Home folder (\$HOME/O3DE). On normal installations/build of the full O3DE engine, these folders are created on-demand based on the current logged in user. Since Docker containers by default are stateless, all the information that is downloaded, updated, deleted, etc from these two folders as part of normal operations will no longer exist once the container is disconnected, thus losing any work that was done while using O3DE. In order to utilize the O3DE Docker container to create and maintain O3DE projects beyond the container session, we will need to create these two folders manually and pass them in as mapped volumes to its corresponding specific folders within the container. 
+
+The following example creates these folders under a parent `docker` folder in the current user's `$HOME` directory, specific to the name of the Docker image.
+
+```
+mkdir -p $HOME/docker/o3de/manifest
+
+mkdir -p $HOME/docker/o3de/home
+```
+
+>**Note** The two folders must be created specifically for the O3DE Docker container that is being connected to. There is no version or compatibility checks in the Docker container, so normal O3DE startup in the container may fail if it does not use the same mapped folders it used during its initial launch.
+
+These two folders will be added as part of the `docker run` argument list:
+
+```
+-v "$HOME/docker/o3de/manifest:/home/o3de/.o3de" -v "$HOME/docker/o3de/home:/home/o3de/O3DE"
+```
+
+## Using the current user id and group id
+The Docker image will map the current user and group id to a Docker-created user and group when running the container. This will allow reading and writing to the mapped O3DE-specific folders described earlier and will add persistence to the Docker container through the mapped folders. The user id and group id are passed to the Docker run command as two arguments: `UID` and `GID`:
+
+```
+--env UID=$(id -u) --env GID=$(id -g)
+```
+
+
+Putting it all together, you can launch the O3DE Docker container with the following command:
+
+```
+xhost +local:root
+
+docker run --env UID=$(id -u) --env GID=$(id -g) -v "$HOME/docker/o3de/manifest:/home/o3de/.o3de" -v "$HOME/docker/o3de/home:/home/o3de/O3DE" --rm --gpus all -e DISPLAY=:1 -v /tmp/.X11-unix:/tmp/.X11-unix -it amd64/o3de:ubuntu.jammy
+```
+
+For the ROS container based example, add the `ros.humble` tag.
+```
+xhost +local:root
+
+docker run --env UID=$(id -u) --env GID=$(id -g) -v "$HOME/docker/o3de/manifest:/home/o3de/.o3de" -v "$HOME/docker/o3de/home:/home/o3de/O3DE" --rm --gpus all -e DISPLAY=:1 -v /tmp/.X11-unix:/tmp/.X11-unix -it amd64/o3de:ros.humble
+```
+
+Once the Docker container is launched, you will be logged into the O3DE-enabled terminal. At this point, typing in `o3de` in the command line will launch the O3DE Project Manager where you will be able to create, build, and launch O3DE projects.

+ 74 - 0
Docker/build.sh

@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+
+# Clone O3DE and bootstrap
+echo "Cloning o3de"
+git clone --single-branch -b $O3DE_BRANCH $O3DE_REPO $O3DE_ROOT && \
+    git -C $O3DE_ROOT lfs install && \
+    git -C $O3DE_ROOT lfs pull && \
+    git -C $O3DE_ROOT reset --hard $O3DE_COMMIT 
+if [ $? -ne 0 ]
+then
+    echo "Error cloning o3de from $O3DE_REPO"
+    exit 1
+fi
+
+$O3DE_ROOT/python/get_python.sh 
+if [ $? -ne 0 ]
+then
+    echo "Error bootstrapping O3DE from $O3DE_REPO"
+    exit 1
+fi
+
+# Build the installer package
+export O3DE_BUILD=$WORKSPACE/build
+export CONFIGURATION=profile
+export OUTPUT_DIRECTORY=$O3DE_BUILD
+export O3DE_PACKAGE_TYPE=DEB
+export CMAKE_OPTIONS="-G 'Ninja Multi-Config' -DLY_PARALLEL_LINK_JOBS=4 -DLY_DISABLE_TEST_MODULES=TRUE -DO3DE_INSTALL_ENGINE_NAME=o3de-sdk -DLY_STRIP_DEBUG_SYMBOLS=TRUE"
+export EXTRA_CMAKE_OPTIONS="-DLY_INSTALLER_AUTO_GEN_TAG=TRUE -DLY_INSTALLER_DOWNLOAD_URL=${INSTALLER_DOWNLOAD_URL} -DLY_INSTALLER_LICENSE_URL=${INSTALLER_DOWNLOAD_URL}/license -DO3DE_INCLUDE_INSTALL_IN_PACKAGE=TRUE"
+export CPACK_OPTIONS="-D CPACK_UPLOAD_URL=${CPACK_UPLOAD_URL}"
+export CMAKE_TARGET=all
+
+cd $O3DE_ROOT && \
+    $O3DE_ROOT/scripts/build/Platform/Linux/build_installer_linux.sh
+if [ $? -ne 0 ]
+then
+    echo "Error building installer"
+    exit 1
+fi
+
+# Install from the installer package
+su $O3DE_USER -c "sudo dpkg -i $O3DE_BUILD/CPackUploads/o3de_4.2.0.deb"
+if [ $? -ne 0 ]
+then
+    echo "Error installing O3DE for the o3de user"
+    exit 1
+fi
+
+# Cleanup the source from github and all intermediate files
+rm -rf $O3DE_ROOT
+rm -rf $O3DE_BUILD
+rm -rf $HOME/.o3de
+rm -rf $HOME/O3DE
+rm -rf /home/o3de/.o3de
+rm -rf /home/o3de/O3DE
+
+# The python libraries that are linked in the engine needs to be writable during python bootstrapping for the O3DE user from the installer
+chmod -R a+w /opt/O3DE/$(ls /opt/O3DE/)/Tools/LyTestTools \
+  && chmod -R a+w /opt/O3DE/$(ls /opt/O3DE/)/Tools/RemoteConsole/ly_remote_console \
+  && chmod -R a+w /opt/O3DE/$(ls /opt/O3DE/)/Gems/Atom/RPI/Tools \
+  && chmod -R a+w /opt/O3DE/$(ls /opt/O3DE/)/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface \
+  && chmod -R a+w /opt/O3DE/$(ls /opt/O3DE/)/scripts/o3de
+if [ $? -ne 0 ]
+then
+    echo "Error making O3DE python library folders writeable."
+    exit 1
+fi
+
+exit 0

+ 77 - 0
Docker/entrypoint.sh

@@ -0,0 +1,77 @@
+#!/bin/bash
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+
+# Validate that the UID and GID environment variables are set 
+: "${UID:=0}"
+: "${GID:=0}"
+
+if [ "$UID" == 0 ]
+then
+    echo 'The env for the current User ID is required. You need to provide the following arguments: --env UID=\$(id -u)'
+    exit 1
+fi
+
+if [ "$GID" == 0 ]
+then
+    echo 'The env for the current Group ID is required. You need to provide the following arguments: --env GID=\$(id -g)'
+    exit 1
+fi
+
+# Update the O3DE user's UID and GID to match the environment so that it has the same user information/permissions for the mapped volumes used
+# for persistence of this Docker container
+set -eu
+
+usermod -u "$UID" "$O3DE_USER" 2>/dev/null && {
+    groupmod -g "$GID" "$O3DE_USER" 2>/dev/null ||
+    usermod -a -G "$GID" "$O3DE_USER"
+}
+if [ $? -ne 0 ]
+then
+    echo "Error matching Docker user $O3DE to User ID $$UID and Group ID $GID"
+    exit 1
+fi
+
+# Make sure the O3DE specific manifest (.o3de) and home (O3DE) folders are mapped correctly for persistence
+if [ ! -d "/home/$O3DE_USER/.o3de" ]
+then
+    echo 'Mapping of the user id was not provided on docker run. You need to provide the following arguments: -v "$HOME/.o3de:/home/o3de/.o3de" -v "$HOME/O3DE:/home/o3de/O3DE"'
+    exit 1
+elif [ ! -d "/home/$O3DE_USER/O3DE" ]
+then
+    echo 'Mapping of the user id was not provided on docker run. You need to provide the following arguments: -v "$HOME/.o3de:/home/o3de/.o3de" -v "$HOME/O3DE:/home/o3de/O3DE"'
+    exit 1
+else
+    # Make sure ownership is correct for the mapped O3DE folders
+    sudo chown $O3DE_USER:$O3DE_USER -R /home/$O3DE_USER/.o3de
+    sudo chown $O3DE_USER:$O3DE_USER -R /home/$O3DE_USER/O3DE
+
+    # Prepare and set the XDG_RUNTIME_DIR value for Qt in order to launch mime applications from Project Manager
+    sudo mkdir -p /run/user/$UID
+    sudo chown $O3DE_USER:$O3DE_USER /run/user/$UID
+    sudo chmod 7700 /run/user/$UID
+    echo -e "\nexport XDG_RUNTIME_DIR=/run/user/$UID\n" >> /home/o3de/.bashrc
+fi
+
+# Bootstrap python first
+su -c "/opt/O3DE/$(ls /opt/O3DE/)/python/get_python.sh" $O3DE_USER 
+if [ $? -ne 0 ]
+then
+    echo "Error Initializing O3DE Python."
+    exit 1
+fi
+
+# If this is a ROS based image, then add ros setup in the $O3DE user's startup
+if [ "$INPUT_IMAGE" == "ros" ]
+then
+    echo -e "\nsource /opt/ros/${ROS_DISTRO}/setup.bash\n" >> /home/o3de/.bashrc
+fi
+
+# Start the session as $O3DE_USER
+set -- su $O3DE_USER -g $O3DE_USER "${@}"
+
+exec "$@"