Tabla de Contenidos
Docker Environment for Compiling APKs with Buildozer and Kivy
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).
1. The Dockerfile (The Build Environment)
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:
- Robust base: Uses Ubuntu 22.04 and disables manual interactions during package installation[cite: 1].
- Essential dependencies: Includes Python 3, Java 17 (
openjdk-17-jdk), build tools likecmake,autoconf, andbuild-essential[cite: 1]. - Non-root user: Buildozer fails if run as root[cite: 1]. The script creates the
kivyuseruser and grants passwordless sudo permissions[cite: 1]. - Pinned versions: Installs the specific
Cython==0.29.36version to ensure compatibility[cite: 1]. - The “Dummy App Trick”: Before mounting your code, the Dockerfile creates a test application to force the Android SDK/NDK download, targeting API 31 and automatically accepting licenses[cite: 1]. This saves hours of downloading every time you start the container.
- Final directory: Everything is set up in
/home/kivyuser/app, which is where you will mount the volume with your actual project[cite: 1].
2. Configuring buildozer.spec
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:
- Identification: The application is named “ia”, belongs to the
org.testdomain, and is on version 0.1[cite: 2]. - Dependencies (Requirements): Specifies Kivy version 2.3.0 and includes critical libraries like
pyjnius(to call the Java API from Python),openssl,certifi(for secure connections), andplyer(to access device hardware)[cite: 2]. - Android Permissions: Requests internet access (
INTERNET) and deep read/write access to device storage (READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE,MANAGE_EXTERNAL_STORAGE)[cite: 2]. - Insecure networks: The
android.allow_cleartext = Trueparameter allows HTTP connections without an SSL certificate[cite: 2].
3. Step-by-step guide to compile your application
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:
Step 1: Build the Docker image
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 .
Step 2: Run the container mounting your code
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
Step 3: Compile the application
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.
Step 4: Retrieve your APK
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!
