Compiling Android applications with Buildozer can be a headache due to system dependencies and Java or Cython versions. To solve this, we have created an Ubuntu-based Docker container that automatically preconfigures the entire environment (Android SDK, NDK, and API 31).
This Dockerfile automates the creation of a clean and secure system to compile your code.
# Use a stable Ubuntu base image
FROM ubuntu:22.04
# Avoid interactive prompts during installation
ENV DEBIAN_FRONTEND=noninteractive
# Update and install system dependencies required by Buildozer and Android SDK/NDK.
# Add 'nano' and extra build tools (autoconf, automake, libtool, pkg-config).
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
python3-venv \
git \
zip \
unzip \
openjdk-17-jdk \
build-essential \
libffi-dev \
libssl-dev \
libltdl-dev \
libsqlite3-dev \
cmake \
sudo \
curl \
nano \
autoconf \
automake \
libtool \
pkg-config \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
# Buildozer throws errors if run as root, so we create a user
RUN useradd -m -s /bin/bash kivyuser \
&& echo "kivyuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# From here on, run everything as the new user
USER kivyuser
# Add the user pip packages path to PATH
ENV PATH="/home/kivyuser/.local/bin:${PATH}"
# Install Buildozer, wheel, and the exact Cython version
RUN pip3 install --user --upgrade pip virtualenv setuptools wheel
RUN pip3 install --user buildozer "Cython==0.29.36"
# --- KEY FIX ---
# Create the folders with our user BEFORE WORKDIR to prevent Docker from creating them as root.
RUN mkdir -p /home/kivyuser/dummy_app /home/kivyuser/app
# --- SDK/NDK AND API 31 PRE-INSTALLATION ---
# Enter the temporary directory
WORKDIR /home/kivyuser/dummy_app
# 1. Initialize Buildozer.
# 2. Modify buildozer.spec to use API 31.
# 3. Accept licenses automatically.
# 4. Create a basic main.py.
# 5. Run buildozer. The "|| true" ensures the image doesn't abort on minor failures.
# 6. Delete the dummy project.
RUN buildozer init \
&& sed -i 's/.*android.api =.*/android.api = 31/' buildozer.spec \
&& sed -i 's/.*android.accept_sdk_license =.*/android.accept_sdk_license = True/' buildozer.spec \
&& echo "print('Preparing Android environment')" > main.py \
&& buildozer android debug || true \
&& rm -rf /home/kivyuser/dummy_app
# Set the final working directory to mount your actual code volume
WORKDIR /home/kivyuser/app
# Default command (keeps the container alive if run interactively)
CMD ["/bin/bash"]
Key points of this image:
openjdk-17-jdk), build tools like cmake, autoconf, and build-essential[cite: 1].kivyuser user and grants passwordless sudo permissions[cite: 1].Cython==0.29.36 version to ensure compatibility[cite: 1]./home/kivyuser/app, which is where you will mount the volume with your actual project[cite: 1].
For this container to work correctly with your application, your buildozer.spec file must be properly configured. Here is an optimized example for an app with network and storage requirements:
[app] title = ia package.name = ia package.domain = org.test source.dir = . version = 0.1 requirements = python3, kivy==2.3.0, android, pyjnius, openssl, certifi, plyer orientation = portrait android.permissions = INTERNET, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, MANAGE_EXTERNAL_STORAGE android.allow_cleartext = True
Explanation of parameters:
org.test domain, and is on version 0.1[cite: 2].pyjnius (to call the Java API from Python), openssl, certifi (for secure connections), and plyer (to access device hardware)[cite: 2].INTERNET) and deep read/write access to device storage (READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, MANAGE_EXTERNAL_STORAGE)[cite: 2].android.allow_cleartext = True parameter allows HTTP connections without an SSL certificate[cite: 2].
Once you have the Dockerfile and the buildozer.spec along with your source code (like your main.py file), it is time to compile. Open your terminal in the folder where you have these files and follow these steps:
First, you must create the local Docker image. This will take some time the first time because it will download the entire base system and the Android SDK.
docker build -t buildozer-env .
Now we will start the container. The trick here is to use -v $(pwd):/home/kivyuser/app. This “connects” your computer's current folder with the working folder inside Docker. This way, everything Buildozer generates will be saved directly to your hard drive.
docker run -it -v $(pwd):/home/kivyuser/app buildozer-env
Once you run the previous command, your terminal will change and you will be inside the Docker container as the kivyuser user. To generate the APK, simply run:
buildozer android debug
The process will start. You will see it download Python dependencies and compile the code. If everything is correct, at the end you will see a success message indicating that the APK has been generated.
Since we mounted the volume in step 2, you don't need to do anything special to extract the file from the container. Simply type exit to leave Docker.
exit
If you look in your local folder (the one on your computer), you will see that a new folder named bin/ has appeared. Inside it, your .apk file will be ready to be installed on your phone or uploaded to your website!