共计 10327 个字符,预计需要花费 26 分钟才能阅读完成。
我有机会建立一个以 Docker 为基础的微服务架构在我现在的工作中,很多人都会分享他们使用 Docker 的心得,我想我也不会例外。因此我总结了一些,可能你会在日常使用 Docker 的时候会用到。
1. 一台主机部署多个 Docker 实例
如果你想运行多个 Docker 容器在一台主机上,如果要设置不同的 TLS 设置,网络设置,日志设置和存储驱动程序特定的容器,这是特别有用的。例如,我们目前正在运行一个标准设立两个 Docker 守护进程。一运行 consul 提供 DNS 解析,并作为群集存储为其他 Docker 容器。
For example:
# start a docker daemon and bind to a specific port
docker daemon -H tcp://$IP:5000 --storage-opt dm.fs=xfs \
-p "/var/run/docker1.pid" \
-g "/var/lib/docker1" \
--exec-root="/var/run/docker1
# and start another daemon
docker daemon -H tcp://$IP:5001 --storage-opt dm.fs=xfs \
-s devicemapper \
--storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool \
-p "/var/run/docker2.pid" \
-g "/var/lib/docker2" --exec-root="/var/run/docker2"
--cluster-store=consul://$IP:8500 \
--cluster-advertise=$IP:2376
# start a docker daemon and bind to a specific port
dockerdaemon -H tcp://$IP:5000 --storage-opt dm.fs=xfs \
-p "/var/run/docker1.pid" \
-g "/var/lib/docker1" \
--exec-root="/var/run/docker1
# and start another daemon
docker daemon -H tcp://$IP:5001 --storage-opt dm.fs=xfs \
-s devicemapper \
--storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool \
-p "/var/run/docker2.pid" \
-g "/var/lib/docker2" --exec-root="/var/run/docker2"
--cluster-store=consul://$IP:8500 \
--cluster-advertise=$IP:2376
2. Docker Exec 的使用
Docker Exec 是一个很重要很多人都会用到的工具,也许你使用 Docker 不只是为你的升级,生产和测试环境,同时也对本地机器上运行的数据库,服务器密钥库等,这是能够直接运行的容器的上下文中运行的命令,非常方便。
我们做了大量的 Cassandra,并检查表是否包含正确的数据。如果你只是想执行一个快速 CQL 查询,Docker exec 就很赞:
$ docker ps --format "table {{.ID}}\t {{.Names}}\t {{.Status}}"
CONTAINER ID NAMES STATUS
682f47f97fce cassandra Up 2 minutes
4c45aea49180 consul Up 2 minutes
$ docker exec -ti 682f47f97fce cqlsh --color
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh>
$ dockerps --format "table {{.ID}}\t {{.Names}}\t {{.Status}}"
CONTAINERID NAMES STATUS
682f47f97fce cassandra Up 2 minutes
4c45aea49180 consul Up 2 minutes
$ dockerexec -ti 682f47f97fce cqlsh --color
Connectedto TestClusterat 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQLspec 3.3.1 | Native protocolv4]
Use HELPfor help.
cqlsh>
或者只是访问 nodetool 或镜像中可用的任何其他工具:
$ docker exec -ti 682f47f97fce nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 192.168.99.100 443.34 KB 256 ? 8f9f4a9c-5c4d-4453-b64b-7e01676361ff rack1
Note: Non-system keyspaces don't have the same replication settings, effective ownership information
$ dockerexec -ti 682f47f97fce nodetoolstatus
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns HostID Rack
UN 192.168.99.100 443.34 KB 256 ? 8f9f4a9c-5c4d-4453-b64b-7e01676361ff rack1
Note: Non-systemkeyspacesdon't havethesamereplicationsettings, effectiveownershipinformation
这当然可以被应用到任何(Client)的工具捆绑在一起的镜像中。我个人觉得这样会比所有客户端和本地更新更简单。
3. Docker 的检查 和 JQ
与其说这是一个 Docker 技巧,不如说是一个 JQ 技巧。如果你没有听过 JQ,它是一个在命令行解析 JSON 的伟大工具。因为我们可以不需要使用 format specifier 而能够查看容器里面发生的一切。
# Get network information:
$ docker inspect 4c45aea49180 | jq '.[].NetworkSettings.Networks'
{
"bridge": {
"EndpointID": "ba1b6efba16de99f260e0fa8892fd4685dbe2f79cba37ac0114195e9fad66075",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "","GlobalIPv6Address":"",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
# Get the arguments with which the container was started
$ docker inspect 4c45aea49180 | jq '.[].Args'
[
"-server",
"-advertise",
"192.168.99.100",
"-bootstrap-expect",
"1"
]
# Get all the mounted volumes
11:22 $ docker inspect 4c45aea49180 | jq '.[].Mounts'
[
{
"Name": "a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f",
"Source": "/mnt/sda1/var/lib/docker/volumes/a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "","RW": true
}
]
# Get network information:
$ dockerinspect 4c45aea49180 | jq '.[].NetworkSettings.Networks'
{
"bridge": {
"EndpointID": "ba1b6efba16de99f260e0fa8892fd4685dbe2f79cba37ac0114195e9fad66075",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "","GlobalIPv6Address":"",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
# Get the arguments with which the container was started
$ dockerinspect 4c45aea49180 | jq '.[].Args'
[
"-server",
"-advertise",
"192.168.99.100",
"-bootstrap-expect",
"1"
]
# Get all the mounted volumes
11:22 $ dockerinspect 4c45aea49180 | jq '.[].Mounts'
[
{
"Name": "a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f",
"Source": "/mnt/sda1/var/lib/docker/volumes/a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "","RW": true
}
]
当然,它也能很好的完成查询其他类型的(Docker-esque) API 生成的 JSON(e.g Marathon, Mesos, Consul etc.)JQ 提供了一个非常广泛的 API,用于访问和处理 JSON. 更多信息可以在这里找到: https://stedolan.github.io/jq/
4. 扩展现有容器和在本地注册
在 Docker hub 中有大量可以使用的的不同使用场景的镜像。我们注意到,虽然有很多可用的镜像,但是很多时候我们不得对他们做一些修改。比如更好的健康检查 consul,通过系统变量或命令行参数的其他配置,为更好地设置或增加我们的集群,这是不容易做到的。如果我们碰到这个是刚刚创建自己的 Docker 的镜像和把它推到我们的本地注册表。我们通常是这么做的。
比如,我们希望有 JQ 可在我们的 consul 镜像中这样我们就可以很方便的检查我们的服务是否正常。
FROM progrium/consul
USER root
ADD bin/jq /bin/jq
ADD scripts/health-check.sh /bin/health-check.sh
FROMprogrium/consul
USERroot
ADDbin/jq /bin/jq
ADDscripts/health-check.sh /bin/health-check.sh
我们有了 health check scripts and JQ 我们就可以从我们自己的 consul image 做 health check 了。我们也有一个本地注册表运行镜像在创建后,我们只是标记生成的镜像,并将其推到我们的本地注册表
$ docker build .
...
$ docker tag a3157e9edc18 <local-registry>/consul-local:some-tag
$ docker push <local-registry>/consul-local:some-tag
$ dockerbuild .
...
$ dockertaga3157e9edc18 <local-registry>/consul-local:some-tag
$ dockerpush <local-registry>/consul-local:some-tag
现在,它可以提供给我们的开发者了。并且也可在我们的不同的测试环境中使用。
5. 访问远程主机的 Docker
Docker 的 CLI 是一个非常酷的工具,其中一个很大的特点是,你可以用它来轻松地访问多 Docker 守护进程,即使它们在不同的主机。你需要做的就是设置 DOCKER_HOST 环境变量指向 Docker daemon 的监听地址。如果该端口是可以的访问,你可以直接在远程主机上的 Docker,这和你运行一个 Docker daemon,并设置为通过 docker-machine 几乎相同的原理。
$ docker-machine env demo
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/jos/.docker/machine/machines/demo"
export DOCKER_MACHINE_NAME="demo"
$ docker-machineenvdemo
exportDOCKER_TLS_VERIFY="1"
exportDOCKER_HOST="tcp://192.168.99.100:2376"
exportDOCKER_CERT_PATH="/Users/jos/.docker/machine/machines/demo"
exportDOCKER_MACHINE_NAME="demo"
但你不必限制自己 Docker daemons 程通过 docker-machine 启动。如果你有你的后台程序运行的控制,以及安全的网络,你可以很容易地从一台机器控制所有的。
6. 简单的主机目录挂载
当你正在使用你的容器,你有时需要得到容器里面的一些数据。您可以复制它,或者通过使用 ssh 命令。但多数情况下是最容易的是将一个主机目录添加容器中。可以很容易地通过执行下面的命令完成操作:
$ mkdir /Users/jos/temp/samplevolume/
$ ls /Users/jos/temp/samplevolume/
$ docker run -v /Users/jos/temp/samplevolume/:/samplevolume -it --rm busybox
$ docker run -v /Users/jos/temp/samplevolume/:/samplevolume -it --rm busybox
/ # ls samplevolume/
/ # touch samplevolume/hello
/ # ls samplevolume/
hello
/ # exit
$ ls /Users/jos/temp/samplevolume/
hello
$ mkdir /Users/jos/temp/samplevolume/
$ ls /Users/jos/temp/samplevolume/
$ dockerrun -v /Users/jos/temp/samplevolume/:/samplevolume -it --rmbusybox
$ dockerrun -v /Users/jos/temp/samplevolume/:/samplevolume -it --rmbusybox
/ # ls samplevolume/
/ # touch samplevolume/hello
/ # ls samplevolume/
hello
/ # exit
$ ls /Users/jos/temp/samplevolume/
hello
你可以看到我们指定的目录安装在容器内,而且我们把所有的文件都在主机上,并在容器内可见。我们也可以使用 inspect 查看,看看有什么安装在哪里。
$ docker inspect 76465cee5d49 | jq '.[].Mounts'
[
{
"Source": "/Users/jos/temp/samplevolume",
"Destination": "/samplevolume",
"Mode": "","RW": true
}
]
$ dockerinspect 76465cee5d49 | jq '.[].Mounts'
[
{
"Source": "/Users/jos/temp/samplevolume",
"Destination": "/samplevolume",
"Mode": "","RW": true
}
]
我们可以在 Docker 官网看到更多的特性和使用方 法:https://docs.docker.com/engine/userguide/dockervolumes/
7. 添加 DNS 解析到你的容器
我之前提到过,我们可以通过 consul 来管理容器。Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,可以为容器提供服务发现和健康检查。对于服务发现 Consul 提供无论是 REST API 或传统 DNS,他的伟大的之处是,当你运行一个具体的镜像,你可以指定你的容器 DNS 服务器。
当你有 Consul 运行 (或者其它 DNS server) 你可以把它添加到您的 Docker daemon 就像这样:
docker run -d --dns $IP_CONSUL --dns-search service.consul <rest of confguration>
dockerrun -d --dns $IP_CONSUL --dns-searchservice.consul <restofconfguration>
现在,我们可以解决与 Consul 的名字注册的所有容器的 IP 地址,比如在我们的环境我们有了一个 cassandra 集群。每个 cassandra 将自己注册名称为“cassandra”我们的 Consul 集群。最酷的是,我们现在只是解决卡 cassandra 的地址基于主机名(而不必使用 Docker 链接)
$ docker exec -ti 00c22e9e7c4e bash
daemon@00c22e9e7c4e:/opt/docker$ ping cassandra
PING cassandra.service.consul (192.168.99.100): 56 data bytes
64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=0.053 ms
64 bytes from 192.168.99.100: icmp_seq=1 ttl=64 time=0.077 ms
^C--- cassandra.service.consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.053/0.065/0.077/0.000 ms
daemon@00c22e9e7c4e:/opt/docker$
$ dockerexec -ti 00c22e9e7c4e bash
daemon@00c22e9e7c4e:/opt/docker$ pingcassandra
PINGcassandra.service.consul (192.168.99.100): 56 databytes
64 bytesfrom 192.168.99.100: icmp_seq=0 ttl=64 time=0.053 ms
64 bytesfrom 192.168.99.100: icmp_seq=1 ttl=64 time=0.077 ms
^C--- cassandra.service.consulpingstatistics ---
2 packetstransmitted, 2 packetsreceived, 0% packetloss
round-tripmin/avg/max/stddev = 0.053/0.065/0.077/0.000 ms
daemon@00c22e9e7c4e:/opt/docker$
8. Docker-UI 是一个很棒来查看和获取洞察你容器的方式
使用 Docker CLI 来查看 Docker 容器所发生的一切并不难。很多时候,虽然你并不需要的 Docker CLI 的全部功能,但只是想快速浏览其中的容器运行,看看发生了什么。Docker UI (https://github.com/crosbymichael/dockerui)就是一个这样伟大的项目,并且他是开源的。
有了这个工具,你可以看到一个特定的 Docker deamon 的容器和镜像的最重要的东西。
9. Container 不能启动? Overwrite the Entry Point 你只需要从 bash 启动。
有时候一个容器只是没有做你想要它做的事情,你已经重新创建了 Docker 镜像,你在启动时运行了几次,但不知何故,该应用程序没有反应,然后日志显示也没什么有用的信息。最简单的调试方法是 overwrite the entry point,看看在容器内部发生的一切,查看文件权限是否正确。拷贝进入镜像的文件是否正确,或者任何其它可能出现的错误。幸运的是,Docker 有这样做的一个简单的解决方案。你可以从一个选择的入口点启动你的容器:
$ docker run -ti --entrypoint=bash cassandra
root@896757f0bfd4:/# ls
bin dev etc lib mediaopt root sbin sys usr
boot docker-entrypoint.sh home lib64 mntproc run srv tmp var
root@896757f0bfd4:/#
$ dockerrun -ti --entrypoint=bashcassandra
root@896757f0bfd4:/# ls
bin dev etc libmediaopt root sbin sys usr
boot docker-entrypoint.sh home lib64 mntproc run srv tmp var
root@896757f0bfd4:/#
10. 监听一个容器的事件:
当你编写自己的脚本,或者只是想了解发生了什么,你可以 Docker event command 运行你的镜像,为此编写脚本很容易。
这是我们没有使用 Docker Compose 和 Swarm yet 和 Docker 1.9 网络层 特性的情况,Docker 一个很酷的工具,有一套伟大的工具。在未来希望 Docker 越来越好,我也会给大家展示一些 Docker 更酷的东西。
更多 Docker 相关教程见以下内容:
Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
Ubuntu 14.04 安装 Docker http://www.linuxidc.com/linux/2014-08/105656.htm
Ubuntu 使用 VNC 运行基于 Docker 的桌面系统 http://www.linuxidc.com/Linux/2015-08/121170.htm
阿里云 CentOS 6.5 模板上安装 Docker http://www.linuxidc.com/Linux/2014-11/109107.htm
Ubuntu 15.04 下安装 Docker http://www.linuxidc.com/Linux/2015-07/120444.htm
在 Ubuntu Trusty 14.04 (LTS) (64-bit)安装 Docker http://www.linuxidc.com/Linux/2014-10/108184.htm
在 Ubuntu 15.04 上如何安装 Docker 及基本用法 http://www.linuxidc.com/Linux/2015-09/122885.htm
Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-12/126586.htm