skip to Main Content

I’m new to Docker. I’ve been learning some basics of docker lately.
I’m working on a c++ project that is supposed to work on windows, linux and macos. And there is two arch supported on each OS, x64 and arm64. Since the repo is a private repo, I have to setup my own self-hosted runners for CI/CD.

I’ve setup a docker image (ubuntu x64) that can help me build my source code on a real x64 linux machine.

Ideally, I would like to run x64 Windows, arm64 Windows, x64 Mac, arm64 Mac and arm64 windows on the same linux machine through another 5 different docker images.
But after searching through some basics online, it doesn’t look like this is very realistic. Though, I’m not sure.

There are two purposes that I’m interested in using docker in my CI/CD setup

  • Every time I need to swap a physical machine for my CI/CD, I don’t need to install a bunch of tool chains needed to compile my source code.
  • In the worst case, I will have to run 6 machines 24 7 to keep the service on. Of course, in reality, I guess I can use Arm Mac to compile code on both arm64 and x64 through Rosetta 2. The same could go true for Windows as well. That means I would need 4 machines without the help of docker. It would be great if I can just use one linux PC to build the source code everywhere.

To clarify, when I say build the code, I actually need to run the unit test in the CI/CD to make sure the behavior of the problem stays expected.

I would appreciate it if anyone could offer some suggestions.
I guess I’m not even sure if Docker is supposed to solve these problems in the first place.

I made a few attempts that work so far

  • Build a docker image (ubuntu x64) run it on arm64 mac, x64 linux, x64 windows. It all builds my code and run the unit test fine.
  • Build a docker image (ubuntu arm4) run it on arm64 mac, x64 linux, x64 windows. It all builds my code and run the unit test fine.
  • I’ve also configured a CI/CD workflow that helps building code on x64 ubuntu through my docker image successfully.
  • It does look like I can build a docker image (windows) that so far only runs on a real windows machine. I’ve only tried x64 in this case, not sure about arm64.

What doesn’t seem to work is

  • Github action seems only support docker images on linux builders.
  • Somehow github action won’t even work if the ubuntu imagge is based on arm64, even if the same x64 image works fine.
  • Windows image doesn’t seem to run on a mac or linux machine at all.

Thanks

2

Answers


  1. If you using self-hosted runner all you need to do is to add arch emulation (qemu). Try to run a helloworld docker with different arches. Actually, it’s possible to build a windows apps on Linux images. You just need to setup an enviroment and build cross-compiler(or setup a multiarch compiller, but for ci-cd I highly recommended build your own instance of cross-compiler).

    Login or Signup to reply.
  2. Using Docker in your GitHub CI/CD pipeline can provide significant benefits, especially when dealing with multiple operating systems and architectures. However, there are some inherent limitations when it comes to Docker and cross-platform compatibility. Let’s break down how Docker can help and what approaches you can take to achieve your goals.

    Benefits of Docker in CI/CD

    1. Environment Consistency: Docker ensures that your build and test environments are consistent across different machines. This eliminates the "works on my machine" problem.
    2. Toolchain Management: You can package all necessary dependencies and toolchains in Docker images, making it easy to set up and switch environments without manually installing tools.
    3. Isolation: Docker containers run in isolation, reducing the risk of conflicts between different dependencies and toolchains.

    Challenges and Solutions

    Cross-Platform Builds

    Running Docker images for different OS and architectures on a single host machine is inherently challenging because Docker containers share the host kernel. Here are some specific points:

    1. Linux Containers on Linux: This works well, and you can use Docker images for different Linux distributions and architectures (with limitations).
    2. Windows Containers on Windows: Windows containers require a Windows host.
    3. MacOS Containers: Docker does not natively support running MacOS containers on non-MacOS hosts.

    Given these limitations, your idea of running different OS containers on a single Linux machine is not fully feasible. However, you can still leverage Docker in your CI/CD setup in a few ways:

    Multi-Platform Builds

    1. QEMU for Emulation: You can use QEMU to emulate different architectures. Docker can integrate with QEMU to run multi-architecture builds. For example, you can build and test ARM64 binaries on an x64 host using QEMU. However, performance might be slower compared to running on native hardware.

    2. Docker Buildx: Docker Buildx supports cross-platform builds using QEMU. This allows you to build multi-architecture Docker images. You can set up your GitHub Actions workflow to build for multiple architectures.

      name: CI
      on: [push, pull_request]
      jobs:
        build:
          runs-on: ubuntu-latest
          strategy:
            matrix:
              platform: [linux/amd64, linux/arm64, windows/amd64]
          steps:
          - name: Checkout code
            uses: actions/checkout@v2
          - name: Set up QEMU
            uses: docker/setup-qemu-action@v1
          - name: Set up Docker Buildx
            uses: docker/setup-buildx-action@v1
          - name: Build and push
            uses: docker/build-push-action@v2
            with:
              push: true
              platforms: ${{ matrix.platform }}
              tags: user/app:latest
      

    Self-Hosted Runners

    For scenarios where Docker cannot solve cross-platform issues (like running Windows or MacOS containers on a Linux host), self-hosted runners are necessary:

    1. Self-Hosted Runners: Set up self-hosted runners on different machines (Linux, Windows, MacOS). Use these runners to handle builds and tests for the respective platforms.
    2. Runner Setup:
      • Windows Runners: Install Docker on a Windows machine to run Windows containers.
      • MacOS Runners: Use Mac hardware for MacOS builds and tests.

    Workflow Example

    Here’s a basic example of a GitHub Actions workflow that uses Docker for Linux builds and self-hosted runners for Windows and MacOS builds:

    name: CI
    
    on: [push, pull_request]
    
    jobs:
      linux-build:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Build Docker image
          run: |
            docker build -t myapp:linux .
            docker run myapp:linux ./run-tests.sh
    
      windows-build:
        runs-on: self-hosted
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Build and test
          run: |
            docker build -t myapp:windows .
            docker run myapp:windows ./run-tests.ps1
    
      macos-build:
        runs-on: self-hosted
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Build and test
          run: |
            docker build -t myapp:macos .
            docker run myapp:macos ./run-tests.sh
    

    Summary

    • Use Docker for Linux builds: Utilize Docker to create consistent build environments on Linux.
    • Self-hosted runners for Windows and MacOS: Set up self-hosted runners for Windows and MacOS builds.
    • Cross-platform builds with QEMU and Buildx: For multi-architecture builds, use QEMU and Docker Buildx to compile and test code on different architectures.

    By combining Docker and self-hosted runners, you can create an efficient CI/CD pipeline that handles builds and tests across multiple operating systems and architectures.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search