Симптом: SSH на удалённый Mac работает, но docker ps сообщает, что daemon недоступен, Socket отсутствует или контейнеры не поднимаются. Самое быстрое решение: не переустанавливайте Docker Desktop сразу — сначала проверьте состояние приложения, вошедшего пользователя, Docker Context и путь к Socket, а первоначальную авторизацию при необходимости выполните через VNC.

По официальным требованиям Docker Desktop для Mac нужен поддерживаемый выпуск macOS и не менее 4 ГБ оперативной памяти; при этом приложение работает как пользовательский процесс, а не как обычный системный daemon. Поэтому доступный SSH ещё не доказывает, что backend Docker Desktop запущен и готов принимать команды. Сверяйте текущие требования с официальной страницей установки Docker Desktop для Mac.

Эта статья предназначена для трёх групп:

  • разработчиков, которые подключаются с Windows или Linux к удалённому Mac по SSH;
  • DevOps-инженеров, обслуживающих узел для сборки, тестирования и публикации образов;
  • администраторов, решающих, подходит ли текущий Mac для длительной контейнерной работы после перезагрузок.

Сначала разделите сбой на четыре уровня

Не начинайте с удаления приложения. Одна и та же фраза «Docker не работает» может означать четыре разных состояния, и для каждого нужен свой тест.

<
Наблюдаемое состояниеЧто проверить первымКакой вывод сделать
Команда docker не найденаcommand -v docker, echo "$PATH"CLI отсутствует в PATH или SSH запускает другую оболочку
Docker Desktop не запущенdocker desktop status, ps aux \grep -i dockerПриложение или backend не стартовали
CLI не видит daemondocker context ls, docker info, ls -l ~/.docker/run/docker.sockОшибка Context, пользователя или Socket
Контейнер запускается, но сервис недоступенdocker ps, docker logs, проверка порта и сетиDesktop работает, проблема находится в приложении или маршрутизации
Команды docker desktop start, status, restart, stop, logs и diagnose предназначены для управления Desktop из терминала. Их наличие зависит от установленной версии CLI, поэтому сначала проверьте:
docker desktop version
docker version
docker info

Актуальный синтаксис и доступные подкоманды описаны в официальной документации Docker Desktop CLI.

Что означает успешный SSH

Команда:

ssh developer@mac-host

проверяет только Remote Login и возможность создать удалённую shell-сессию. Она не проверяет:

  • был ли тот же пользователь авторизован в графической сессии macOS;
  • запустился ли Docker Desktop после входа;
  • переключился ли CLI на актуальный Context;
  • существует ли пользовательский Socket;
  • доступны ли Keychain, прокси и разрешения для приватного реестра.
Apple описывает Remote Login как доступ к Mac через SSH или SFTP, но это отдельный механизм от запуска приложений при входе пользователя. Для проверки самой службы используйте [документацию Apple по Remote Login](https://support.apple.com/en-asia/guide/mac-help/mchlp1066/mac).

Первый этап: подтвердите установку и архитектуру

Проблема может появиться после обновления macOS, замены установочного пакета или установки неподходящей сборки. Сначала соберите факты, не меняя систему:

uname -m
sw_vers
test -d /Applications/Docker.app && echo "Docker.app найден"
ls -l /Applications/Docker.app/Contents/Resources/bin/docker
command -v docker
docker --version

На Apple Silicon команда uname -m обычно возвращает arm64; на Intel — x86_64. Это не означает автоматически, что контейнерный образ совместим с архитектурой узла: образ может быть одноплатформенным, а сборка — требовать явного --platform. Однако архитектура помогает отделить ошибку пакета от ошибки запуска.

Проверьте три независимых условия:

  1. Каталог /Applications/Docker.app существует и содержит исполняемые файлы.
  2. docker находится в текущем PATH, которым пользуется именно SSH-сессия.
  3. Версия macOS входит в диапазон, поддерживаемый текущим выпуском Desktop.
Docker указывает, что Desktop для Mac поддерживает текущий и два предыдущих основных выпуска macOS, а минимальное требование по памяти составляет 4 ГБ. Эти параметры нужно сверять с актуальной страницей установки перед обновлением, а не переносить из старого runbook.

Если CLI установлен в пользовательский каталог, например $HOME/.docker/bin, добавьте его в профиль нужной оболочки:

echo 'export PATH="$HOME/.docker/bin:$PATH"' >> ~/.zprofile
source ~/.zprofile
command -v docker

Не добавляйте путь через sudo и не исправляйте его в профиле другого пользователя. Ошибка, при которой Docker доступен интерактивно через VNC, но отсутствует по SSH, часто объясняется различием между zsh, bash, non-login shell и профилями пользователя.

<
ПроверкаНормальный результатЕсли проверка не пройдена
uname -mАрхитектура соответствует выбранному пакету и образамПроверить сборку Docker Desktop и параметры --platform
test -d /Applications/Docker.appКаталог приложения существуетПроверить неполную установку
command -v dockerПуть указывает на актуальный CLIИсправить PATH текущего пользователя
sw_versmacOS входит в поддерживаемый диапазонСверить выпуск с официальными требованиями

Второй этап: проверьте пользовательскую сессию

Может ли Docker Desktop запуститься без графического интерфейса?

Для удалённого Mac ответ зависит от состояния узла. Команда запуска из SSH может сработать, если приложение уже было инициализировано, пользовательские разрешения подтверждены, а среда не требует интерактивного действия. Но нельзя считать, что любой чистый или только что обновлённый узел гарантированно пройдёт первичную авторизацию без VNC.

Docker Desktop на Mac запускается от имени непривилегированного пользователя. При установке или изменении некоторых параметров могут потребоваться разрешения администратора, создание CLI-ссылок, настройка Socket или разрешение на привилегированные порты. Подробные ограничения описаны в документации Docker о правах Docker Desktop на Mac.

Практический порядок такой:

  1. Подключитесь к узлу по VNC под тем же пользователем, от имени которого будет работать Docker.
  2. Запустите /Applications/Docker.app.
  3. Завершите первоначальные окна, разрешения и миграцию настроек.
  4. Дождитесь состояния, при котором Dashboard показывает готовый Docker Engine.
  5. Вернитесь в SSH под тем же именем пользователя.
  6. Проверьте docker desktop status, затем docker info.
  7. Только после этого тестируйте перезапуск через CLI.
Проверить совпадение пользователей можно так:
whoami
id -u
echo "$HOME"
ps aux | grep -i '[D]ocker'

Если Docker Desktop запущен пользователем builder, а SSH-команды выполняются под admin, не переносите проблему в категорию «сломался Docker». У этих учётных записей будут разные $HOME, конфигурация Docker, Keychain и пользовательский Socket.

Apple разделяет Login Items, LaunchAgents и LaunchDaemons: пользовательские агенты работают в контексте вошедшего пользователя, а системные daemons могут запускаться до входа в систему. Это важная граница для оценки полностью безэкранного узла. Сравните фактическую конфигурацию с документацией Apple по Service Management.

Третий этап: восстановите правильный Context и Docker Socket

Одна из самых частых ошибок удалённой схемы — проверять только файл /var/run/docker.sock. В Docker Desktop актуальный CLI может использовать Context desktop-linux, а системная ссылка на /var/run/docker.sock может отсутствовать намеренно.

Выполните:

docker context ls
docker context show
docker context inspect desktop-linux
env | grep -E 'DOCKER_HOST|DOCKER_CONTEXT'
ls -la ~/.docker
ls -la ~/.docker/run

Если выбран другой Context, переключите его только после фиксации текущего состояния:

docker context show > /tmp/docker-context.before.txt
docker context use desktop-linux
docker info

Docker указывает, что CLI получает путь к Socket через текущий Context, а при запуске Docker Desktop Context обычно переключается на desktop-linux. В настройках также существует отдельная опция создания /var/run/docker.sock; это не то же самое, что пользовательский Socket внутри домашнего каталога.

Типичный пользовательский путь выглядит так:

$HOME/.docker/run/docker.sock

Проверяйте его существование и владельца:

stat -f '%N %Su:%Sg %Mp%Lp' "$HOME/.docker/run/docker.sock"

Если Socket отсутствует после перезагрузки, сначала выполните:

docker desktop status
docker desktop start
sleep 10
docker context show
docker info

Не создавайте пустой файл командой touch ~/.docker/run/docker.sock. Socket — это конечная точка работающего процесса, а не обычный маркер состояния. Ручное создание файла может скрыть настоящий сбой и привести к ошибкам вида «connection refused» или «file is not a socket».

<
ПроверкаЧто подтверждаетБезопасное действие
docker context showКакой endpoint использует CLIСохранить значение и выбрать ожидаемый Context
env \grep DOCKER_HOSTНе переопределён ли endpoint переменной средыВременно выполнить unset DOCKER_HOST и повторить тест
test -S ~/.docker/run/docker.sockФайл действительно является Unix SocketЗапустить Desktop, а не создавать файл вручную
docker infoCLI получил ответ от daemonПерейти к проверке контейнера и сети
Если вы намеренно используете системную ссылку, проверьте её отдельно:
ls -l /var/run/docker.sock
test -S /var/run/docker.sock && echo "Socket доступен"

Содержимое /var/run на macOS очищается при перезапуске. При включённой настройке Desktop может создавать ссылку через задачу launchd, но это зависит от конфигурации установки. Поэтому отсутствие ссылки после перезагрузки само по себе ещё не доказывает повреждение Docker Desktop.

Четвёртый этап: отделите права от ошибки приложения

Сообщение permission denied не всегда означает, что вам нужен root. В Docker Desktop контейнеры запускаются внутри управляемой Linux-виртуальной машины; права root внутри контейнера не дают автоматически права root на хостовой macOS.

Разделяйте минимум четыре случая.

CLI не находится

Проверьте:

echo "$PATH"
command -v docker
ls -l "$HOME/.docker/bin/docker"

Исправляйте профиль пользователя, а не запускайте все команды через sudo.

Нужен привилегированный порт

Порты ниже 1 024 могут требовать отдельной настройки привилегированного помощника. Для первичной проверки используйте порт выше 1 024:

docker run --rm -p 18080:80 nginx

Если тест на 18080 работает, а публикация на 80 нет, проблема, вероятно, относится к privileged port mapping, а не к запуску Docker Engine.

Не работает приватный реестр

Проверьте, что удалённый пользователь видит собственное хранилище учётных данных:

echo "$HOME"
cat "$HOME/.docker/config.json"
docker login registry.example.invalid

В примере используется фиктивный адрес. Не передавайте токены в командной строке, shell history, CI-логах или открытых переменных. Для автоматизации применяйте секрет-хранилище CI и временные учётные данные, если это поддерживает ваш реестр.

Не работает прокси

Сначала проверьте минимальный публичный образ, затем приватный:

docker pull hello-world
docker pull registry.example.invalid/team/test-image:tag

Если первый образ скачивается, а второй нет, не меняйте Socket и не переустанавливайте Desktop: ищите проблему в DNS, прокси, сертификате или аутентификации реестра.

Пятый этап: снимите логи до перезапуска

Перезапуск может удалить полезную последовательность событий из текущего терминала, поэтому сначала сохраните состояние:

docker desktop status > /tmp/docker-desktop.status.txt 2>&1
docker context ls > /tmp/docker-context.txt
docker info > /tmp/docker-info.txt 2>&1
docker desktop logs > /tmp/docker-desktop.logs.txt 2>&1

Если CLI не поддерживает docker desktop logs, используйте системные журналы и файл backend:

log show --style syslog --last 30m \
  --predicate 'process contains[c] "docker" OR eventMessage contains[c] "docker"' \
  > /tmp/docker-macos.log

tail -n 100 \
  "$HOME/Library/Containers/com.docker.docker/Data/log/vm/init.log"

Ищите не отдельную строку error, а связку событий:

  • backend не запустился;
  • не создан внутренний Socket;
  • не переключился Context;
  • не прошла авторизация помощника;
  • не поднялась виртуальная машина;
  • контейнерный daemon готов, но приложение внутри контейнера завершилось.
Команда диагностики может занять несколько минут, поэтому не закрывайте терминал сразу после запуска:
docker desktop diagnose

Если версия CLI старее и этой команды нет, используйте официальный диагностический инструмент или журналы Console. Не отправляйте диагностический архив третьим лицам без проверки на секреты, имена проектов и внутренние адреса.

Как безопасно выполнить перезапуск

После сохранения состояния используйте штатную команду:

docker desktop restart
sleep 10
docker desktop status
docker context show
docker info

Затем запустите тестовый контейнер:

docker run --rm hello-world

Для сетевой проверки:

docker run -d --name docker-check -p 18080:80 nginx
curl -I http://127.0.0.1:18080
docker rm -f docker-check

Если приложение не отвечает, попробуйте запуск, но не переходите к удалению данных:

docker desktop start
sleep 10
docker info

Операции «Clean / Purge data» и «Reset to factory defaults» имеют разрушительный эффект для настроек и данных. Их нельзя применять как универсальный вариант исправления SSH-сбоя. Сначала сохраните docker context, config.json, compose-файлы, список образов и сведения о томах.

Проверьте узел после перезагрузки

Чтобы понять, пригоден ли удалённый Mac для постоянной работы, одной успешной команды docker run недостаточно. Проведите отдельную приёмку после перезагрузки.

  • [ ] Записан точный macOS-пользователь, под которым должен запускаться Docker Desktop.
  • [ ] Проверено, что SSH возвращается после перезагрузки.
  • [ ] Зафиксирован путь к CLI и значение PATH в неинтерактивной SSH-сессии.
  • [ ] Проверено наличие ожидаемого Docker Context.
  • [ ] Проверено, что пользовательский Socket является настоящим Unix Socket.
  • [ ] Проверено состояние командой docker desktop status.
  • [ ] Проверен ответ docker info.
  • [ ] Запущен минимальный тестовый контейнер.
  • [ ] Проверена публикация порта выше 1 024.
  • [ ] Проверена загрузка тестового образа из нужного реестра.
  • [ ] Проверено восстановление бизнес-контейнеров согласно вашей политике restart.
  • [ ] Зафиксировано, требовался ли вход через VNC или ручное подтверждение.
  • [ ] Повторена проверка после полного выхода пользователя из графической сессии, если узел должен работать без неё.
Последний пункт особенно важен. Пользовательские LaunchAgents работают от имени вошедшего пользователя, тогда как LaunchDaemons могут существовать независимо от графического входа. Поэтому успешное восстановление после перезагрузки с ручным входом через VNC ещё не равно полностью безоперационному запуску. <
Результат приёмкиОценка узлаСледующее решение
SSH, Desktop, Context, Socket и контейнер работают без VNCПодходит для автоматизированных задачДобавить мониторинг и повторную проверку после обновлений
Нужен VNC только после первого запуска или обновленияПодходит с операционной процедуройЗафиксировать ручной шаг и владельца дежурства
После каждой перезагрузки требуется авторизацияОграниченно пригоденНе использовать для полностью автономного CI без доработки
Socket появляется только после ручного создания файлаНепригодно в текущем видеИсправить конфигурацию Desktop или заменить узел
Docker работает, но приватный реестр или сеть нестабильныDesktop исправен, задача не готоваОтдельно исправить credentials, proxy или DNS

Когда удалённый Mac лучше заменить

Если проблема вызвана один раз сбившимся Context, пустым PATH или неподтверждённой настройкой Socket, ремонт обычно оправдан. Если же после каждого обновления или перезапуска требуется ручной вход, а контейнеры должны восстанавливаться ночью без доступа к VNC, это уже не единичный сбой, а несоответствие эксплуатационной модели.

Сравнивайте не только наличие Docker, но и весь путь восстановления:

  • кто выполняет вход после перезагрузки;
  • где хранятся credentials;
  • как создаётся Socket;
  • как контролируется версия macOS и Docker Desktop;
  • что произойдёт при зависании backend;
  • можно ли получить VNC, SSH и консольный доступ одновременно.
Если текущий Mac находится у вас дома, добавляются нестабильный upload, проброс портов, энергосбережение, ручное восстановление после отключения электричества и риск того, что рабочая станция занята другим пользователем. Linux-сервер не решает проблему macOS-инструментов и Apple Silicon-совместимости, а виртуальная macOS-среда может отличаться от реального удалённого Mac по разрешениям, графической сессии и поведению Docker Desktop.

Когда нужен временный контейнерный узел для сборки или теста, аренда реального Mac у MACGPU может быть практичнее покупки отдельного компьютера: вы получаете VNC и SSH-доступ, можете провести первичную настройку через графическую сессию, а затем проверить Docker по этому runbook. Перед выбором сравните условия на странице руководства по Mac M4 и актуальные цены аренды Mac M4.

Для постоянной тяжёлой нагрузки, физического USB-доступа, локальной периферии или полностью контролируемой инфраструктуры собственный Mac всё ещё может быть рациональнее. Но если ваша задача — временный CI-узел, удалённая сборка или воспроизводимая проверка контейнеров, выбирайте не просто «Mac с Docker», а узел, который проходит SSH-подключение, VNC-авторизацию, восстановление Context и Socket, тест контейнера и перезагрузочную приёмку. С вариантами удалённого доступа можно ознакомиться на странице MACGPU для разработчиков.