# How to Create Multi-Platform Docker Images

By Bobby Iliev, 2024-11-18. https://bobbyiliev.com/post/how-to-create-multi-platform-docker-images/

Building Docker images that work on different CPU architectures like ARM and x86 is becoming more important, especially with the rise of ARM-based machines like M1/M2 Macs and Raspberry Pis. In this guide, I'll show you how to build images that run everywhere!

## What are Multi-Platform Images?

Multi-platform images are Docker images that can run on different CPU architectures. Instead of building separate images for each architecture, we can create a single image that works across:
- AMD64 (regular Intel/AMD computers)
- ARM64 (M1/M2 Macs, newer Raspberry Pis)
- ARMv7 (older Raspberry Pis)
- And more!

## Prerequisites

Before we start, you'll need:
- Docker installed on your machine
- Docker BuildKit enabled (it's enabled by default in newer Docker versions)
- Docker Hub account (or another registry) to push your images

## Setting Up BuildX

BuildX is Docker's tool for building multi-platform images. Let's set it up:

1. Create a new builder instance:
```bash
docker buildx create --name mybuilder --use
```

2. Start the builder:
```bash
docker buildx inspect --bootstrap
```

## Creating a Simple Multi-Platform Image

Let's create a basic web server as an example. First, make a new directory:

```bash
mkdir multi-arch-demo
cd multi-arch-demo
```

Create a simple `index.html`:
```bash
echo "<h1>Hello from $(uname -m)</h1>" > index.html
```

Now create a `Dockerfile`:
```dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```

## Building for Multiple Platforms

Here's the cool part! Build and push the image for multiple platforms in one command:

```bash
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
  -t yourusername/multi-arch-demo:latest \
  --push .
```

This command:
- Builds for three different architectures
- Tags the image with your username
- Pushes it to Docker Hub

## Testing Your Multi-Platform Image

To test your image, you can pull and run it on different devices:

```bash
# On a regular computer (AMD64)
docker run -p 80:80 yourusername/multi-arch-demo:latest

# On a Raspberry Pi (ARM)
docker run -p 80:80 yourusername/multi-arch-demo:latest

# On an M1/M2 Mac (ARM64)
docker run -p 80:80 yourusername/multi-arch-demo:latest
```

Docker automatically picks the right version for each device!

## Real-World Example: Python Application

Let's create a more practical example with a Python application:

Create a simple `app.py`:
```python
from flask import Flask
import platform

app = Flask(__name__)

@app.route('/')
def hello():
    return f"Hello from {platform.machine()}!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
```

Create a `requirements.txt`:
```
flask==2.0.1
```

Create a multi-platform `Dockerfile`:
```dockerfile
FROM --platform=$BUILDPLATFORM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY app.py .
EXPOSE 5000

CMD ["python", "app.py"]
```

Build and push for multiple platforms:
```bash
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
  -t yourusername/python-multi-arch:latest \
  --push .
```

## Tips and Tricks

1. **Cache Management**
```bash
docker buildx build --platform linux/amd64,linux/arm64 \
  --cache-from type=registry,ref=yourusername/myapp:cache \
  --cache-to type=registry,ref=yourusername/myapp:cache \
  -t yourusername/myapp:latest \
  --push .
```

2. **Checking Available Platforms**
```bash
docker buildx ls
```

3. **Inspecting Multi-Platform Images**
```bash
docker buildx imagetools inspect yourusername/multi-arch-demo:latest
```

## Common Issues and Solutions

1. **No space left on device**
Solution: Clean up your builder:
```bash
docker buildx prune
```

2. **QEMU errors**
Solution: Install QEMU support:
```bash
docker run --privileged --rm tonistiigi/binfmt --install all
```

3. **Build taking too long**
Solution: Build only the platforms you need:
```bash
docker buildx build --platform linux/amd64,linux/arm64 \
  -t yourusername/myapp:latest \
  --push .
```

## Conclusion

Multi-platform Docker images are super helpful when you need your application to run on different types of computers. With BuildX, it's pretty straightforward to create images that work everywhere. The key things to remember are:

If you want to see what Docker does between `docker run` and the kernel, try the [How Docker works under the hood](https://devops-daily.com/games/docker-under-the-hood-simulator) simulator on DevOps Daily.

1. Use BuildX for multi-platform builds
2. Test your images on different architectures
3. Only build for the platforms you actually need
4. Keep your images small and efficient

Now you can build Docker images that run on any device, from your laptop to a Raspberry Pi!

If you want to try this out but don't have a server, you can use my DigitalOcean referral link to get a free $200 credit: [Free $200 Credit For DigitalOcean](https://m.do.co/c/2a9bba940f39). This is more than enough to spin up a few Droplets and practice building multi-architecture Docker images!

And if you're new to Docker, I've written a free Docker ebook that covers all the basics - you can check it out at [Introduction to Docker eBook](https://github.com/bobbyiliev/introduction-to-docker-ebook). The ebook will help you get started with Docker before diving into multi-architecture builds!

Give it a try and let me know if you have any questions. You can reach me on Twitter [@bobbyiliev_](https://twitter.com/bobbyiliev_).
