Skip to content

Commit

Permalink
fix: readd working docker image build and update readme.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Bilb committed May 28, 2024
1 parent 93c7027 commit d177c62
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 173 deletions.
2 changes: 0 additions & 2 deletions .eslintignore

This file was deleted.

1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ module.exports = {
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
},
ignorePatterns: ['avd/', '*.js', "run/**/*.js", ".eslintrc.js"]
};
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.js
README.md
package.json
package.json
/avd/
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM android-emulator-base



#=========================
# Copying Scripts to root
#=========================

RUN chmod a+x /session-appium/docker/*.sh
RUN ln -s /session-appium/docker/dl.sh /usr/bin/dl && ln -s /session-appium/docker/test.sh /usr/bin/ci_test && ln -s /session-appium/docker/dl_and_test.sh /usr/bin/dl_and_test



WORKDIR /session-appium

EXPOSE 8080

COPY avd /root/.android/avd

ENTRYPOINT [ "/usr/bin/supervisord", "-c", "/etc/supervisord_test.conf", "-n" ]
119 changes: 119 additions & 0 deletions Dockerfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# syntax=docker.io/docker/dockerfile:1.7-labs

FROM openjdk:18-ea-11-jdk-slim-bullseye

LABEL maintainer "Audric Ackermann"

ENV DEBIAN_FRONTEND noninteractive

WORKDIR /
#=============================
# Install Dependenices
#=============================
SHELL ["/bin/bash", "-c"]

RUN apt-get update
RUN apt install -y ca-certificates curl git cpu-checker supervisor vim bash wget unzip xvfb x11vnc fluxbox xterm novnc net-tools htop libpulse-dev libnss3 libxcursor1 libasound2 libqt5gui5 libc++-dev libxcb-cursor0 htop tree tar gzip


#==============================
# Android SDK ARGS
#==============================
ARG ARCH="x86_64"
ARG TARGET="google_apis_playstore"
ARG API_LEVEL="34"
ARG BUILD_TOOLS="34.0.0"
ARG ANDROID_ARCH=${ANDROID_ARCH_DEFAULT}
ARG ANDROID_API_LEVEL="android-${API_LEVEL}"
ARG ANDROID_APIS="${TARGET};${ARCH}"
ARG EMULATOR_PACKAGE="system-images;${ANDROID_API_LEVEL};${ANDROID_APIS}"
ARG PLATFORM_VERSION="platforms;${ANDROID_API_LEVEL}"
ARG BUILD_TOOL="build-tools;${BUILD_TOOLS}"
ARG ANDROID_CMD="commandlinetools-linux-11076708_latest.zip"
ARG ANDROID_SDK_PACKAGES="${EMULATOR_PACKAGE} ${PLATFORM_VERSION} ${BUILD_TOOL} platform-tools"

#==============================
# Set JAVA_HOME - SDK
#==============================
ENV ANDROID_SDK_ROOT=/opt/android
ENV PATH "$PATH:$ANDROID_SDK_ROOT/cmdline-tools/tools:$ANDROID_SDK_ROOT/cmdline-tools/tools/bin:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/latform-tools:$ANDROID_SDK_ROOT/build-tools/${BUILD_TOOLS}:$ANDROID_SDK_ROOT/platform-tools/"
ENV DOCKER="true"

#============================================
# Install required Android CMD-line tools
#============================================
RUN wget https://dl.google.com/android/repository/${ANDROID_CMD} -P /tmp && \
unzip -d $ANDROID_SDK_ROOT /tmp/$ANDROID_CMD && \
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/tools && cd $ANDROID_SDK_ROOT/cmdline-tools && mv NOTICE.txt source.properties bin lib tools/ && \
cd $ANDROID_SDK_ROOT/cmdline-tools/tools && ls

#============================================
# Install required package using SDK manager
#============================================
RUN yes Y | sdkmanager --licenses
RUN yes Y | sdkmanager --verbose --no_https ${ANDROID_SDK_PACKAGES}

#============================================
# Create required emulators
#============================================
RUN adb devices # keep this one to make sure adb is initialized (and creates a dummy adbkey, then erase it)
RUN rm /root/.android/adbkey
COPY adbkey /root/.android/adbkey
COPY adbkey.pub /root/.android/adbkey.pub
RUN chmod 600 /root/.android/adbkey
RUN chmod 644 /root/.android/adbkey.pub
RUN adb devices

ARG EMULATOR_NAME="emulator1"
ARG EMULATOR_DEVICE="pixel_6" # all emulators are created with the pixel 6 spec for now

RUN yes | sdkmanager emulator
RUN echo "no" | avdmanager --verbose create avd --force --name "${EMULATOR_NAME}" --device "${EMULATOR_DEVICE}" --package "${EMULATOR_PACKAGE}"

#==========================
# Install node & yarn berry
#==========================

RUN curl -sL https://deb.nodesource.com/setup_18.x | bash && \
apt-get -qqy install nodejs && npm install -g yarn && corepack enable && \
yarn set version 4.1.1


# Install websokify and noVNC
RUN curl -O https://bootstrap.pypa.io/get-pip.py && \
python3 get-pip.py && \
pip3 install --no-cache-dir \
setuptools && \
pip3 install -U https://github.com/novnc/websockify/archive/refs/tags/v0.11.0.tar.gz

RUN wget -O x11vnc.zip https://github.com/x11vnc/noVNC/archive/refs/heads/x11vnc.zip && \
unzip x11vnc.zip && mv noVNC-x11vnc /usr/local/noVNC/ && ls -la /usr/local/noVNC/utils && \
(chmod a+x /usr/local/noVNC/utils/launch.sh || \
(chmod a+x /usr/local/noVNC/utils/novnc_proxy && \
ln -s -f /usr/local/noVNC/utils/novnc_proxy /usr/local/noVNC/utils/launch.sh)) && \
rm -rf /tmp/* /var/tmp/*


ENV HOME=/root \
DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8 \
LC_ALL=C.UTF-8 \
DISPLAY=:0.0 \
DISPLAY_WIDTH=1920 \
DISPLAY_HEIGHT=900 \
RUN_XTERM=yes \
RUN_FLUXBOX=yes


#==========================
# copy the appium current folder
#==========================

COPY --exclude="node_modules" --exclude="avd" --exclude=".git" --exclude="etc" --exclude="config/local*" ./ /session-appium


COPY docker/etc /etc


EXPOSE 8080
132 changes: 41 additions & 91 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -1,106 +1,56 @@
# Android emulator Image
### Build the base image without the adb in it

The use of this Docker image simplifies the process of running an Android emulator within a Docker container. This can be achieved through a few basic commands or by utilizing a simple Docker compose file. The image includes the latest version of the Android SDK, as well as the Appium server, which allows for the execution of mobile automation tests.
for more info --> https://medium.com/@Amr.sa/running-android-emulator-in-a-docker-container-19ecb68e1909
**This has to be done once on each computers you use this docker, and if you ever change the Dockerfile.base settings related to the avd.**

# Feature
Comment this line in the Dockerfile:
`COPY avd /root/.android/avd`

- Run android emulator in headless or in headed mode (through VNC)
- Support Appium driver
- Come with the latest JDK lts.
then run build both docker images (base and test one) so you can manually build a snapshot for your avds. (step 1)
```sh
clear; sudo docker build -t android-emulator-base -f Dockerfile.base . && sudo docker build -t android-emulator -f Dockerfile . && sudo docker run --privileged -it --device /dev/kvm -p 8080:8080 android-emulator
```

Once that's done, open a browser to http://localhost:8080/vnc.html, you should see the novnc connect button.
Connect, and in the terminal opened, enter this (copy/paste doesn't work for now)
```
./docker/start_emu_for_state.sh
```

# Setup
Let the emulator start, and give it a few more minutes so the snapshot is as complete as possible.
Then, close manually the emulator, it should display the "saving state" dialog.
Once the state is saved, do on a host terminal from the root of the `appium` folder:
```
sudo rm -rf avd; sudo docker cp $(sudo docker ps -q):/root/.android/avd/ ./avd # sudo docker ps -q returns the running container hash directly
```

## Manual execution

Down below is the list of the main scripts to launch the relevant service, certain environment variables should be passed during starting the container.
Once that's done, stop the current docker container (ctrl-c should be enough).

1. **build the docker image :**
Then, uncomment the line
```
COPY avd /root/.android/avd
```

docker build -t android-emulator .
in the Dockerfile, and rebuild the 2 images
```
clear; sudo docker build -t android-emulator-base -f Dockerfile.base . && sudo docker build -t android-emulator -f Dockerfile . # (step 1)
```
Once that's done, you can start the docker with the apk to test with

OR for customized image
```
sudo docker run --privileged -it --device /dev/kvm -e APK_URL='<url of apk to test>' -e NODE_CONFIG_ENV="ci" -e APK_TO_TEST_PATH="/session.apk" -p 8080:8080 android-emulator # (step 2)
```

docker build \
--build-arg ARCH=x86_64 \
--build-arg TARGET=google_apis_playstore\
--build-arg API_LEVEL=31 \
--build-arg BUILD_TOOLS=31.0.0 \
--build-arg EMULATOR_DEVICE="Nexus 6" \
--build-arg EMULATOR_NAME=nexus \
-t my-android-image .

2. **Start your container:**
Then, reconnect via vnc http://localhost:8080/vnc.html, and run in the terminal
```
./docker/start_4_emus.sh &
```
The 4 emulators should start hopefully not too slowly.

docker run -it --privileged -d -p 5900:5900 --name androidContainer --privileged android-emulator
You can then trigger the dl of the APK (from the APK_TO_TEST_PATH env variable above) and the integration tests by running the command
`dl_and_test`

3. **Launch the appium session :**

docker exec --privileged -it androidContainer bash -c "appium -p 5900"
### Daily use

OR

docker exec --privileged -it androidContainer bash -c "./start_appium.sh"


4. **Start the emulator in headless mode :**

docker exec --privileged -it -e EMULATOR_TIMEOUT=300 androidContainer bash -c "./start_emu_headless.sh"

5. **Starting VNC server:**

docker exec --privileged -it androidContainer bash -c "./start_vnc.sh"



## Launch emulator in headed mode


1. **The following command must be used to initiate the Docker container:**

docker run -it -d -p 5900:5900 --name androidContainer -e VNC_PASSWORD=password --privileged android-emulator

2. **Instantiate the VNC service by running:**

docker exec --privileged -it androidContainer bash -c "./start_vnc.sh"

3. **Connect to the VNC server via remmina or any VNC viewer, on:**

localhost:5900

4. **Open dash terminal in vnc viewer and right the following command:**

#: ./start_emu.sh

<a href="https://ibb.co/pPq0bn9"><img src="https://i.ibb.co/pPq0bn9/vnc.png" alt="vnc" border="0"></a> <a href="https://ibb.co/cJB6qkX"><img src="https://i.ibb.co/cJB6qkX/gif.gif" alt="gif" border="0"></a>

*Note:
- The "start_emu.sh" script will start the emulator in a visible mode, therefore it should not be used for integration with a pipeline such as GitHub Actions or CircleCI. Instead, use the "start_emu_headless.sh" script.
- By default, Running emulator is 'Nexus 6' (emulator name: nexus) (Android 13)
- It is not necessary to launch all services in the docker-compose file, instead you should only enable the services you require, and comment out the others in the file.


## Using Docker-compose

The Docker Compose file simplifies the process of starting the service. It includes multiple services, such as launching the emulator with the Appium instance or launching the VNC server. You have the flexibility to enable or disable any service based on your needs.

docker compose up

## Environments

**When manually starting the container, ensure to set the necessary environment variables for proper operation**

| Environments | Description | Required | Service |
| ----------------- | -------------------------------------------------------------------------------------------------------- | ----------------- | -----------|
| APPIUM_PORT | Port for the appium instance | optional | Android |
| VNC_PASSWORD | Password needed to connect to VNC Server | optional | VNC |
| OSTYPE | linux or macos/darwin | optional | Android |
| EMULATOR_TIMEOUT | emulator booting up timeoue, default 240 second | optional | Android |
| HW_ACCEL_OVERRIDE | Pass aceel options e.g "-accel on" or "-aceel off" | optional | Android

## Kill the container

- **Run the following command to kill and remove the container:**

docker rm -f androidContainer
No need to rebuild the avds every time you use the docker image/start integration tests, but you will have to rebuild both docker images after a `git pull` the session-appium repository (i.e. updating the integration tests themselves). That step should be very fast though, as everything should be cached by docker. I usually just have one big command to rebuild the changes and restart the container.
4 changes: 4 additions & 0 deletions docker/dl_and_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -ex

/session-appium/docker/dl.sh && /session-appium/docker/test.sh
19 changes: 0 additions & 19 deletions docker/entrypoint.sh

This file was deleted.

2 changes: 1 addition & 1 deletion docker/start_emu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ emulator_name=${EMULATOR_NAME}
device_name=${DEVICE_NAME}

function start_emulator() {
emulator -avd "${emulator_name}" -gpu off -read-only
emulator -avd "${emulator_name}" -read-only -gpu off
printf "${G}==> ${BL}Emulator has ${YE}${EMULATOR_NAME} ${BL}started in headed mode! ${G}<==${NC}""\n"
}

Expand Down
Loading

0 comments on commit d177c62

Please sign in to comment.