Run Docker on an AMD Hackintosh — no Docker Desktop, no Hypervisor.framework, no bullshit.
Docker Desktop requires Apple's Hypervisor.framework (com.apple.security.hypervisor). On a genuine Intel or Apple Silicon Mac, this works fine. On an AMD Hackintosh, it crashes immediately and silently — no useful error, just failure.
Lima (the VM layer under Colima) hardcodes -machine q35,accel=hvf into every QEMU launch. HVF is Apple's hypervisor acceleration. AMD Hackintoshes don't have it. End of story — unless you do what this repo does.
We use QEMU + Colima with a compiled C wrapper that intercepts Lima's QEMU launch command and silently swaps accel=hvf for accel=tcg,thread=multi before the real QEMU binary ever sees it.
TCG (Tiny Code Generator) is QEMU's pure software emulation mode. It doesn't need Hypervisor.framework. It doesn't need a real Mac. It just works.
Lima generates: qemu-system-x86_64 -machine q35,accel=hvf ...
Wrapper intercepts: ^^^^^^^^^^^
Wrapper passes: qemu-system-x86_64 -machine q35 -accel tcg,thread=multi ...
The wrapper is a compiled binary (not a shell script) so it can be codesigned with the hypervisor entitlement — which Lima requires to trust the QEMU binary.
| Requirement | Notes |
|---|---|
| macOS Sequoia (15.x) | Tested on 15.7.5 |
| AMD CPU (any) | Ryzen, Threadripper, etc. |
| Hackintosh EFI | OpenCore recommended |
| Homebrew | Package manager |
| Xcode Command Line Tools | For gcc — run xcode-select --install |
Not tested on Intel Hackintosh. It may work, but you probably don't need it — Intel Macs support HVF natively. If you try it, open an issue and let me know.
git clone https://github.com/osx86-ijb/docker-amd-hackintosh.git
cd docker-amd-hackintosh
chmod +x install.sh
./install.shThat's it. Grab a coffee — the first boot takes 2–4 minutes because TCG is pure software emulation and has to cold-start a full Linux VM from scratch.
- Installs
qemu,colima,docker,docker-compose,docker-credential-helpervia Homebrew - Compiles a C wrapper at
~/bin/qemu-system-x86_64that intercepts and patches the QEMU launch flags - Codesigns the wrapper with the
com.apple.security.hypervisorentitlement - Symlinks the QEMU EFI firmware so Lima can find it relative to the wrapper
- Writes a minimal Colima config using
cpuType: qemu64(avoids host CPU passthrough issues) - Starts the Colima VM
- Forwards the Docker socket from inside the VM to your host via SSH
- Installs a
launchdagent to keep the socket forwarded across reboots - Registers Colima as a brew service for auto-start on login
brew install qemu colima docker docker-compose docker-credential-helpermkdir -p ~/.docker
cat > ~/.docker/config.json << 'EOF'
{
"cliPluginsExtraDirs": [
"/usr/local/lib/docker/cli-plugins"
]
}
EOFmkdir -p ~/bin
cat > /tmp/qemu_wrapper.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char **newargs = malloc(sizeof(char*) * (argc + 4));
int j = 0;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "q35,accel=hvf") == 0) {
newargs[j++] = "q35";
} else {
newargs[j++] = argv[i];
}
if (i > 0 && strcmp(argv[i-1], "-machine") == 0
&& strcmp(argv[i], "q35,accel=hvf") == 0) {
newargs[j++] = "-accel";
newargs[j++] = "tcg,thread=multi";
}
}
newargs[j] = NULL;
newargs[0] = "/usr/local/bin/qemu-system-x86_64";
execv("/usr/local/bin/qemu-system-x86_64", newargs);
return 1;
}
EOF
gcc -o ~/bin/qemu-system-x86_64 /tmp/qemu_wrapper.cSign it:
cat > /tmp/hypervisor.entitlements << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.hypervisor</key>
<true/>
</dict>
</plist>
EOF
codesign -s - --entitlements /tmp/hypervisor.entitlements ~/bin/qemu-system-x86_64echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
export PATH="$HOME/bin:$PATH"Lima looks for firmware relative to the QEMU binary path. Since our wrapper is in ~/bin, we need to make the firmware findable there too:
mkdir -p ~/.local/share/qemu
ln -s /usr/local/share/qemu/edk2-x86_64-code.fd ~/.local/share/qemu/edk2-x86_64-code.fdmkdir -p ~/.colima/default
cat > ~/.colima/default/colima.yaml << 'EOF'
cpu: 4
memory: 8
disk: 60
vmType: qemu
arch: x86_64
cpuType: qemu64
runtime: docker
mountType: sshfs
EOFWhy
cpuType: qemu64? Using the defaulthostCPU type on an AMD Hackintosh tells QEMU to pass through your actual CPU, which can trigger HVF attempts.qemu64is a generic baseline x86_64 virtual CPU that plays nicely with TCG.
colima startThe VM will boot. Colima may exit with an error about Docker state — that's a known first-boot quirk. As long as you see the 4 SSH requirements satisfied in the output, the VM is up.
Colima's daemon didn't finish, so we forward the socket manually:
rm -f ~/.colima/default/docker.sock
ssh -F ~/.colima/_lima/colima/ssh.config \
-o ControlMaster=no \
-o ControlPath=none \
-L $HOME/.colima/default/docker.sock:/run/docker.sock \
-N lima-colima &docker ps
docker run --rm hello-worldInstall the LaunchAgent for persistent socket forwarding:
cat > ~/Library/LaunchAgents/com.docker.sock-forward.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.docker.sock-forward</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>rm -f $HOME/.colima/default/docker.sock; /usr/bin/ssh -F $HOME/.colima/_lima/colima/ssh.config -o ControlMaster=no -o ControlPath=none -L $HOME/.colima/default/docker.sock:/run/docker.sock -N lima-colima</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/docker-sock-forward.log</string>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.docker.sock-forward.plist
brew services start colimaDocker Desktop uses com.apple.security.hypervisor — a macOS entitlement that grants access to Apple's Hypervisor.framework. On a genuine Apple Mac, this is fine. On an AMD Hackintosh, the kernel-level hypervisor support either isn't present or isn't properly exposed. The result: instant silent crash.
Colima uses Lima under the hood to manage VMs. Lima detects macOS and unconditionally passes -machine q35,accel=hvf to QEMU. This flag tells QEMU to use HVF acceleration. There's no config option to disable it — it's hardcoded in Lima's Go source at runtime.
Lima checks that the QEMU binary is properly codesigned with the hypervisor entitlement before launching it. A shell script can't be codesigned. A compiled binary can.
The wrapper sits in ~/bin/qemu-system-x86_64, which is first in PATH. When Lima calls qemu-system-x86_64, it gets our wrapper. The wrapper:
- Iterates over all arguments Lima passes
- When it sees
-machine q35,accel=hvf, replaces it with-machine q35 - Immediately after that argument, injects
-accel tcg,thread=multias separate flags execvs the real QEMU binary at/usr/local/bin/qemu-system-x86_64with the patched args
The thread=multi flag enables multi-threaded TCG, which significantly improves performance.
Colima's own daemon process normally handles forwarding the Docker socket from inside the VM to your host. On first boot with this setup, Colima's daemon exits before completing that step due to a state-tracking issue. The SSH port forward we set up replicates exactly what Colima's daemon would have done — it's the same mechanism Colima uses internally.
TCG is slower than native virtualization. This is unavoidable — we're doing pure software CPU emulation. In practice:
- Container startup: slightly slower than Docker Desktop on a real Mac
- Running workloads: near-native once the container is up (workloads run on the Linux kernel inside the VM, not through emulation)
- Image pulls: network-speed limited, effectively no difference
- Build times: somewhat slower for CPU-intensive builds
For most development workflows — web servers, databases, CI runners, etc. — the performance is perfectly usable. If you're doing heavy compilation inside Docker, expect maybe 2–3x slower than a native setup.
The socket forward isn't active. Run:
rm -f ~/.colima/default/docker.sock
ssh -F ~/.colima/_lima/colima/ssh.config \
-o ControlMaster=no \
-o ControlPath=none \
-L $HOME/.colima/default/docker.sock:/run/docker.sock \
-N lima-colima &Colima may start before the SSH config is ready. Give it a moment, then:
colima startCheck VM status:
LIMA_HOME=~/.colima/_lima limactl listThe firmware symlink is missing or broken:
mkdir -p ~/.local/share/qemu
ln -sf /usr/local/share/qemu/edk2-x86_64-code.fd ~/.local/share/qemu/edk2-x86_64-code.fdRe-sign the wrapper:
codesign -s - --entitlements /tmp/hypervisor.entitlements ~/bin/qemu-system-x86_64If /tmp/hypervisor.entitlements was cleaned up, recreate it first (see Step 3 above).
The VM is up but the socket forward is dead. Kill and restart:
launchctl unload ~/Library/LaunchAgents/com.docker.sock-forward.plist
launchctl load ~/Library/LaunchAgents/com.docker.sock-forward.plistLIMA_HOME=~/.colima/_lima limactl list
LIMA_HOME=~/.colima/_lima limactl shell colima sudo systemctl status docker# Stop everything
colima stop
brew services stop colima
launchctl unload ~/Library/LaunchAgents/com.docker.sock-forward.plist
# Remove files
rm -f ~/bin/qemu-system-x86_64
rm -f ~/.local/share/qemu/edk2-x86_64-code.fd
rm -f ~/Library/LaunchAgents/com.docker.sock-forward.plist
rm -rf ~/.colima
# Uninstall packages (optional)
brew uninstall docker docker-compose docker-credential-helper colima qemuFound a bug? Got it working on a different setup? Open an issue or PR. Especially interested in:
- Results on different AMD CPUs (Threadripper, older Ryzen generations, etc.)
- Results on different macOS versions
- Performance benchmarks vs native setups
- Any Lima/Colima version updates that break or fix things
MIT — do whatever you want with it. If this saved you hours of pain, a star on the repo is appreciated.
Built through pure trial, error, and stubbornness. If Apple doesn't want you running their OS on AMD hardware, that's their problem.