Mac OS X 下安装使用 Docker (2017年7月)
两年前的一篇 Mac OS X 下安装使用 Docker 安装时还是用的 boot2docker, 如今进化到了在 Mac OS X 下用 Docker Toolbox, 而且命令也由 boot2docker 换成了 docker-machine. 当然由于是非 Linux 系统, 所以Mac OS X 仍然需要借助于 VirtualBox 中的 linux 虚拟机作为桥梁, Docker Toolbox 创建的虚拟机名是 default (boot2docker 创建的虚拟机名是 boot2docker-vm) 就是这一桥梁, 我们称之为 DOCKER_HOST. 文中的 default 虚拟机指的就是这个 DOCKER_HOST.
现在来看下安装步骤及体验, 因为我系统中已安装好了 VirtualBox, 所以这一步骤等会就省略了.
一. 安装 docker 和 docker-machine
官方的指南是通过下载 DockerToolbox 来安装 docker, docker-machine 和其他辅助工具. 但如果你偏于极客, 并不习惯于图形界面来安装的话, 那么安装 docker 和 docker-machine 就只要下面两个指令
1
2
brewinstalldocker
breainstalldocker-machine
如果你已选择了使用上面的两条命令来安装 docker, docker-machine 的话, 那么请跳到下一步.
如果你热爱图形界面来安装应用的话, 可以到页面 https://www.docker.com/products/docker-toolbox 中下载 Mac 的版本的 DockerToolbox-1.10.3.pkg, 当前版本是 1.10.3
可以看到 Docker Toolbox 包含了以下五个组件
. Docker Client docker binary —- docker 命令
. Docker Machine docker-machine binary —- docker-machine 命令
. Docker Compose docker-compose binary
. Kitematic – Desktop GUI for Docker
. Docker Quickstart Terminal app
然后就 Continue, 选择安装路径, 按提示输入 sudo 密码, 由于 Docker Toolbox 检测到我已安装了 Virtual Box, 所以不曾提示我去下载安装 Virtual Box.
将要完成之际你要选择使用 Docker Quickstart Terminal 还是 Kitematic (Beta) 来开始使用 Docker. 这两个东西都可以在第一次启动的时候自动创建 Virtual Box 的 default 虚拟机.
二. 初始化 Virtual Box 的 default 虚拟机
如果你是使用的 brew install 来安装的 docker 和 docker-machine 的话, 可以用命令
1
docker-machine
create --driver virtualbox default
来手动创建 default 虚拟机. 创建过程与下面使用 Docker quickstart Terminal 是一样的.
如果安装的是 Docker Toolbox 的话, 可以执行 Docker Quickstart Terminal 来创建 default 虚拟机. 我在 Launchpad 中点击 Docker Quickstart Terminal 后没什么效果, 所以是直接执行相应的命令文件
/Applications/Docker/Docker\ Quickstart\ Terminal.app/Contents/Resources/Scripts/start.sh
或者打开 Docker Toolbox 中的 Kitematic 工具, 创建 default 虚拟机也是自动完成的. Kitematic 还有更为丰富的功能, 省去了记忆那些 docker-machine 和 docker 命令, 不过极客们可不这么想.
虽然我们新的虚拟机名称变成了 default, 但安装的镜像依旧是 boot2docker.iso. 由于我以前安装过 boo2docker, 所以上面直接从缓存的 boot2docker.iso 创建了 default 虚拟机. 再看看在 Virtual Box 中的样子
三. 初始化环境变量
docker-machine env default 显示宿主机需要为 default 虚拟机设置的环境变量的指令
eval (docker-machine env default) 将在宿主机中设置相应的环境变量 — 我的机器的 shell 是 fish, 如果 bash 将是 eval $(docker-machine env default)
env 显示宿主机的环境变量
不设置好环境变量将无法使用 docker 命令, 比如执行 docker images 时会看到 Cannot connect to the Docker daemon. Is the docker daemon running on this host? 错误, 因为 docker 无法与 default 虚拟机连接起来. 为了每次都有效还必须把 eval (docker-machine env default) 加到 ~/.config/fish/config.fish 文件中. 使用 bash 则加一行 eval $(docker-machine env default) 到 ~/.bash_profile 中.
四. 最简单的使用 Docker
[I]
➜ ~ docker
images
REPOSITORY
TAG IMAGE ID CREATED SIZE
[I]
➜ ~ docker
run -it busybox /bin/sh
Unable
to findimage
'busybox:latest'locally
latest:
Pulling from library/busybox
385e281300cc:
Pull complete
a3ed95caeb02:
Pull complete
Digest:
sha256:4a887a2326ec9e0fa90cce7b4764b0e627b5d6afcb81a3f73c85dc29cea00048
Status:
Downloaded newer image forbusybox:latest
/#
uname -a
Linux
5427a4ee9eaa 4.1.19-boot2docker #1
SMP Mon Mar 7 17:44:33 UTC 2016 x86_64 GNU/Linux
/#
exit
[I]
➜ ~ docker images
REPOSITORY
TAG IMAGE ID CREATED SIZE
busybox
latest 47bcc53f74dc 9 days ago 1.113 MB
[I]
➜ ~ dockerps-a
CONTAINER
ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5427a4ee9eaa
busybox "/bin/sh" 20
seconds ago Exited (0) 8 seconds ago grave_kowalevski
第一个 docker images 时是没有一个镜像的, 用 docker run -it busybox /bin/sh 安装并启动一个交互时的 busybox 容器, 退出后 docker images 列出我们安装了一个 busybox 镜像.
五. 基于 Dockerfile 构建
当然目录下创建 Dockerfile 文件, 内容如下:
FROM
ubuntu:14.04
USER
root
RUN
apt-get install-y
apache2
EXPOSE
80
由 Dockerfile 构建镜像
$ docker builder -t ubuntu:apache2 ./
……
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu apache2 511aaac08bc1 2 minutes ago 224 MB
ubuntu 14.04 97434d46f197 9 days ago 188 MB
加载镜像, 启动容器
docker run -P -d ubuntu:apache2 apachectl -D FOREGROUND
那么 Docker 会在 default 虚拟机上开启一个随机的端口与容器的 80 端口进行映射, 像 docker ps 可以看到
$ docker ps
Container ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91fd870d5e18 ubuntu:apache2 “apachectl -D FOREGRO” 7 seconds ago Up 7 seconds 0.0.0.0:32768->80/tcp furious_borg
容器的 80 映射到了 default 虚拟机的 32768 端口. 查看到 default 虚拟机的 ip
docker-machine
ip default
192.168.99.106
这时可以在 Mac 本机访问容器中的 Apache2 服务
curl
-I http://192.168.99.106:32769
HTTP/1.1
200 OK
Date:
Mon, 28 Mar 2016 00:49:08 GMT
Server:
Apache/2.4.7
(Ubuntu)
Last-Modified:
Sun, 27 Mar 2016 22:38:30 GMT
ETag:"2cf6-52f0f748d8580"
Accept-Ranges:
bytes
Content-Length:
11510
Vary:
Accept-Encoding
Content-Type:
text/html
如果希望非本机也能访问容器中的 Apache2 服务, 则需要把 Mac 的端口映射到 default 虚拟机上去, 比如 Mac 下可以用 pf 实现, 也可以设置在 default 虚拟机上
$ VBoxManage controlvm default natpf1 “tcp-port_80,tcp,,20080,,10080”
上面的命令配置了 Mac OS X 的 20080 映射到 default 虚拟机的 10080 端口. Mac:20080 -> default:10080
然后在启动容器时用 -p 参数指定 default 虚拟机到容器的端口映射. default:10080 -> 容器:80
docker run -p 10080:80 -d ubuntu:apache2 apachectl -D FOREGROUND
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
200f14210914 ubuntu:apache2 “apachectl -D FOREGRO” About a minute ago Up About a minute 0.0.0.0:10080->80/tcp pensive_bohr
现在可以用 Mac 的 20080 端口访问到容器的 80 端口
curl
-I http://localhost:20080
HTTP/1.1
200 OK
Date:
Mon, 28 Mar 2016 00:49:08 GMT
Server:
Apache/2.4.7
(Ubuntu)
Last-Modified:
Sun, 27 Mar 2016 22:38:30 GMT
ETag:"2cf6-52f0f748d8580"
Accept-Ranges:
bytes
Content-Length:
11510
Vary:
Accept-Encoding
Content-Type:
text/html
当然其他机器在没有防火墙的限制下也可以通过 Mac 的 IP 地址访问容器的 Apache2 服务了.
关于端口映射的配置
前面是用 VBoxMange controlvm 添加端口映射时不需要用 docker-machine stop 停止 default 虚拟机
VBoxManage modifyvm default –natpf1 “tcp-port_80,tcp,,20080,,10080” 命令不能对运行中的虚拟机操作.
VBoxManage controlvm default natpf1 delete tcp-port_80 可以删除运行中的 default 虚拟机的端口映射规则.
VBoxManage showvminfo default --machinereadable | grep Forwarding 显示 default 虚拟机的所有端口映射规则
上面的命令必须逐个的把在 Mac OS X 与 default 虚拟机之间进行端口映射, 也有人想一了百了, 用下面那样的脚本
1
2
3
4
fori
in{10000..10999};
do
VBoxManage
modifyvm "boot2docker-vm"--natpf1
"tcp-port$i,tcp,,$i,,$i";
VBoxManage
modifyvm "boot2docker-vm"--natpf1
"udp-port$i,udp,,$i,,$i";
done
这样做完全是在 Mac OS X 上无畏的启动大量监听的端口, 并与 default 虚拟机进行映射, 不仅浪费了大量的资源, 而且 EXPOSE 80 选的随机端口不一定落在 10000 — 10999 这个区间上, 比如前面的 32768 端口.
和 boot2docker 类似, 如果你不想用 VBoxMange 命令来操作虚拟机设置的话, 也可以用 docker-machine ssh 来设置隧道转发, 如
1
2
3
4
docker-machinesshdefault
-L 20080:localhost:10080
或者无需进入到
default 虚拟机的话
docker-machinesshdefault
-f -N -L 20080:localhost:10080
尚不知如何停止掉 docker-machine 对某个端口转发.