Docker Compose
Docker Compose
简介
是一个定义和运行多个容器的工具,使用YAML配置文件。Compose是Docker官方的开源项目,需要我们自己安装使用。服务、应用是一个个容器,Compose将关联容器组成一个Project来运行。
Docker-Compose将所管理的容器分为三层:
- 工程(project):由一组关联的应用容器组成的一个完成业务单元,在docker-compose.yml中定义。即是 Compose的一个配置文件可以解析为一个项目,Compose通过分析指定配置文件,得出配置文件所需完成的所 有容器管理与部署操作。
- 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。每个服务都有自己的名 字、使用的镜像、挂载的数据卷、所属的网络、依赖哪些其他服务等等,即以容器为粒度,用户需要Compose 所完成的任务。
- 容器(container)
一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例。
Compose 使用的三个步骤:
- 使用 Dockerfile 定义应用程序的环境。
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
- 最后,执行 docker-compose up 命令来启动并运行整个应用程序。
安装
下载
1
curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
授权
1
2
3[root@io bin]# chmod +x docker-compose
[root@io bin]# docker-compose version
Docker Compose version v2.6.1体验
准备
创建一个测试目录:
1
2$ mkdir composetest
$ cd composetest在测试目录中创建一个名为 app.py 的文件,并复制粘贴以下内容:
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
26import time
import redis
from flask import Flask
app = Flask(__name__)
#host 域名
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)在此示例中,redis 是应用程序网络上的 redis 容器的主机名,该主机使用的端口为 6379。
在 composetest 目录中创建另一个名为 requirements.txt 的文件,内容如下:
1
2flask
redis创建Dockerfile文件
在 composetest 目录中,创建一个名为 Dockerfile 的文件,内容如下:
1
2
3
4
5
6
7
8
9FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]Dockerfile 内容解释:
FROM python:3.7-alpine: 从 Python 3.7 映像开始构建镜像。
WORKDIR /code: 将工作目录设置为 /code。
ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0复制 requirements.txt 并安装 Python 依赖项。1
2
3
4
5
6
7
8
设置 flask 命令使用的环境变量。
- **RUN apk add --no-cache gcc musl-dev linux-headers**: 安装 gcc,以便诸如 MarkupSafe 和 SQLAlchemy 之类的 Python 包可以编译加速。
- ```
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txtCOPY . .: 将 . 项目中的当前目录复制到 . 镜像中的工作目录。
CMD [“flask”, “run”]: 容器提供默认的执行命令为:flask run。
创建 docker-compose.yml
1
2
3
4
5
6
7
8
9# yaml 配置
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"该 Compose 文件定义了两个服务:web 和 redis。
- web:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。
- redis:该 redis 服务使用 Docker Hub 的公共 Redis 映像。
使用 Compose 命令构建和运行您的应用
在测试目录中,执行以下命令来启动应用程序:
1
docker-compose up
如果你想在后台执行该服务可以加上 -d 参数:
1
docker-compose up -d
查看结果
1
2[root@io yio]# curl localhost:5000
Hello World! I have been seen 13 times.关闭服务
1
docker compose down
查看一下网络
1
docker network inspect composetest_default

YAML规则
1 | # 3层 |
多看多想,看官网,开源项目
一键部署WP博客
1 | version: '3' |
##Docker Swarm
简介
如下图所示,swarm 集群由管理节点(manager)和工作节点(work node)构成,A given Docker host can be a manager, a worker, or perform both roles,如果一个Worker挂掉了,这个Worker中的task就会被交给其他的Worker执行,每个task都不是以一个独立的容器运行的。
- swarm mananger:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作,manage node也可以执行服务,但是可以自己配置它只运行管理工作。
- worker node:即图中的 available node,主要负责运行相应的服务来执行任务(task)。

一些优点:Swarm支持我们自定义服务的配置,并且自动生效。集群中的node仍然可以运行一个独立的容器,Swarm中的容器只会被Swarm Manager管理控制,这是与独立的容器之间的区别。
###Raft一致性协议
Raft协议是一种基于日志复制的一致性算法,通过选举领袖的方式来实现的。
基本概念:
复制状态机(Replicated state machines)
将集群中的每个服务器看做一个状态机, 它们接收外部的指令, 进行状态的改变。只要初始状态和接收到的指令是确定的, 那么它任意时刻的状态也是确定的, 这样以来, 所谓保持分布式一致性即是保证集群中所有状态机的状态一致性
领导人(leader)、跟随者(follower) 和 候选人(candidate)
raft 将所有服务器结点划分为 3 个互不相交的子集, 任何一个结点都隶属于某一个集合, 其中地位最高的结点称为领导人(leader), 它负责接收来自客户端的调用, 组织日志复制给其它结点, 统筹管理整个计算机集群, raft 保证集群中在任意时刻至多有一个领导人, 跟随者(follower)接收来自领导人(leader)的复制日志, 按照领导人(leader)的要求进行相应的动作。领导人(leader)持续地向集群中的所有其它结点发送心跳包, 以此宣告“你们的皇帝还活着”。一旦跟随者(follower)在给定的时间内没有收到来自领导人(follower)的心跳包, 它便认为领导人出了故障, 于是转变自己的身份为候选人(candidate)进行领导人的竞选。
任期(term)
raft 将系统时间划分为一个个逻辑段, 每个逻辑段的时间长度是不一致的, 可以是任意长度, 每一个逻辑段称为一个任期(term), raft 对每一个任期都设置一个整型编号, 称为任期号(类似皇帝的年号或者说最后的庙号), 每一个任期可以进一步划分为两个子段, 其中第一个子段是选举期, 第二个子段是任职期, 选举期将竞选产生集群的领导人, 若领导人选举成功, 则进入了任职期, 在任职期内只要领导人持续保持健康状态(即持续不间断地向其他跟随者发送心跳包), 则这个时期可以无限期地持续, 当然在 raft 中选举不一定都是成功的, 可能存在某个 term 中的选举期没有任何候选人胜出, 这样 raft 会进行下一个 term, 重新进行选举, 直到有新的领导人胜出, 从而进入任职期, raft 采用了特别的机制来尽可能地避免一个 term 中没有任何候选人竞选成功的情形出现。
日志(log)与日志复制(log replication)
raft 将集群中的所有服务器看做若干个状态机, 状态机接收指令进行状态的变更, 在 raft 协议中, 指令是以日志的形式的传递的, 虽然集群中有N个结点, 但只有一个结点(领导人)接收客户端的请求, 其它所有结点接收来自领导人的复制日志(Replicated log), 进行解析、和执行, 从而进行状态的变更, 所有服务器结点按序执行相同的日志(指令), 从而保持状态一致性。(Hadoop的集群)
日志提交(commit)
领导人在接收到客户端请求之后, 会产生一个相应的日志项(log entry), 日志项中包含了指令, 领导人不会立即执行这个指令, 它首先会进行日志项复制, 当日志项被成功地复制到集群中的大多数结点(超多半数,一半以上不包括一半)后, 领导人会提交(commit)这个日志项, 并执行其中的指令(即将该日志应用(apply)到状态机中)
使用
Docker Machine 创建Docker主机
安装:
1
2$ sudo curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine
$ sudo chmod +x /usr/local/bin/docker-machine创建四个主机
1
2
3
4docker-machine create -d virtualbox manager1 &&
docker-machine create -d virtualbox manager2 &&
docker-machine create -d virtualbox worker1 &&
docker-machine create -d virtualbox worker2查看主机信息
1
docker-machine ls
Docker Swarm 配置集群节点
创建管理节点(初始化)
1
2#在manager1主机上,创建一个 Docker Swarm 管理节点(初始化集群的时候,会自动把当前节点设置为管理节点)
docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.99.100"创建工作节点并加入到集群
1
2
3
4
5
6#1
docker-machine ssh worker1 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.
#2
docker-machine ssh worker2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.另一个管理节点
1
2
3
4
5
6
7#先在manager1主机上,获取管理节点对应的token,然后再配置为管理节点
[user]docker-machine ssh manager1 "docker swarm join-token manager"
+To add a manager to this swarm, run the +following command:
+
+ docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377
[user] docker-machine ssh manager2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377"查看集群信息
1
2
3
4
5
6
7
8#进入manager1内
[user]docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
n0ub7dpn90rxjq97dr0g8we0w * manager1 Ready Active Leader
t4cy67qp0bf2spgabsutwxnzt manager2 Ready Active Reachable
if0kmzp4ww3oy57y7cha7v36t worker1 Ready Active
jgg61cujzaeb3du5796fm0x2g worker2 Ready Active
#Leader表示领导者,Reachable表示候选人,头一挂掉它就顶上去了,可以不指定,会选举。
Docker Service 部署单个集群服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# --replicas 4 表示四个副本 实际上这个副本可以更多 每个容器中可以多跑几个服务来分配
docker service create --replicas 4 -p 8088:80 --name nginx 192.168.99.1:5000/nginx:latest
#此时四个docker任意一个ip都可以访问服务
#也可以手动设置实例个数
docker service scale nginx=4
#
#查看服务
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ap8h8srb8yh3 nginx replicated 4/4 192.168.99.1:5000/nginx:latest *:8080->8080/tcp
$ docker service ps nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
l2rdrwzs5zog nginx.1 192.168.99.1:5000/nginx:latest manager1 Running Running about a minute ago
vsfczzbwanx3 nginx.2 192.168.99.1:5000/nginx:latest manager2 Running Running about a minute ago
qtbgw5h6dsi9 nginx.3 192.168.99.1:5000/nginx:latest worker Running Running about a minute ago
za2ejnvb3n6z nginx.4 192.168.99.1:5000/nginx:latest worker2 Running Running about a minute agoDocker Stack 部署多个集群服务
以后可以使用k8s了
使用
docker stack进行多服务编排部署,使用的同样是docker-compose.yml配置文件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
29
30
31
32version: "3"
services:
nginx:
image: 192.168.99.1:5000/nginx:latest
ports:
- 8088:80
deploy:
mode: replicated
replicas: 4
visualizer:
image: 192.168.99.1:5000/dockersamples/visualizer:latest
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
portainer:
image: 192.168.99.1:5000/portainer/portainer:latest
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]1
2
3
4
5
6
7
8#部署
docker stack deploy -c docker-compose.yml deploy-demo
#查看
docker stack ls
#
#去浏览器看
http://192.168.99.100:8080/
http://192.168.99.100:9000/常用命令
docker-machine命令 说明 docker-machine create 创建一个 Docker 主机(常用 -d virtualbox)docker-machine ls 查看所有的 Docker 主机 docker-machine ssh SSH 到主机上执行命令 docker-machine env 显示连接到某个主机需要的环境变量 docker-machine inspect 输出主机更多信息 docker-machine kill 停止某个主机 docker-machine restart 重启某台主机 docker-machine rm 删除某台主机 docker-machine scp 在主机之间复制文件 docker-machine start 启动一个主机 docker-machine status 查看主机状态 docker-machine stop 停止一个主机 docker swarm命令 说明 docker swarm init 初始化集群 docker swarm join-token worker 查看工作节点的 token docker swarm join-token manager 查看管理节点的 token docker swarm join 加入集群中 docker node命令 说明 docker node ls 查看所有集群节点 docker node rm 删除某个节点( -f强制删除)docker node inspect 查看节点详情 docker node demote 节点降级,由管理节点降级为工作节点 docker node promote 节点升级,由工作节点升级为管理节点 docker node update 更新节点 docker node ps 查看节点中的 Task 任务 docker service命令 说明 docker service create 部署服务 docker service inspect 查看服务详情 docker service logs 查看某个服务日志 docker service ls 查看所有服务详情 docker service rm 删除某个服务( -f强制删除)docker service scale 设置某个服务个数 docker service update 更新某个服务 docker stack命令 说明 docker stack deploy 部署新的堆栈或更新现有堆栈 docker stack ls 列出现有堆栈 docker stack ps 列出堆栈中的任务 docker stack rm 删除堆栈 docker stack services 列出堆栈中的服务 docker stack down 移除某个堆栈(不会删除数据)
docker secretdocker config·····
