Docker之旅-Docker图形化管理和监控(一)

Docker管理之官方三剑客

Docker Machine

Docker Machine 是 Docker 官方提供的一个工具,它可以帮助我们在远程的机器上安装 Docker,或者在虚拟机 host 上直接安装虚拟机并在虚拟机中安装 Docker。我们还可以通过 docker-machine 命令来管理这些虚拟机和 Docker。

  • 以前你需要登录主机,按照主机及操作系统特有的安装以及配置步骤安装Docker,使其能运行Docker容器。
  • 现在DockerMachine的产生简化了这一过程,让你可以使用一条命令在你的计算机,公有云平台以及私有数据中心创建及管理Docker主机。

安装Docker Machine

在macOS和Windows上,Machine会随着Docker for Mac, Docker for Windows, 或 Docker Toolbox一起安装.

独立安装Docker Machine

这里以ubuntu 18.04为例,其他系统安装参见官方文档Docker Machine

1
2
3
# base=https://github.com/docker/machine/releases/download/v0.16.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo install /tmp/docker-machine /usr/local/bin/docker-machine

查看 Machine version:

1
2
# docker-machine version
docker-machine version 0.16.0, build 702c267f

在远程主机上安装 Docker

在使用 docker-machine 进行远程安装前我们需要做一些前提准备工作:

在目标主机上启用root或创建具有sudo权限的普通用户

启用root ssh 登陆

1
2
3
4
5
6
7
#允许root ssh登录
$ sudo -i
$ sed -i -e "s/PermitRootLogin without-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
#重启SSH
$ service ssh restart
#按提示设置root用户密码
$ passwd root

或者创建一个具有sudo权限的普通用户,这里以创建一个用户为例

1
2
$ sudo adduser worker1
$ sudo usermod -a -G sudo worker1

配置用户ssh免密登录

启用visiblepw

1
2
3
4
$ sudo visudo
#在文件前添加
Defaults visiblepw
#按Ctrl+O保存 Ctrl+X退出

编辑nopasswdsudo

1
2
3
$ vim /etc/sudoers.d/nopasswdsudo
在文件中添加
worker1 ALL=(ALL) NOPASSWD : ALL

把本地用户的 ssh public key 添加到目标主机上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ssh-copy-id -i ~/.ssh/id_rsa.pub worker1@192.168.48.202
# 若用户下未生成过key,使用如下命令生成后再执行上条命令
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xW6kJVWFItg6Lirdi7G1Jte8+lD3FaA/7BSedCICKt0 root@ubuntu
The key's randomart image is:
+---[RSA 2048]----+
| . o o..o. |
| . o .. o+... |
|. o E ..+.O.o |
| . o. & = . |
| ...S X . |
| .... = o |
| ..oo+ o |
|. +=+oo |
| .o+++o. |
+----[SHA256]-----+
在本地主机执行安装命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ docker-machine create -d generic \
--generic-ip-address=192.168.48.202 \
--generic-ssh-user=worker1 \
--generic-ssh-key ~/.ssh/id_rsa \
machine-worker1
Running pre-create checks...
Creating machine...
(machine-worker1) Importing SSH key...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env machine-worker1

create 命令创建虚拟主机并安装 Docker
-d –driver 的简写形式,主要用来指定使用什么驱动程序来创建目标主机
另外支持的驱动详见:Machine drivers
本例中使用 generic 下面以 –generic 开头的三个参数主要是指定操作的目标主机和使用的账户
machine-worker1 参数是虚拟机的名称

检查安装结果

1
2
3
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
machine-worker1 - generic Running tcp://192.168.48.202:2376 v18.09.0

使用本地的客户端连接远程的服务器

1
$ eval $( docker-machine env machine-worker1)

这样就可以愉快的在本地管理远端的docker了
另外docker-machine支持的命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Commands:
active Print which machine is active
config Print the connection config for machine
create Create a machine
env Display the commands to set up the environment for the Docker client
inspect Inspect information about a machine
ip Get the IP address of a machine
kill Kill a machine
ls List machines
provision Re-provision existing machines
regenerate-certs Regenerate TLS Certificates for a machine
restart Restart a machine
rm Remove a machine
ssh Log into or run a command on a machine with SSH.
scp Copy files between machines
mount Mount or unmount a directory from a machine with SSHFS.
start Start a machine
status Get the status of a machine
stop Stop a machine
upgrade Upgrade a machine to the latest version of Docker
url Get the URL of a machine
version Show the Docker Machine version or a machine docker version
help Shows a list of commands or help for one command

对于远程管理来说,SSH 的支持是必不可少的!Docker Machine 当然也尽职尽责的完成了任务:

1
$ docker-machine ssh machine-worker1

执行上面的命令,瞬间穿越至目标主机,双击666

Docker Compose

Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。
实际项目中我们不可能就一个docker容器走天下,正常都是要多个容器合作完成任务,如果我们一个一个容器去启动,势必很麻烦头大,docker-compose 可以解决我们的问题,下面简单实例以springboot服务+mysql数据库服务
项目结构如下,

  • demo 是我们的springboot web工程
  • mysql目录,可以加一下针对mysql的配置
  • docker-compose.yaml 猪脚,描述如何构建整个服务

docker-compose.yaml 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3'
services:
mysql:
container_name: demo-mysql
image: mysql/mysql-server:5.7
volumes:
- ./mysql/data:/var/lib/mysql
environment:
MYSQL_DATABASE: demo
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: '%'
ports:
- "3306:3306"
restart: always

demo:
restart: always
build: ./demo
working_dir: /demo
volumes:
- /etc/localtime:/etc/localtime:ro
- ./demo:/demo
- ~/.m2:/root/.m2
ports:
- "8080:8080"
depends_on:
- mysql
command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker
  • version: ‘3’: 表示使用第三代语法来构建 docker-compose.yaml 文件。
  • services: 用来表示 compose 需要启动的服务,我们可以看出此文件中有2个服务分别为:mysql、demo。
  • container_name: 容器名称
  • environment: 此节点下的信息会当作环境变量传入容器,此示例中 mysql 服务配置了数据库、密码和权限信息。
  • ports: 表示对外开放的端口
  • restart: always 表示如果服务启动不成功会一直尝试。
  • volumes: 加载本地目录下的配置文件到容器目标地址下
  • depends_on:可以配置依赖服务,表示需要先启动 depends_on 下面的服务后,再启动本服务。
  • command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker: 表示以这个命令来启动项目,-Dspring-boot.run.profiles=docker表示使用 application-docker.properties文件配置信息进行启动。

Spring Boot 项目配置

在demo 目录下也就是和pom.xm文件同级添加Dockerfile文件,文件内容如下:

1
FROM maven:3.5-jdk-8

只要这一句,依赖于基础镜像maven3.5和jdk1.8。
因为在docker-compose.yaml文件设置了项目启动命令,这里不需要再添加启动命令

application-docker.properties 添加针对于docker的配置:

1
2
3
4
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysql:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

项目部署

以下命令在docker-compose.yaml 同级目录执行
启动服务:

1
docker-compose up --build


停止服务:

1
docker-compose down


查看项目中目前的所有容器

1
docker-compose ps


就是这么简单。

项目GitHub源码

Docker Swarm

Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。

Docker Swarm的获取

从Docker(1.12版本以后) swarm 已整体集成在Docker Engine中,这里我们只讨论新版本中docker swarm的使用

创建一个Swarm的集群

详细参数参见官方文档https://docs.docker.com/engine/reference/commandline/swarm_init/#options

1
docker swarm init [OPTIONS]

1
2
3
4
5
6
7
8
$ docker swarm init --listen-addr 0.0.0.0:2377 --advertise-addr 192.168.48.244
Swarm initialized: current node (unegtfborf8ldmn41h89rttzf) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-5i1itkmhe4tehzbqhas4wztns 192.168.48.244:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

–listen-addr 指出的是这个集群暴露给外界调用的HTTPAPI的socket地址
–advertise-addr 标志配置了管理节点的 IP 地址。如果你的机器只有一张网卡,可以省略。

Swarm的集群管理

向Swarm的集群中添加节点

分别在第二台、第三台主机上执行以上生成的 docker swarm join –token命令

1
2
3
4
5
6
7
8
9
10
# 输出添加一个worker节点命令
$ docker swarm join-token worker
To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-5i1itkmhe4tehzbqhas4wztns 192.168.48.244:2377
# 输出添加一个manager节点命令
$ docker swarm join-token manager
To add a manager to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-0f54w8ra5ldg27b8yjwe4kg9r 192.168.48.244:2377

为了不用登陆到每台主机中去执行docker swarm join –token命令,这样太麻烦,我们可以结合上面的docker-machine 命令使用,通过docker-machine create添加两台远程主机

1
2
3
4
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
machine-worker1 - generic Running tcp://192.168.48.202:2376 v18.09.0
machine-worker2 - generic Running tcp://192.168.48.203:2376 v18.09.0

分别将machine-worker1,machine-worker2 作为一个节点添加到swarm集群,执行如下命令

1
2
3
4
$  docker-machine ssh machine-worker1 "sudo docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-5i1itkmhe4tehzbqhas4wztns 192.168.48.244:2377"
This node joined a swarm as a worker.
$ docker-machine ssh machine-worker2 "sudo docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-5i1itkmhe4tehzbqhas4wztns 192.168.48.244:2377"
This node joined a swarm as a worker.

无需登录远程主机,这样两个节点就添加进swarm集群了,查看下当前swarm集群中的节点

1
2
3
4
5
$  docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
53bbepypujpr5qi5zzspre7el * master Ready Active Leader 18.09.0
bifyoaqegffgcmooulu749co5 worker1 Ready Active 18.09.0
d94ktuzewdxl9nkszbibilj24 worker2 Ready Active 18.09.0

这样我们就得到了一个由三个节点组成的小集群,manager本身也自动作为worker一员加入集群

节点更新
1
2
$ docker node update --availability drain worker2
worker2

可以手动将某个节点的可用性设置为Drain或者active,比如这里将名为worker2的节点设置为drain了之后,可以看到在docker node ls 中出现的新信息

1
2
3
4
5
$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
53bbepypujpr5qi5zzspre7el * master Ready Active Leader 18.09.0
bifyoaqegffgcmooulu749co5 worker1 Ready Active 18.09.0
d94ktuzewdxl9nkszbibilj24 worker2 Ready Drain 18.09.0

删除节点

执行命令 docker swarm leave –force
这里我们将worker2节点从swarm 集群中移除:

1
2
$ docker-machine ssh machine-worker2 "sudo docker swarm leave --force" 
Node left the swarm.

构建服务

在swarm集群中,管理节点是集群中唯一可以执行命令的机器,或授权其他机器作为manager加入群集,worker只是在那里提供服务能力,并且没有权力告诉任何其他机器它能做什么和不能做什么,为了构建下面的集群服务,我们再次执行上面的添加节点操作把worker2节点添加进集群。

1
2
$ docker-machine ssh machine-worker2 "sudo docker swarm join --token SWMTKN-1-2j9t0uf0a442hks10f4l4bp9fz01j5wkr81twl3mgjyl6fuvva-5i1itkmhe4tehzbqhas4wztns 192.168.48.244:2377"
This node joined a swarm as a worker.

在管理节点执行构建服务命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker service create -p 4000:80 --replicas 5 --name helloswarm yaonew/hellowpy:v1
image yaonew/hellowpy:v1 could not be accessed on a registry to record
its digest. Each node will access yaonew/hellowpy:v1 independently,
possibly leading to different nodes running different
versions of the image.

h926sud2306kg0lirv0dcydwy
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged

docker service create 命令创建服务
-p 端口映射,将容器80端口映射到宿主机4000端口上
–name 标志将服务命名为helloswarm
–replicas 标志指定了期望状态为 5 个运行示例
yaonew/hellowpy:v1 镜像 这里使用了自己构建的镜像

查看服务列表
1
2
3
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
h926sud2306k helloswarm replicated 5/5 yaonew/hellowpy:v1
查看服务详情
1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker service ps helloswarm 
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
kderyu36u33v helloswarm.1 yaonew/hellowpy:v1 worker2 Running Running 15 minutes ago
quly9g70410v helloswarm.2 yaonew/hellowpy:v1 master Running Running 15 minutes ago
frzcgbjkogia helloswarm.3 yaonew/hellowpy:v1 worker2 Running Running 15 minutes ago
jr7xux73fpmo helloswarm.4 yaonew/hellowpy:v1 master Running Running 15 minutes ago
xpqar72dplms helloswarm.5 yaonew/hellowpy:v1 worker1 Running Running 15 minutes ago
```
可以看到swarm集群根据算法将期望运行的5个实例分别运行在master、worker1、worker2上,通过浏览器访问http://192.168.48.244:4000 可以看出swarm自动为我们做了负载均衡,每个请求,以循环方式选择5个实例中的一个来响应。

##### 伸缩服务
``` bash
$ docker service scale helloswarm=10

通过以上命令可以迅速将helloswarm服务提升至10个实例,之前已经启动的5个实例不受影响,将新构建5个实例,查看服务详情。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker service ps helloswarm 
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
vhyxlovgvjdj helloswarm.1 yaonew/hellowpy:v1 worker1 Running Running 9 minutes ago
my8fv4gf5pxg helloswarm.2 yaonew/hellowpy:v1 worker2 Running Running 9 minutes ago
x8p9nuqpmz0p helloswarm.3 yaonew/hellowpy:v1 master Running Running 9 minutes ago
zlx5o9m7jyyf helloswarm.4 yaonew/hellowpy:v1 worker1 Running Running 9 minutes ago
4rbcagnwqn4t helloswarm.5 yaonew/hellowpy:v1 worker2 Running Running 9 minutes ago
tv4x55ihaq7q helloswarm.6 yaonew/hellowpy:v1 master Running Running 24 seconds ago
wvr1dys8psg0 helloswarm.7 yaonew/hellowpy:v1 master Running Running 22 seconds ago
u7uz9lq8l2cd helloswarm.8 yaonew/hellowpy:v1 master Running Running 23 seconds ago
xyt77whcy911 helloswarm.9 yaonew/hellowpy:v1 worker2 Running Running 30 seconds ago
ldi0b1atvzz2 helloswarm.10 yaonew/hellowpy:v1 worker1 Running Running 30 seconds ago

删除swarm上的服务

1
$ docker service rm helloswarm

通过YAML文件构建服务

YAML文件,用于定义Docker容器在生产中的行为方式,yaonew/hellowpy:v1 我们自己的镜像,请确保已推送到远程仓库,下面新建docker-compose.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: yaonew/hellowpy:v1
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:

这个docker-compose.yml文件告诉Docker执行以下操作:
从注册中心中提取镜像。
以此镜像运行5个实例作为一个服务,服务名为web,限制每个实例使用最多10%的CPU(所有核心)和50MB的RAM。
如果如果容器出错,立即重启。
将主机上的端口4000映射到Web的端口80。
指示Web容器通过称为webnet的负载平衡网络共享端口80。
默认使用Webnet网络(负载平衡网络)。

通过yaml文件省去了在命令行添加太多参数的烦恼,运行服务

1
2
3
$ docker stack deploy -c docker-compose.yml helloswarm
Creating network helloswarm_webnet
Creating service helloswarm_web

这里创建了一个网络名称为:helloswarm_webnet 创建了一个服务名称:helloswarm_web
查看服务详情

1
2
3
4
5
6
7
docker service ps helloswarm_web 
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
v3tzalw6trzg helloswarm_web.1 yaonew/hellowpy:v1 worker2 Running Starting 8 seconds ago
xa37injkdiov helloswarm_web.2 yaonew/hellowpy:v1 master Running Starting 4 seconds ago
y81yo07gzsl7 helloswarm_web.3 yaonew/hellowpy:v1 worker1 Running Running less than a second ago
2ujbxosbiu2z helloswarm_web.4 yaonew/hellowpy:v1 worker2 Running Starting 8 seconds ago
1fa0jsr09v5i helloswarm_web.5 yaonew/hellowpy:v1 master Running Starting 4 seconds ago

查看容器信息

1
2
3
4
# 各主机查看启动容器id
$ docker container ls -q
# 查看所有容器
$ docker ps -a

扩展应用
我们可以通过更改docker-compose.yml文件,并重新运行docker stack deploy命令来扩展应用程序:

1
2
3
4
5
6
docker stack deploy -c docker-compose.yml helloswarm
Updating service helloswarm_web (id: xa3th1y6lwz45ca3c0dpgu872)
image yaonew/hellowpy:v1 could not be accessed on a registry to record
its digest. Each node will access yaonew/hellowpy:v1 independently,
possibly leading to different nodes running different
versions of the image.

Docker执行就地更新,无需杀死任何容器。
现在,重新运行docker container ls -q以查看已重新配置的已部署实例。 如果增加实例数量,则会启动更多任务,从而启动更多容器。

清理退出

1
2
3
docker stack rm helloswarm 
Removing service helloswarm_web
Removing network helloswarm_webnet

项目GitHub源码

参考文章

https://docs.docker.com/machine/overview/
http://blog.51cto.com/hashlinux/1772507
https://www.cnblogs.com/sparkdev/p/7044950.html
https://docs.docker.com/compose/overview/
https://docs.docker.com/engine/reference/commandline/swarm/
https://www.cnblogs.com/franknihao/p/8490416.html
https://blog.csdn.net/u011936655/article/details/81147315

-------------本文结束感谢您的阅读-------------
Alex.Yao wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!