Skip to main content

Running your build locally in Docker

Abstract

You can run a Bitrise build in Docker on your own machines: you need Docker, the Bitrise CLI, and a Bitrise Docker image.

Docker Hub rate limit

From July 15, 2024, rate limiting will apply on downloads from Docker Hub. If you pull a Docker image from Docker Hub without authentication during a Bitrise build on our Linux machines, you may run into issues because of rate limiting.

Bitrise is mirroring some of the popular public docker images, but to avoid these potential issues with rate limiting, you can either:

  • Authenticate your Docker image pulling requests towards Docker Hub. For the details and Docker's full policy, refer to Docker Hub rate limit.

  • Switch to another Docker registry to store your images.

To be able to run your Linux stack builds locally, you’ll need docker:

In this guide, we’ll use this Bitrise Android sample project.

Large images ahead

The official Bitrise Docker images are quite large because they include a wide variety of preinstalled tools. You’ll need at least 20-25 GB FREE DISC SPACE!

If you’re not familiar with the Bitrise CLI, you should try that first. You don’t have to master the CLI, if you know what bitrise run WORKFLOW does, that should be enough for this tutorial.

Downloading docker images

  1. Install docker.

  2. Make sure you have your bitrise.yml in your repository.

    You don’t have to commit it, but the file must exist in your repository’s root directory.

  3. cd into your repository’s directory on your Mac/Linux.

  4. Pull the image from its registry:

    docker pull bitriseio/android-20.04:latest
    
  5. Run the following command:

    docker run --privileged --env CI=false --volume "$(pwd):/bitrise/src" --volume "/var/run/docker.sock:/var/run/docker.sock" --rm quay.io/bitriseio/android-20.04:latest bitrise run WORKFLOW`       

    If you want to just jump into the container and experiment inside, you can replace --rm quay.io/bitriseio/android-20.04:latest bitrise run WORKFLOW with -it quay.io/bitriseio/android-20.04:latest bash to start an interactive bash shell inside the container. For example:

    docker run --privileged --env CI=false --volume "$(pwd):/bitrise/src" --volume "/var/run/docker.sock:/var/run/docker.sock" -it quay.io/bitriseio/android-20.04:latest bash
    

    In general, if your project is an Android project but you don’t use Android NDK, to preserve precious disk space, you should use the quay.io/bitriseio/android docker image. You can find other official Bitrise docker images on our Quay page. In this example, we’re using the quay.io/bitriseio/android one.

  6. Download docker images from the Quay:

    docker pull bitriseio/android-20.04:latest`
    

    Be aware that this can take quite a bit of time, as this image is over 10 GB. If the download fails or hangs, you can restart it any time by running the same command again.

  7. Download your Bitrise build configuration (bitrise.yml) to the root directory of your repository.

    You can download your project’s bitrise.yml from the bitrise.yml tab of your Workflow Editor on bitrise.io.

  8. In your Terminal / Command Line go to (cd) the root directory of your repository. Check if your bitrise.yml is at this location.

If you try to reproduce an issue, you should git clone your repository into a NEW DIRECTORY, so that the directory will only contain the files which are committed into the repository! It’s a frequent reproducibility issue that you try to run the commands in your normal working directory, where you most likely have files which are not committed into your repository, for example, files which are in .gitignore.

Running the build

Run your build with the following command:

docker run --privileged --env CI=false --volume "$(pwd):/bitrise/src" --volume "/var/run/docker.sock:/var/run/docker.sock" --rm quay.io/bitriseio/android:latest bitrise run WORKFLOW
  • --rm quay.io/bitriseio/android:latest bitrise run WORKFLOW

    with -it quay.io/bitriseio/android:latest bash to start an interactive bash shell inside the container.

    For example:

    docker run --privileged --env CI=false --volume "$(pwd):/bitrise/src" --volume "/var/run/docker.sock:/var/run/docker.sock" -it quay.io/bitriseio/android:latest bash`.       

    This command will share the current directory (the directory of your repository) as a shared volume with the docker container, and will make it available inside the container at the path /bitrise/src.

    After this, you can run bitrise run WORKFLOW, which will run the workflow inside the container. To exit from the container, just run exit.

  • Don’t forget to replace WORKFLOW with the actual ID of your workflow in your bitrise.yml, with something like primary!

  • The --env CI=false flag sets the environment variable CI to false - this will make Bitrise CLI skip certain steps that only make sense to run in a CI environment. For example, our Git Clone Step - you already have your code, so there’s no need to git clone it again inside the docker container (that’s why we shared the code directory as a --volume).

  • The --rm flag tells docker to discard the container after the docker run command finishes. This means that if you run the command again, the only thing which will persist between the docker run .. commands are the files stored at the shared --volume (in your repository’s directory). Every other file that is generated into a temp or any other location will be discarded / won’t be kept.

    If you want to debug the container after a failed build, feel free to remove the --rm flag, and check out a Docker tutorial about how you can connect to an existing docker container. Please note that simply running the command again will not use the same container, but will create a new one!

  • The --privileged flag allows access control of the host from the docker container, so you should never use this flag unless you trust the docker image you will use! This flag is required for allowing VPNs to work (to change network configs of the host), for example.

  • The --volume "/var/run/docker.sock:/var/run/docker.sock" flag exposes the docker socket from the host for the container - this is required if you want to run other docker containers from within the container, or if you want to run any docker command during your build / inside the container.