Docker
macOS
linux/amd64
containerization
cross-platform compatibility

Forcing docker to use linux/amd64 platform by default on macOS

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

To force Docker to default to linux/amd64 on macOS with Apple Silicon, set the DOCKER_DEFAULT_PLATFORM environment variable in your shell profile. This is a single line that makes every docker run, docker build, and docker compose command target x86_64 unless you explicitly override it.

bash
# Add to ~/.zshrc (or ~/.bashrc)
export DOCKER_DEFAULT_PLATFORM=linux/amd64

After saving, run source ~/.zshrc or open a new terminal. Every Docker command in that shell will now default to the amd64 platform.

Why This Is Necessary on Apple Silicon

Apple's M-series chips use the ARM64 (aarch64) architecture. Docker on Apple Silicon defaults to pulling and building linux/arm64 images. This causes problems when:

  • The image you need only publishes an amd64 variant (common with older or niche images).
  • A native dependency inside the image was compiled for x86_64 and has no ARM build.
  • Your CI/CD pipeline runs on x86_64 Linux servers, and you want local builds to match production exactly.
  • A multi-service docker-compose.yml mixes images where some have ARM support and others do not.

When Docker cannot find an ARM variant of the image, you see errors like:

text
WARNING: The requested image's platform (linux/amd64) does not match
the detected host platform (linux/arm64/v8)

Or worse, the container starts but crashes at runtime because a binary inside it was compiled for the wrong architecture.

Three Ways to Force the Platform

1. Environment variable (global default)

This is the recommended approach for developers who consistently need amd64 images:

bash
# ~/.zshrc
export DOCKER_DEFAULT_PLATFORM=linux/amd64

Every Docker command inherits this setting. You can override it per-command with --platform linux/arm64 when needed.

2. Per-command flag

For one-off commands where you want to target a specific platform without changing the global default:

bash
1# Pull an amd64 image explicitly
2docker pull --platform linux/amd64 mysql:8.0
3
4# Run with platform override
5docker run --platform linux/amd64 --rm mysql:8.0 mysql --version
6
7# Build for amd64
8docker build --platform linux/amd64 -t myapp:latest .

3. Docker Compose platform field

In docker-compose.yml, you can specify the platform per service:

yaml
1services:
2  database:
3    image: mysql:8.0
4    platform: linux/amd64
5    environment:
6      MYSQL_ROOT_PASSWORD: dev
7    ports:
8      - '3306:3306'
9
10  app:
11    build:
12      context: .
13      dockerfile: Dockerfile
14      platforms:
15        - linux/amd64
16    ports:
17      - '8080:8080'
18    depends_on:
19      - database

This is useful when only specific services need amd64 and others run fine on ARM.

Comparison of Approaches

ApproachScopePersistenceOverride Needed
DOCKER_DEFAULT_PLATFORM env varAll Docker commands in the shellUntil shell profile is changed--platform linux/arm64 per command
--platform flagSingle commandNoneNot applicable
Compose platform fieldSingle servicePer projectOverride in compose override file
Dockerfile FROM --platformSingle build stagePer DockerfileRebuild required

Setting Platform in the Dockerfile

You can pin the platform directly in the Dockerfile so it is architecture-explicit regardless of the host machine:

dockerfile
1FROM --platform=linux/amd64 node:20-slim AS builder
2WORKDIR /app
3COPY package*.json ./
4RUN npm ci
5COPY . .
6RUN npm run build
7
8FROM --platform=linux/amd64 node:20-slim
9WORKDIR /app
10COPY --from=builder /app/dist ./dist
11COPY --from=builder /app/node_modules ./node_modules
12CMD ["node", "dist/index.js"]

This approach is useful when the Dockerfile will be built on both ARM and x86_64 machines but the resulting image must always be amd64 (for example, deploying to x86_64 cloud servers).

Performance Impact of Emulation

Running amd64 containers on Apple Silicon requires QEMU emulation, which Docker Desktop includes automatically. The performance cost is real and measurable.

OperationNative ARM64Emulated amd64Slowdown
Node.js build (npm ci)30s90-120s3-4x
Python pip install20s60-80s3-4x
Database queries (MySQL)Baseline1.5-2x slower1.5-2x
File I/O heavy workloadsBaseline2-5x slower2-5x

For daily development, a 3-4x slowdown on builds is noticeable but manageable. For running databases or I/O-intensive services, consider using the native ARM variant when one exists and only forcing amd64 for services that require it.

Using Rosetta for Better Emulation Performance

Docker Desktop 4.25 and later supports Apple's Rosetta 2 for x86_64 emulation, which is significantly faster than QEMU for many workloads.

To enable it:

  1. Open Docker Desktop Settings.
  2. Go to General.
  3. Check "Use Rosetta for x86_64/amd64 emulation on Apple Silicon."
  4. Click Apply and Restart.

Rosetta typically cuts the emulation overhead in half compared to QEMU, though results vary by workload.

Multi-Platform Builds with Buildx

If you need to produce images for both architectures (for example, publishing a library), Docker Buildx handles this:

bash
1# Create a builder that supports multiple platforms
2docker buildx create --name multiplatform --use
3
4# Build and push for both architectures
5docker buildx build \
6  --platform linux/amd64,linux/arm64 \
7  -t myregistry/myapp:latest \
8  --push .

This builds the image twice (once per architecture) and pushes a manifest list so that Docker automatically pulls the correct variant on any machine.

Verifying the Active Platform

After setting the environment variable, verify it is working:

bash
1# Check the environment variable
2echo $DOCKER_DEFAULT_PLATFORM
3
4# Verify the platform of a running container
5docker run --rm alpine uname -m
6# Expected output: x86_64 (if amd64 is forced)
7# Would show: aarch64 (if running natively on ARM)
8
9# Check the platform of a pulled image
10docker inspect --format '{{.Os}}/{{.Architecture}}' alpine:latest

When to Use ARM Native Instead

Forcing amd64 everywhere is a blunt instrument. As ARM support in the Docker ecosystem has matured, many popular images now publish ARM variants. Consider using native ARM images when:

  • The image has an official ARM variant (most major images do: Node, Python, PostgreSQL, Redis, Nginx).
  • You are not deploying to x86_64 servers (or your CI handles the architecture difference).
  • Build or runtime performance matters (native is 3-4x faster than emulated).

A pragmatic approach is to force amd64 only for the specific services that need it and let everything else run natively.

Common Pitfalls

Setting the env var but not reloading the shell. After adding DOCKER_DEFAULT_PLATFORM to ~/.zshrc, you must run source ~/.zshrc or open a new terminal. The old shell session still uses the previous setting.

Forgetting to pull fresh images after changing platforms. If you previously pulled mysql:8.0 as an ARM image, Docker may use the cached ARM layer. Run docker pull --platform linux/amd64 mysql:8.0 to force a fresh pull, or remove the old image first.

Applying amd64 globally when only one service needs it. This slows down every container unnecessarily. Use per-service platform in Compose or per-command --platform flags to limit the impact.

Ignoring Rosetta. If you are on Docker Desktop 4.25 or later and running emulated amd64 containers, enabling Rosetta can cut emulation overhead significantly. There is no downside to turning it on.

Assuming emulation is identical to native. Some workloads expose subtle differences under emulation, particularly those involving low-level system calls, JIT compilation, or memory-mapped I/O. If you hit unexplained crashes only in emulated containers, test on a native amd64 machine to isolate the cause.

Summary

  • Set export DOCKER_DEFAULT_PLATFORM=linux/amd64 in ~/.zshrc to make Docker default to x86_64 images on Apple Silicon.
  • Use --platform linux/amd64 on individual commands for one-off overrides.
  • Use the platform field in docker-compose.yml for per-service control.
  • Pin FROM --platform=linux/amd64 in Dockerfiles when the image must always target x86_64 regardless of the build host.
  • Enable Rosetta in Docker Desktop for faster emulation.
  • Emulated amd64 runs 2-4x slower than native ARM. Only force amd64 for services that genuinely require it.
  • Use docker buildx for multi-platform builds when publishing images that need to run on both architectures.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.