无法连接到 Mac OS X 上的 Docker 守护程序

Posted

技术标签:

【中文标题】无法连接到 Mac OS X 上的 Docker 守护程序【英文标题】:Couldn't connect to Docker daemon on Mac OS X 【发布时间】:2016-06-28 10:06:59 【问题描述】:

我想在 Mac OS X El Capitan (v10.11.2) 上使用 docker-compose 运行多容器应用程序。

但是,$ docker-compose up 命令抱怨它无法连接到 Docker 守护进程。

错误:无法连接到 Docker 守护程序 - 您可能需要运行 docker-machine start default

只有在执行$ eval "$(docker-machine env default)" 之后,我才能访问docker-compose 命令。

为什么会这样,我该如何克服这个额外的步骤?

【问题讨论】:

您是否从 Docker 快速入门终端运行 docker-compose(假设您使用的是 Docker 工具箱)?还是来自普通终端?只有在第二种情况下才需要额外的步骤。 我从普通终端运行它 Docker 需要设置一些环境变量才能正常使用,这就是为什么每次重启 docker-machine 时总是需要eval 命令。 【参考方案1】:

Docker.app 附带的 Docker 版本更新

自发布此答案以来,macOS 上的 Docker 体验得到了改善:

现在唯一的先决条件是 Docker.app 正在运行。请注意,按需启动它需要一段时间,因为必须启动底层 Linux VM。

然后任何 shell 都可以访问 Docker 功能。

默认情况下,Docker.app 在登录时启动(您可以通过其首选项进行更改)。 如果您更喜欢从命令行按需启动和停止 Docker,这里有 bash 脚本这样做,docker-startdocker-stop;将它们放在您的$PATH 中的任何位置。

docker-start 启动Docker.app 时,它会等待Docker 完成启动并准备就绪。


docker-start

#!/usr/bin/env bash

case $1 in
  -h|--help)
    echo $'usage: docker-start\n\nStarts Docker (Docker.app) on macOS and waits until the Docker environment is initialized.'
    exit 0
    ;;
esac
(( $# )) &&  echo "ARGUMENT ERROR: Unexpected argument(s) specified. Use -h for help." >&2; exit 2; 

[[ $(uname) == 'Darwin' ]] ||  echo "This function only runs on macOS." >&2; exit 2; 

echo "-- Starting Docker.app, if necessary..."

open -g -a Docker.app || exit

# Wait for the server to start up, if applicable.  
i=0
while ! docker system info &>/dev/null; do
  (( i++ == 0 )) && printf %s '-- Waiting for Docker to finish starting up...' || printf '.'
  sleep 1
done
(( i )) && printf '\n'

echo "-- Docker is ready."

docker-stop

#!/usr/bin/env bash

case $1 in
  -h|--help)
    echo $'usage: docker-stop\n\nStops Docker (Docker.app) on macOS.'    
    exit 0
    ;;
esac
(( $# )) &&  echo "ARGUMENT ERROR: Unexpected argument(s) specified. Use -h for help." >&2; exit 2; 

[[ $(uname) == 'Darwin' ]] ||  echo "This function only runs on macOS." >&2; exit 2; 

echo "-- Quitting Docker.app, if running..."

osascript - <<'EOF' || exit
tell application "Docker"
  if it is running then quit it
end tell
EOF

echo "-- Docker is stopped."
echo "Caveat: Restarting it too quickly can cause errors."

原始的、过时的答案:

Kevan Ahlquist's helpful answer 显示了要添加到您的 Bash 配置文件 (~/.bash_profile) 以在打开交互式 shell 时自动初始化 Docker 的命令。

请注意,您始终可以通过打开应用程序 /Applications/Docker/Docker Quickstart Terminal.app(例如,通过 Spotlight)在 new shell 选项卡/窗口中初始化 Docker。 在现有的 shell 中,您可以以 open -a 'Docker Quickstart Terminal.app' 的形式调用它(这也会打开 new shell 选项卡)。 这个答案提供了一种在 current shell 中启动 Docker 的便捷方式。

在下面添加 Bash shell 函数 - docker-startdocker-stop - 在以下方面改进了 Kevan 的方法:

您可以运行docker-start on demand,而无需在 打开 shell 时启动 VM 的开销(一旦 Docker VM 运行,初始化是快得多,但仍然需要相当长的时间)。 (当然,您仍然可以选择直接从您的个人资料中调用docker-start。)

docker-stop 允许停止 Docker 并按需清理环境变量。

这些函数确保 Docker 的错误消息不被抑制,并且它们通过 Docker 错误退出代码。

提供了额外的状态信息。

您可以将 VM 名称作为参数传递;默认为default

例子:

$ docker-start
-- Starting Docker VM 'default' (`docker-machine start default`; this will take a while)...
Starting "default"...
(default) Check network to re-create if needed...
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
-- Setting DOCKER_* environment variables (`eval "$(docker-machine env default)"`)...
DOCKER_CERT_PATH="/Users/jdoe/.docker/machine/machines/default"
DOCKER_HOST="tcp://192.168.99.100:2376"
DOCKER_MACHINE_NAME="default"
DOCKER_TLS_VERIFY="1"
-- Docker VM 'default' is running.


$ docker-stop
-- Stopping Docker VM 'default' (`docker-machine stop default`)...
Stopping "default"...
Machine "default" was stopped.
-- Unsetting DOCKER_* environment variables (DOCKER_CERT_PATH, DOCKER_HOST, DOCKER_MACHINE_NAME, DOCKER_TLS_VERIFY)...
-- Docker VM 'default' is stopped.

用于按需启动和停止 Docker 的 Shell 函数(将它们放入,例如,~/.bash_profile 以在您的交互式 Shell 中实现全局可用性)。

注意:函数在 bashkshzsh 中有效,但在 ksh 中,您必须重命名它们,以免在函数名。

function docker-start 
  typeset vm=$1:-default sts
  case $vm in
    -h|--help)
      echo $'usage: docker-start [<vm>]\n\nEnsures that the specified/default Docker VM is started\nand the environment is initialized.'
      return 0
      ;;
  esac
  sts=$(docker-machine status "$vm") || return
  [[ $sts == 'Running' ]] && echo "(Docker VM '$vm' is already running.)" ||  
    echo "-- Starting Docker VM '$vm' (\`docker-machine start "$vm"\`; this will take a while)..."; 
    docker-machine start "$vm" || return
  
  echo "-- Setting DOCKER_* environment variables (\`eval \"\$(docker-machine env "$vm")\"\`)..."
  # Note: If the machine hasn't fully finished starting up yet from a
  #       previously launched-but-not-waited-for-completion `docker-machine status`,
  #       the following may output error messages; alas, without signaling failure
  #       via the exit code. Simply rerun this function to retry.
  eval "$(docker-machine env "$vm")" || return
  export | grep -o 'DOCKER_.*'
  echo "-- Docker VM '$vm' is running."


function docker-stop 
  typeset vm=$1:-default sts envVarNames fndx
  case $vm in
    -h|--help)
      echo $'usage: docker-stop [<vm>]\n\nEnsures that the specified/default Docker VM is stopped\nand the environment is cleaned up.'
      return 0
      ;;
  esac
  sts=$(docker-machine status "$vm") || return
  [[ $sts == 'Running' ]] &&  
    echo "-- Stopping Docker VM '$vm' (\`docker-machine stop "$vm"\`)...";
    docker-machine stop "$vm" || return
   || echo "(Docker VM '$vm' is not running.)"
  [[ -n $BASH_VERSION ]] && fndx=3 || fndx=1 # Bash prefixes defs. wit 'declare -x '
  envVarNames=( $(export | awk -v fndx="$fndx" '$fndx ~ /^DOCKER_/  sub(/=.*/,"", $fndx); print $fndx ') )
  if [[ -n $envVarNames ]]; then
    echo "-- Unsetting DOCKER_* environment variables ($(echo "$envVarNames[@]" | sed 's/ /, /g'))..."
    unset "$envVarNames[@]"
  else
    echo "(No DOCKER_* environment variables to unset.)"
  fi
  echo "-- Docker VM '$vm' is stopped."

【讨论】:

@BrianArmstrong:该功能确实随 Docker 提供,但作为单独的应用程序 /Applications/Docker/Docker Quickstart Terminal.app,它在 new 终端窗口中初始化 Docker。我认为这个单独的入口点的原因是在 OSX 上运行 Docker 需要启动一个基于 VirtualBox 的 Linux VM(除了设置环境变量)——这是你每次打开 shell 时不希望产生的开销。这个答案提供了一种从 现有 shell 启动 Docker on demand 的便捷方式。 @mklement0 太棒了!您是否将这些命令保存在某个存储库中? @ManeatingKoala:不,抱歉。这个答案是目前唯一的来源。 我通过ssh登录macbook pro,在命令行运行“open -g -a Docker.app”不起作用:LSOpenURLsWithRole() failed for the application /Applications/Docker.app with error -54.如果命令行必须在GUI环境下运行,那么命令行并没有太大帮助...... @zerox:您是说open -g -a Docker.app本地 运行时为您工作,但通过SSH 失败?通常,open -a 也可以通过 SSH 工作(但显然只能在目标机器上以可见的方式启动应用程序)。【参考方案2】:

我的~/.bash_profile 中有以下内容,因此我不必每次都运行 env 命令:

docker-machine start default 2>/dev/null # Hide output if machine is already running
eval `docker-machine env default`

【讨论】:

【参考方案3】:

在快速启动终端中,我重新启动“默认”机器解决了我的问题

docker-machine restart default
eval $(docker-machine env default)

然后我就可以开始用 docker-compose up -d --build 组合我的容器了

【讨论】:

【参考方案4】:

我的案例有帮助:停止 + 删除所有 docker 容器(Docker 版本 1.13.0-rc4)

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

在此“docker-compose up”运行后没有错误“错误:无法连接到 Docker 守护程序。您可能需要启动 Docker for Mac。”

也许在某些情况下,这个错误消息只是由另一个错误引起的,即内存空间问题。

【讨论】:

【参考方案5】:

我写了一个自制水龙头,在这里:https://github.com/nejckorasa/mac-docker-go

它包含一个启动/重启 Docker 守护进程的脚本。

Usage: dckr [options]

Options:
  -k  | --kill        Kill Docker daemon
  -s  | --start       Start Docker daemon
  -r  | --restart     Restart Docker daemon
  -ka | --killall     Kill all running Docker containers
  -h                  Display help

  Defaults to restart if no options are present

【讨论】:

以上是关于无法连接到 Mac OS X 上的 Docker 守护程序的主要内容,如果未能解决你的问题,请参考以下文章

通过蓝牙将 Android 应用程序连接到 Mac OS X 上的 Python 脚本

RazorSQL 和 sql 开发人员无法使用 docker 连接到 Mac 上的 oracle DB

在 mac os x 上安装 cloudera impala shell 并连接到 impala 集群

无法在 Mac OS X 上使用 C + libusb 声明 USB 接口

markdown Mac OS X上的Docker Machine

无法从本地主机连接到 Docker 中的 MySQL(Docker for Mac beta)