{
  "manifest_version": "1",
  "slug": "docker-host",
  "title": "Docker Engine",
  "headline": "Use exe.dev as a remote Docker host",
  "description": "Point docker context or DOCKER_HOST at an exe.dev VM over SSH: native amd64 builds from your Mac, Compose, and a warm build cache off your laptop.",
  "category": "dev-tools",
  "tags": [
    "remote docker host",
    "docker context",
    "DOCKER_HOST ssh",
    "docker buildx",
    "docker compose",
    "amd64 builds on apple silicon"
  ],
  "url": "https://exe.dev/deploy/docker-host",
  "markdown_url": "https://exe.dev/deploy/docker-host.md",
  "upstream": {
    "website": "https://docs.docker.com/engine/",
    "source": "https://github.com/moby/moby",
    "docs": "https://docs.docker.com/engine/manage-resources/contexts/",
    "license": "Apache-2.0"
  },
  "example_vm_name": "my-docker-host",
  "time": "10 minutes",
  "stack": [
    {
      "name": "Docker Engine 29",
      "detail": "preinstalled on exeuntu, with Buildx and Compose; starts at boot",
      "data": "/var/lib/docker"
    },
    {
      "name": "SSH",
      "detail": "your docker CLI runs `docker system dial-stdio` over exe.dev's SSH; no Docker port is opened"
    },
    {
      "name": "Daily prune",
      "detail": "a systemd timer that clears unused images and old build cache"
    }
  ],
  "access": [
    {
      "url": "ssh://my-docker-host.exe.xyz",
      "who": "private",
      "what": "The Docker API, for your docker CLI, over SSH with your exe.dev key"
    },
    {
      "url": "https://my-docker-host.exe.xyz:8080/",
      "who": "private",
      "what": "Any HTTP port you publish from 3000 to 9999 (8080 in the examples)"
    }
  ],
  "delivers": [
    "Docker Engine enabled at boot, so containers with a restart policy come back after a reboot.",
    "Docker usable by `exedev` without sudo, which is the account your docker CLI uses over SSH.",
    "Container logs capped at 30 MB each, and a daily prune of unused images and build cache."
  ],
  "owner_runs_after": [
    "ssh my-docker-host.exe.xyz docker version",
    "docker context create exe --docker \"host=ssh://my-docker-host.exe.xyz\"",
    "docker context use exe"
  ],
  "deployable": true,
  "deploy": {
    "new_vm_url": "https://exe.dev/new?prompt=Set%20up%20Docker%20Engine%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe.dev%2Fdeploy%2Fdocker-host.md%20from%20top%20to%20bottom.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-docker-host.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-docker-host.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20Docker%20Engine%20enabled%20at%20boot%2C%20so%20containers%20with%20a%20restart%20policy%20come%20back%20after%20a%20reboot.%0A-%20Docker%20usable%20by%20%60exedev%60%20without%20sudo%2C%20which%20is%20the%20account%20your%20docker%20CLI%20uses%20over%20SSH.%0A-%20Container%20logs%20capped%20at%2030%20MB%20each%2C%20and%20a%20daily%20prune%20of%20unused%20images%20and%20build%20cache.%0A%0ARead%20the%20whole%20recipe%2C%20including%20closed%20details%2C%20but%20run%20only%20%22Set%20up%0Athe%20VM%20by%20hand%22%2C%20skipping%20VM%20creation.%20Everything%20else%20%28docker%20context%2C%0A~%2F.ssh%2Fconfig%2C%20buildx%2C%20Compose%2C%20ssh%20-L%29%20runs%20on%20the%20owner%27s%20computer%2C%0Anot%20on%20this%20VM.%20Use%20the%20preinstalled%20Docker%3B%20do%20not%20install%20Docker%20from%0Aanother%20source%2C%20change%20sshd%2C%20or%20expose%20the%20Docker%20API%20on%20TCP.%20Do%20not%0Ainstall%20qemu-user-static%20unless%20the%20owner%20asks%20for%20arm64%20builds.%0AVerify%3A%20docker.service%20is%20enabled%3B%20%60sudo%20-iu%20exedev%20docker%20info%60%20works%3B%0Aa%20new%20container%20gets%20max-size%2010m%20and%20max-file%203%20log%20options%3B%0Adocker-prune.timer%20is%20enabled%20and%20docker-prune.service%20last%20ran%20with%0Aresult%20%22success%22.%20Leave%20no%20test%20containers%20behind.%20Do%20not%20reboot.%0AFinish%20with%20this%20VM%27s%20CPUs%2C%20memory%2C%20and%20free%20disk%20%28nproc%2C%20free%20-h%2C%0Adf%20-h%20%2F%29%2C%20the%20%60ssh%20exe.dev%20resize%60%20command%20from%20%22Room%20to%20grow%22%20with%0Athis%20VM%27s%20name%2C%20and%20the%20commands%20for%20the%20owner%27s%20computer.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open%20and%20these%20commands%2C%20which%20only%20I%20can%20run%2C%20from%20my%20own%20computer%20%28with%20this%20VM%27s%20name%20in%20them%29%3A%0A%20%20ssh%20my-docker-host.exe.xyz%20docker%20version%0A%20%20docker%20context%20create%20exe%20--docker%20%22host%3Dssh%3A%2F%2Fmy-docker-host.exe.xyz%22%0A%20%20docker%20context%20use%20exe%0A",
    "terminal": "curl -fsSL https://exe.dev/deploy/docker-host/prompt.txt | ssh exe.dev new --prompt=/dev/stdin",
    "prompt": "Set up Docker Engine on this VM by following the exe.dev recipe at https://exe.dev/deploy/docker-host.md from top to bottom.\n\nThe recipe's example VM name is my-docker-host. This VM's name is the output of `hostname`: use it wherever the recipe writes my-docker-host. Skip the step that creates the VM; you are on it.\n\nYou are done when all of these are true. Check each one yourself:\n- Docker Engine enabled at boot, so containers with a restart policy come back after a reboot.\n- Docker usable by `exedev` without sudo, which is the account your docker CLI uses over SSH.\n- Container logs capped at 30 MB each, and a daily prune of unused images and build cache.\n\nRead the whole recipe, including closed details, but run only \"Set up\nthe VM by hand\", skipping VM creation. Everything else (docker context,\n~/.ssh/config, buildx, Compose, ssh -L) runs on the owner's computer,\nnot on this VM. Use the preinstalled Docker; do not install Docker from\nanother source, change sshd, or expose the Docker API on TCP. Do not\ninstall qemu-user-static unless the owner asks for arm64 builds.\nVerify: docker.service is enabled; `sudo -iu exedev docker info` works;\na new container gets max-size 10m and max-file 3 log options;\ndocker-prune.timer is enabled and docker-prune.service last ran with\nresult \"success\". Leave no test containers behind. Do not reboot.\nFinish with this VM's CPUs, memory, and free disk (nproc, free -h,\ndf -h /), the `ssh exe.dev resize` command from \"Room to grow\" with\nthis VM's name, and the commands for the owner's computer.\n\nFinish with the URLs I should open and these commands, which only I can run, from my own computer (with this VM's name in them):\n  ssh my-docker-host.exe.xyz docker version\n  docker context create exe --docker \"host=ssh://my-docker-host.exe.xyz\"\n  docker context use exe\n",
    "prompt_url": "https://exe.dev/deploy/docker-host/prompt.txt"
  },
  "updated": "2026-10-17",
  "related": [
    "docker-compose",
    "github-actions-runner",
    "code-server",
    "dev-test-prod",
    "forgejo",
    "gitea"
  ],
  "alternatives": [
    "Docker Desktop",
    "Colima"
  ]
}
