diff --git a/.github/workflows/docker-feature.yml b/.github/workflows/docker-feature.yml index 78570d9..2c92851 100644 --- a/.github/workflows/docker-feature.yml +++ b/.github/workflows/docker-feature.yml @@ -20,6 +20,4 @@ jobs: with: push: true tags: halimqarroum/docker-android:test - build-args: | - API_LEVEL=33 - IMG_TYPE=google_apis + build-args: INSTALL_ANDROID_SDK=0 diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index c4b7a68..27bdbb8 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -5,6 +5,7 @@ on: branches: [ "main" ] paths: - 'Dockerfile' + - 'Dockerfile.gpu' - '.github/workflows/*' - 'deps/*' - 'keys/*' @@ -17,7 +18,14 @@ jobs: strategy: matrix: version: [33, 32, 31, 30, 29, 28] - image: [{ name: 'google_apis', suffix: '' }, { name: 'google_apis_playstore', suffix: '-playstore' }] + image: [ + { name: 'google_apis', suffix: '' }, + { name: 'google_apis_playstore', suffix: '-playstore' } + ] + gpu: [ + { file: 'Dockerfile', suffix: '' }, + { file: 'Dockerfile.gpu', suffix: '-cuda' } + ] runs-on: ubuntu-latest steps: - name: Login to Docker Hub @@ -29,13 +37,20 @@ jobs: uses: docker/build-push-action@v4 with: push: true - tags: halimqarroum/docker-android:api-${{ matrix.version }}${{ matrix.image.suffix }} + file: ${{ matrix.gpu.file }} + tags: halimqarroum/docker-android:api-${{ matrix.version }}${{ matrix.image.suffix }}${{ matrix.gpu.suffix }} build-args: | API_LEVEL=${{ matrix.version }} IMG_TYPE=${{ matrix.image.name }} # Builds a minimal image without any Android SDK images. build-minimal: + strategy: + matrix: + gpu: [ + { file: 'Dockerfile', suffix: '' }, + { file: 'Dockerfile.gpu', suffix: '-cuda' } + ] runs-on: ubuntu-latest steps: - name: Login to Docker Hub @@ -47,5 +62,6 @@ jobs: uses: docker/build-push-action@v4 with: push: true - tags: halimqarroum/docker-android:minimal + file: ${{ matrix.gpu.file }} + tags: halimqarroum/docker-android:minimal${{ matrix.gpu.suffix }} build-args: INSTALL_ANDROID_SDK=0 diff --git a/Dockerfile b/Dockerfile index d2267c2..2497c73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ ARG IMG_TYPE=google_apis ARG ARCHITECTURE=x86_64 ARG CMD_LINE_VERSION=9477386_latest ARG DEVICE_ID=pixel +ARG GPU_ACCELERATED=false # Environment variables. ENV ANDROID_SDK_ROOT=/opt/android \ @@ -44,6 +45,7 @@ ENV ANDROID_SDK_ROOT=/opt/android \ DEVICE_ID=$DEVICE_ID \ ARCHITECTURE=$ARCHITECTURE \ ABI=${IMG_TYPE}/${ARCHITECTURE} \ + GPU_ACCELERATED=$GPU_ACCELERATED \ QTWEBENGINE_DISABLE_SANDBOX=1 \ ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 diff --git a/Dockerfile.gpu b/Dockerfile.gpu new file mode 100644 index 0000000..0be8255 --- /dev/null +++ b/Dockerfile.gpu @@ -0,0 +1,88 @@ +FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04 + +# Docker labels. +LABEL maintainer "Halim Qarroum " +LABEL description "A Docker image allowing to run an Android emulator" +LABEL version "1.1.0" + +# `redir.c` will be used to redirect +# localhost ADB ports to the container interface. +COPY deps/redir/redir.c /usr/src/redir.c + +# Installing required packages. +RUN apt update -y && \ + apt install -y --no-install-recommends \ + build-essential \ + bash \ + unzip \ + wget \ + libvirt-daemon \ + dbus \ + openjdk-11-jdk \ + ca-certificates-java \ + virt-manager \ + libvulkan1 \ + xvfb \ + libgl1-mesa-glx \ + libgl1-mesa-dri \ + iproute2 && \ + # Compile `redir`. + gcc /usr/src/redir.c -o /usr/bin/redir && \ + strip /usr/bin/redir && \ + rm -rf /var/lib/apt/lists/* + +# Arguments that can be overriden at build-time. +ARG INSTALL_ANDROID_SDK=1 +ARG API_LEVEL=33 +ARG IMG_TYPE=google_apis +ARG ARCHITECTURE=x86_64 +ARG CMD_LINE_VERSION=9477386_latest +ARG DEVICE_ID=pixel +ARG GPU_ACCELERATED=true + +# Environment variables. +ENV ANDROID_SDK_ROOT=/opt/android \ + ANDROID_PLATFORM_VERSION="platforms;android-$API_LEVEL" \ + PACKAGE_PATH="system-images;android-${API_LEVEL};${IMG_TYPE};${ARCHITECTURE}" \ + API_LEVEL=$API_LEVEL \ + DEVICE_ID=$DEVICE_ID \ + ARCHITECTURE=$ARCHITECTURE \ + ABI=${IMG_TYPE}/${ARCHITECTURE} \ + GPU_ACCELERATED=$GPU_ACCELERATED \ + QTWEBENGINE_DISABLE_SANDBOX=1 \ + ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL=10 + +# Exporting environment variables for keeping in the path +# Android SDK binaries and shared libraries. +ENV PATH "${PATH}:${ANDROID_SDK_ROOT}/platform-tools" +ENV PATH "${PATH}:${ANDROID_SDK_ROOT}/emulator" +ENV PATH "${PATH}:${ANDROID_SDK_ROOT}/cmdline-tools/tools/bin" +ENV LD_LIBRARY_PATH "$ANDROID_SDK_ROOT/emulator/lib64:$ANDROID_SDK_ROOT/emulator/lib64/qt/lib" + +# Set the working directory to /opt +WORKDIR /opt + +# Exposing the Android emulator console port +# and the ADB port. +EXPOSE 5554 5555 + +# Initializing the required directories. +RUN mkdir /root/.android/ && \ + touch /root/.android/repositories.cfg + +# Exporting ADB keys. +COPY keys/* /root/.android/ + +# Copy the startup scripts. +COPY scripts/* /opt/ + +# Make the scripts executable. +RUN chmod +x /opt/*.sh + +# This layer will download the Android command-line tools +# to install the Android SDK, emulator and system images. +# It will then install the Android SDK and emulator. +RUN /opt/install-sdk.sh + +# Set the entrypoint +ENTRYPOINT ["/opt/start-emulator.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 4e31eeb..8ebc0e8 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![DeepSource](https://deepsource.io/gh/HQarroum/docker-android.svg/?label=active+issues&show_trend=true&token=JTfGSHolIiMj0WNfv2ES0I6X)](https://deepsource.io/gh/HQarroum/docker-android/?ref=repository-badge) ![Docker Pulls](https://img.shields.io/docker/pulls/halimqarroum/docker-android) -Current version: **1.0.0** +Current version: **1.1.0** ## 📋 Table of contents diff --git a/scripts/start-emulator.sh b/scripts/start-emulator.sh index 78cf13b..833bcac 100644 --- a/scripts/start-emulator.sh +++ b/scripts/start-emulator.sh @@ -23,20 +23,35 @@ export USER=root # Creating the Android Virtual Emulator. echo "Creating the Android Virtual Emulator ..." echo "Using package '$PACKAGE_PATH', ABI '$ABI' and device '$DEVICE_ID' for creating the emulator" -echo no | avdmanager create avd -n android --abi "$ABI" -k "$PACKAGE_PATH" --device "$DEVICE_ID" +echo no | avdmanager create avd \ + --force \ + --name android \ + --abi "$ABI" \ + --package "$PACKAGE_PATH" \ + --device "$DEVICE_ID" + +# If GPU acceleration is enabled, we create a virtual framebuffer +# to be used by the emulator when running with GPU acceleration. +# We also set the GPU mode to `host` to force the emulator to use +# GPU acceleration. +if [ "$GPU_ACCELERATED" == "true" ]; then + export DISPLAY=":0.0" + export GPU_MODE="host" + Xvfb "$DISPLAY" -screen 0 1920x1080x16 -nolisten tcp & +else + export GPU_MODE="auto" +fi # Asynchronously write updates on the standard output # about the state of the boot sequence. -#cat ~/.android/avd/android.avd/config.ini wait_for_boot & # Start the emulator with no audio, no GUI, and no snapshots. echo "Starting the emulator ..." emulator \ + -verbose \ -avd android \ - -noaudio \ + -gpu "$GPU_MODE" \ -no-boot-anim \ -no-window \ - -no-snapshot-save \ - -qemu \ - -enable-kvm || update_state "ANDROID_STOPPED" + -no-snapshot || update_state "ANDROID_STOPPED"