飞天班第46节:Docker精通-4

2020/06/09

1、Docker Compose(重点)

简介

前面我们学了使用Dockerfile,build 生成 image 镜像,run 运行成 container 容器,但这只适合单个服务,我们的微服务架构通常包含多个服务,如何一起部署?

微服务架构(多个服务),会部署多个实例!大量的服务如果都需要手动启停,效率很低!

使用Docker Compse,高效轻松管理我们容器!运行多容器!

官网:https://docs.docker.com/compose/

介绍:

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to

compose 是一个定义和运行多个包含docker应用的容器的工具。使用compose,你可以用一个yaml文件去配置

configure your application’s services. Then, with a single command, you create and start all the services from your

你的应用服务。然后用一个简单的命令,通过你的yaml文件配置去创建和启动所有的服务。

configuration. To learn more about all the features of Compose, see the list of features.

需要了解更多,你可以看 compose的特性

Compose works in all environments: production, staging, development, testing, as well as CI workflows.

Compose 工作在所有的环境:生产、准备环境、开发、测试,

You can learn more about each case in Common Use Cases.

你可以通过Compose 使用案例,了解更多

Using Compose is basically a three-step process:

使用 Dockercompose的3个基本核心步骤:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

    用一个Dockerfile定义你的app环境。这样它在其他地方可以使用

  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

    在docker-compose.yml定义组成你的应用程序的所有服务。这样它们可以在一个独立的环境一起运行。

  3. Run docker-compose up and Compose starts and runs your entire app.

    运行 docker-compose up命令,启动运行你的整个应用程序。

Docker Composr 就是一个核心功能: 批量编排服务!比如你有10个服务,你可以通过docker-compose up down 一键启停所有服务。

DockerCompose 本质就是Docker官方的一个开源项目,负责实现Docker容器集群的快速编排!

项目地址:https://github.com/docker/compose

Compose has commands for managing the whole lifecycle of your application:

Docker-compose 管理你的应用的整个生命周期的命令

  • Start, stop and rebuild services

    启动、停止、重建服务

  • View the status of running services

    查看服务的状态

  • Stream the log output of running services

    输出服务日志

  • Run a one-off command on a service

    关闭一个服务的命令

安装

确保服务器已安装docker引擎,然后选择 docker compose所对应的系统版本安装

1、下载

# 在linux上安装docker compose,它依赖下面的一些python环境
py-pip, python-dev, libffi-dev, openssl-dev, gcc, libc-dev, and make.
# 使用yum安装这些依赖
yum install -y py-pip
# 1、下载,这个网络十分慢,有可能还下载失败!
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 这个可能快点!16.7m大小 docker-compose 
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

# 如果第一步没有下载下来,我们就手动去网站下载即可!
# 地址:https://github.com/docker/compose/releases
# 下载:docker-compose-Linux-x86_64
# 然后将文件上传到 /usr/local/bin/ 文件夹下,然后将其重命名为docker-compose

# 2、修改此文件的权限,增加可执行
sudo chmod +x /usr/local/bin/docker-compose

# 查看版本信息,确认安装成功
[root@alibaba bin]# docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

# 3、卸载docker compose
sudo rm /usr/local/bin/docker-compose

2、赋予权限

chmod +x /usr/local/bin/docker-compose

快速开始

# pip 是Pyhon的包管理工具!
[root@alibaba bin]# yum install -y python-pip  

用一个简单的python web 应用:基于Flask框架,维护redis中的访问数的web应用。快速开始docker-compose,参考文档:https://docs.docker.com/compose/gettingstarted/

按照官方文档走一篇

Python例子

1、配置

  • 创建项目目录

      [root@alibaba www]# mkdir composetest
      [root@alibaba www]# cd composetest
    
  • composetest下创建一个app.py python文件,复制下面代码

    import time
      
    import redis
    from flask import Flask
      
    app = Flask(__name__)
    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)
      
    # 路由,把看了多少次的次数丢回来           
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.\n'.format(count)
    
  • composetest定义另一个requirements.txt文件,复制下面内容,其实就是定义依赖包

    flask
    redis
    

2、创建一个Dockerfile,通过它构建镜像

# 下载python3.7作为基础镜像
FROM python:3.7-alpine
# 设置工作目录
WORKDIR /code
# 设置两个环境变量
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
# 安装gcc,一些环境的添加
RUN apk add --no-cache gcc musl-dev linux-headers
# 导入requirements.txt文件,安装依赖,也就是flask和redis
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# 复制当前目录文件到镜像里的工作目录,
COPY . .
# 运行起来,类似于java -jar 命令
CMD ["flask", "run"]

3、在Compose 文件定义服务

创建一个docker-compose.yml文件,定义web和redis俩个服务,复制下面内容

version: '3'
# 可以有多个服务
services:
  web:
  	# 相当于docker build,很多的编排指令!
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

web服务,是使用当前目录下的Dockerfile build创建的镜像,它绑定的是宿主机的5000端口到容器内flask web server的默认5000端口

redis服务,是从Docker hub 仓库拉取的公共Redis镜像

# 已有4个文件
[root@alibaba composetest]# ls
app.py  Dockerfile  requirements.txt docker-compose.yml

4、使用Compose 创建和运行你的应用

# 建议先单独pull拉取 python 和redis两个镜像到服务器
[root@alibaba composetest]# docker pull python:3.7-alpine
[root@alibaba composetest]# docker pull redis:alpine
# 要在项目目录下执行docker-compose up
[root@alibaba composetest]# docker-compose up
# 启动关闭
docker-compse up / down

浏览器 访问 http://localhost:5000/ , see the application running.服务器防火墙和安全组要开放5000端口

发现通过 docker-compse up,会阻塞控制台!我再打开一个控制台,使用curl命令测试

[root@alibaba ~]# curl localhost:5000
Hello World! I have been seen 1 times.
[root@alibaba ~]# curl localhost:5000
Hello World! I have been seen 2 times.

查看镜像

[root@alibaba ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
composetest_web       latest              2f7c2a237d5f        11 minutes ago      227MB
redis                 alpine              b546e82a6d0e        17 hours ago        31.5MB

关闭应用

# 在项目目录下执行
[root@alibaba composetest]# docker-compose down
Stopping composetest_redis_1 ... done
Stopping composetest_web_1   ... done
# 对应的容器也会删除,docker ps -a 命令查看
Removing composetest_redis_1 ... done
Removing composetest_web_1   ... done
# 网络也会删除
Removing network composetest_default

5、修改docker-compose.yml文件,增加数据卷的挂载,指定Flask为开发环境

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_ENV: development
  redis:
    image: "redis:alpine"

把宿主机的当前目录和容器内的/code目录做挂载,这样你修改了代码,也不用重建镜像(传统的做法:进入容器修改,修改完后通过commit 容器重建成为新的镜像)。环境变量FLASK_ENV为开发者模式,当代码被修改后会自动reload 重新运行web应用,开发中使用开发模式很方便。

6、使用Compose 重建创建和运行你的应用

[root@alibaba composetest]# docker-compose up

运行成功,查看运行的容器

7、更新应用app.py

因为已经将容器内的/code目录挂载到了项目目录下,所以我们可以直接修改代码app.py,马上看到效果,不用重建镜像

# 修改app.py,返回的message 修改为
[root@alibaba composetest]# vim app.py 
return 'Hello from Docker! I have been seen {} times.\n'.format(count)

# 马上访问测试,返回信息已经变了
[root@alibaba composetest]# curl localhost:5000
Hello from Docker! I have been seen 4 times.

8、-d后台运行,查看compose的状态

# 后台运行 
docker-compose up -d

# 停止服务,与down的区别是不会移除容器,也就是可以通过start重启服务
[root@alibaba composetest]# docker-compose stop
Stopping composetest_web_1   ... done
Stopping composetest_redis_1 ... done
[root@alibaba composetest]# docker-compose start
Starting web   ... done
Starting redis ... done
[root@alibaba composetest]# curl localhost:5000 
Hello from DockerCompose! I have been seen 5 times.

# 查看运行的服务
[root@alibaba composetest]# docker-compose ps
       Name                      Command               State           Ports         
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp              
composetest_web_1     flask run                        Up      0.0.0.0:5000->5000/tcp

# 使用down,停止服务并移除容器,传递--vloumes 参数同时移除容器挂载的数据
# 下面使用的是docker 搭建的mywordpress博客
[root@alibaba my_wordpress]# docker-compose down --volumes
Removing my_wordpress_wordpress_1 ... done
Removing my_wordpress_db_1        ... done
Removing network my_wordpress_default
Removing volume my_wordpress_wordpress_db_data  # 移除挂载目录

Java 例子

创建一个Spring Initialzr项目,选择web和redis依赖

1、配置文件application.yml

# 使用服务名连接
spring.redis.host=redis
# 默认端口是6379

2、web层接口的定义HelloController

@RestController
public class HelloController {
	@Autowired
	StringRedisTemplate stringRedisTemplate;


	@GetMapping("/")
	public String hello(){
		Long view = stringRedisTemplate.opsForValue().increment("view");
		return "Hello from DockerCompose! I have been seen "+ view +" times.\\n";
	}
}

3、项目根目录下创建Dockerfile文件

FROM java:8
# 拷贝当前目录下的所有jar包到app.jar
COPY *.jar /app.jar
# 配置应用tomcat的端口
CMD ["--server.port=8080"]
# 暴露容器的端口
EXPOSE 8080
# 设置容器的入口程序
ENTRYPOINT ["java","-jar","/app.jar"]

4、项目根目录下创建docker-compose.yml文件,定义web服务和redis服务

# 容器 =》 服务
version: '3.8'
services:
	compose-web: 
		build: .
		image: compose-web  # 指定创建的镜像名称
		depends_on:
			- redis
		ports: 
			- "8080:8080"
	redis: 
    image: "redis:alpine"

compose file的官方文档命令: https://docs.docker.com/compose/compose-file/

# depends_on
docker-compose up启动服务的依赖顺序

5、项目compose-web打包

# 创建项目目录composejava
[root@alibaba www]# mkdir composejava
[root@alibaba www]# cd composejava
# 上传Dockerfile、docker-compose.yml、项目运行jar包到当前目录
[root@alibaba composejava]# ls
compose-web-0.0.1-SNAPSHOT.jar  docker-compose.yml  Dockerfile

6、使用Compose 创建和运行你的应用

# 要在项目目录下执行docker-compose up
[root@alibaba composejava]# docker-compose up
# 后台运行 docker-compose up --help 帮助命令
[root@alibaba composejava]# docker-compose up -d

第一步,先去下载java:8镜像

使用curl命令测试

[root@alibaba composejava]# curl localhost:8080
Hello from DockerCompose! I have been seen 1 times.
[root@alibaba composejava]# curl localhost:8080 

细节探究

1、容器

# docker-compose up运行后,查询容器
[root@alibaba www]# docker ps
CONTAINER ID        IMAGE                 PORTS                    NAMES
ac4cf875adaf        compose-web           0.0.0.0:8080->8080/tcp   composejava_compose-web_1
1433dacfbe39        redis:alpine        6379/tcp                 	composejava_redis_1

# 镜像名:在 docker-compse.yml 中命名!
# 容器名:composejava_compose-web_1   composejava_redis_1
# 容器名默认规则: contextName(上下文,项目目录名)_服务名_num ,服务名在 docker-compse.yml中命名,num 按 1、2、3、4...副本(实例)可以有多个,
# 容器名后面的_1,就是代表了有几个副本,集群状态下,我们可以定义一个服务在多个机器下都有副本! 高可用!

2、网络

[root@alibaba composejava]# docker network ls
NETWORK ID          NAME                  DRIVER              SCOPE
ff7225883433        bridge                bridge              local
4761487649f4        composejava_default   bridge              local
25538e0aaebc        host                  host                local
1da6a07a9ace        none                  null                local

# docker-compse up 服务上线之后,自动多一个网络 composejava_default。
# docker-compose.yml 在同一服务编排下,会在同一个网络下!网络名格式:contextName(上下文,项目目录名)_default 
# 可以在docker-compose.yml 中设置

# 查看网络的全部信息
[root@alibaba composejava]# docker inspect 4761487649f4
  "Containers": {
            "704a94be9c267f0499604f2c3c4e9e5071f13444b6183e14d5cb3f347097d226": {
                "Name": "composejava_compose-web_1",
                "EndpointID": "d1450b0e78cf7cc250f5fb761f1497155b33540521420495df54abf920f7ce6a",
                "MacAddress": "02:42:ac:15:00:03",
                "IPv4Address": "172.21.0.3/16",
                "IPv6Address": ""
            },
            "800bb7ccba16a7d8e211b4549914cc96ba63728c64638d956549fc01947d1127": {
                "Name": "composejava_redis_1",
                "EndpointID": "9f5d6e45c35296c571771c8cd40f7705546871054b1d1e05fce673218b4f1976",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            }
        },
# 发现编排的服务都在一个网络中,我们就可以使用服务名来ping通!所以配置application.properties 中spring.redis.host=redis,
# 这个redis是服务名,直接使用服务名来连接

3、服务

查看所有的服务信息,我们现在发现是没有的,需要在集群下,就可以看到所有的服务!需要使用docker swarm init ,下面开始讲

# 停止 = 移除容器 + 移除网络
docker-compose down
# --volumes 使用该参数移除挂载的数据卷

配置说明

1、docker compose cli 客户端命令,通过官方文档学习或者help命令学习

# 查看docker-compose 帮助命令
[root@alibaba composejava]# docker-compose --help
Define and run multi-container applications with Docker.

Usage:
  docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  docker-compose -h|--help

Options:
  -f, --file FILE             Specify an alternate compose file 指定compose文件名,默认docker-compse.yml
                              (default: docker-compose.yml) 
  -p, --project-name NAME     Specify an alternate project name 指定项目名,默认目录名,上下文
                              (default: directory name) 
  --verbose                   Show more output
  --log-level LEVEL           Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
  --no-ansi                   Do not print ANSI control characters
  -v, --version               Print version and exit
  -H, --host HOST             Daemon socket to connect to
  
Commands:
  build              Build or rebuild services  创建服务
  config             Validate and view the Compose file  
  create             Create services
  down               Stop and remove containers, networks, and volumes 关闭服务,移除容器,网络
  events             Receive real time events from containers 
  exec               Execute a command in a running container 进入容器
  help               Get help on a command
  images             List images
  kill               Kill containers
  logs               View output from containers
  pause              Pause services
  port               Print the public port for a port binding
  ps                 List containers
  pull               Pull service images
  push               Push service images
  restart            Restart services
  rm                 Remove stopped containers
  run                Run a one-off command
  scale              Set number of containers for a service
  start              Start services
  stop               Stop services
  top                Display the running processes
  unpause            Unpause services
  up                 Create and start containers 
  version            Show the Docker-Compose version information  

Docker run -> docker-compose-> swarm

docker-compose.yaml 记好三层

2、docker-compose.yaml的官方文档命令: https://docs.docker.com/compose/compose-file/

# docker-compose.yaml  记好三层
# 第一层 版本
version: ''  # 版本,向下兼容的
# 第二层 服务
services: # 服务,可以有一个和多个
	服务1:
		# 服务的具体配置(build、端口、挂载卷、网络、command、容器名、depends_on:启动顺序,deploy:集群多个服务实例replicas)
	服务2: 
	  # 服务的具体配置(build、端口、挂载卷、网络、command、容器名、depends_on:启动顺序,deploy:集群多个服务实例replicas)
	....
# 第三层 其他配置
networks  容器(服务)运行的网络配置
volumes   挂载卷的配置
secrets   安全
config
...     配置相关的!

# docker stack 一个完整的应用很多的服务的,就是一个 服务栈(网站!)deploy的配置只会在swarm架构中使用docker stack 部署才会生效
  • 例子1 网络

    version: "3.8"
    services:
      web:
        networks:
          hostnet: {}
    networks:
      hostnet:
        external: true
        name: host 
    
  • 例子2 挂载卷

    version: "3.8"
    services:
      web:
        image: nginx:alpine
        volumes:
          - type: volume
            source: mydata
            target: /data
            volume:
              nocopy: true
          - type: bind
            source: ./static
            target: /opt/app/static
      
      db:
        image: postgres:latest
        volumes:
          - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"  # 指定目录挂载
          - "dbdata:/var/lib/postgresql/data"  # 具名挂载
      
    volumes:
      mydata: {}  # 具名挂载,宿主机的目录在docker的默认目录/var/lib/docker/volumes
      dbdata: {}
    
  • 例子3 安全

    version: "3.8"
    services:
      redis:
        image: redis:latest
        deploy:
          replicas: 1
        secrets:
          - my_secret
          - my_other_secret
    secrets:
      my_secret:
        file: ./my_secret.txt
      my_other_secret:
        external: true
    

官方实战-部署wp博客

官方文档:https://docs.docker.com/compose/wordpress/

总共两步

# 1、第一步定义项目
# 创建项目目录
[root@alibaba www]# mkdir my_wordpress
[root@alibaba www]# cd my_wordpress/
# 定义docker-compose.yml
[root@alibaba my_wordpress]# vim dokcer-compose.yml
version: '3.8'
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql  # 数据的目录挂载
     restart: always  # 
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress   # mysql实例的root密码
       MYSQL_DATABASE: wordpress  # 创建一个wordpress数据库
       MYSQL_USER: wordpress			# 创建一个数据库用户/密码
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"		# 暴露端口,宿主机8080映射到容器内的80
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306    # 服务名:端口 mysql实例连接
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress		# 连接的用户/密码
       WORDPRESS_DB_NAME: wordpress  # 连接的数据库
volumes:
   db_data: {}  # 具名挂载,表示docker的默认目录/var/lib/docker,运行成功后发现volumes目录下有个mywordpress_db_data
# 先拉取镜像
[root@alibaba my_wordpress]# docker pull mysql:5.7
[root@alibaba my_wordpress]# docker pull wordpress:latest

# 2、第二步创建和运行项目
[root@alibaba my_wordpress]# docker-compose up -d

启动成功,可以访问wp博客了,浏览器 http://服务器ip:8000,进入界面选择语言,进行相关设置,登录博客

这是控制台

总结

1、Dockerfile

2、Docker-compose 单机玩玩而已!

3、Docker集群,Docker底层,网络原理,,,,,

以后你们下载的开源项目中,有 Docker-compose.yaml,只需要配置对应的环境即可一键启动!

2、Docker Swarm

企业中,docker绝对是使用集群上线的!

购买服务器

购买4台服务器,登录阿里云(阿里云余额>200)

1、创建实例

2、配置实例:按量付费+ 地域+共享型(至少1核2G)

3、购买数量4台,选择操作系统CentOS 7.8

4、创建网络和安全组,带宽计费按流量计费 ,安全组打开1/65535端口

5、 系统配置:root密码,实例名称

6、确认订单,创建即可

服务器启动完毕

7、可以互相访问,在一个网络中!使用Xshell连接或者SecureCRT连接4个服务器

把所有的服务器安装上docker!这里有个技巧,可以把命令同步发送到4个会话,同时安装docker!

准备工作结束。

Swarm架构

打开官方文档 https://docs.docker.com/engine/swarm/

重点swarm架构:3个管理者节点+7个工作者节点

Manager管理节点是互通的,Worker工作节点是隔离的,每个节点都是一个docker 引擎实例

1、Manager管理节点的作用:

  • 管理集群状态
  • 调度服务
  • 使用 raft 一致性协议:集群要在大多数节点可存活的情况下才可以运行,集群必须要大于3个主节点!

2、Worker工作节点的作用:

  • 执行容器
  • 默认的,所有的管理节点都是工作节点,至少一个管理节点

  • docker service create 创建服务,实现高可用

3、互换角色:运行 docker node promote ,把一个Worker转换为Manager,也可以吧Manager转换为Worker!

搭建一个集群

1、初始网络查看

2、Swarm 命令,核心:初始化+加入+离开+更新

docker swarm init --help

3、省流量,私网ip搭建集群!

# 初始化一个主节点,广播地址
# ip: 172.24.82.145
# 初始化
docker swarm init --advertise-addr 172.24.83.145
docker1 是一个管理节点,如何加入worker节点,manager节点看截图的命令

# 在主节点(Manager节点)上执行
# 创建一个worker token
docker swarm join-token worker   
# 创建一个manager token
docker swarm join-token manager  

可以颁发一个work token 让其他节点加入集群,也可以颁发,manager token 加入集群!

4、搭建一个worker节点

# 在 docker2 上执行join加入swarm 成为一个worker节点 
docker swarm join -token SMTKN-1xxxxx.......

5、在主节点docker1上查看集群节点信息,注意:从节点不能操作!主节点操作的!

# 在Manager节点上执行
docker node ls

6、当前状态。docker-1 manager,docker-2/3 worker、docker4- manager

# 在 docker3 上执行join加入swarm 成为一个worker节点 
docker swarm join -token SMTKN-1xxxxx.......
# 在 docker1上执行创建一个manager token
docker swarm join-token manager 

在 docker4 上执行返回的命令,加入swarm集群成为一个Manager节点

现在就是一个双主双从的swarm架构

7、集群是高可用的,哪挂一个节点还能不能正常使用?

# 在 docker1 上执行 停止docker
systemctl stop docker

注意:这里有一个细节, raft 一致性协议:集群要在大多数节点可存活的情况下才可以运行,集群必须要大于3个主节点!

# 在 docker4 上执行查看集群节点状态
docker node ls

# 发现报错了,集群不可用了,少于一半的管理者节点数

Raft 协议(核心)

目前我们是两个管理节点,如果一个节点挂了,另一个节点也不能使用!

Raft 协议来操作,保证绝对大数节点存活才可以使用,至少存活要大于1台才可以!

在项目中,Swarm 管理节点3个才可以保证高可用!至少3个管理节点,2 > 1.5 ( 3 / 2 = 1.5)

测试

1、docker3离开集群

# 在 docker3上执行 离开swarm 集群
docker swarm leave

2、docker3 以manger的角色重新加入,配置3个manager

# 在主节点docker1 上创建manager token 令牌
docker swarm join-token manager 
# 在docker3上执行返回的命令

3、现在挂掉一个管理节点,其他管理节点依旧可以使用,集群服务可正常使用

4、如果挂掉两个管理节点,只剩下一个管理节点,这个时候集群服务不可用!

Raft 协议:确保大多数节点存活才可用! > 1 , 集群最低要求,3个管理节点,基本的高可用!生产环境肯定不止3个管理节点

中小企业:原生的docker集群就足够了! k8s!

测试启动服务(重点)

从此告别 docker run, docker compose up,启动服务!

集群,就需要使用 docker service (使用docker管理服务), 容器(单个) ==> 服务(多个容器实例)

其实本质还是容器,只是在集群状态下,变为了服务!

单机下,compose ,也可以编排上线!单机!

1、创建一个服务!

# docker service  管理集群中的所有服务
# docker stack    一个完整的应用很多的服务的,就是一个 服务栈!(网站!)
[root@alibaba ~]# docker stack --help
Usage:  docker stack [OPTIONS] COMMAND
Commands:
  deploy      Deploy a new stack or update an existing stack
  ls          List stacks
  ps          List the tasks in the stack
  rm          Remove one or more stacks
  services    List the services in the stack

# 创建服务
docker service create -p 8888:80 --name my-nginx nginx

2、测试节点访问!我们在集群当前启动的服务,可以在任何一节点访问,配置上负载均衡!

现在docker1运行了一个nginx服务,集群内的节点都能正常访问到这个服务

3、只有一个容器在里面!那么我们要并发很大,怎么操作!

# 你知道你的公司的大概并发量,初始并发量
docker service create --replicas n
docker service create --name my-nginx -p 8888:80 --replicas 7 nginx

# 更新服务运行的时候动态扩容!一个服务多个实例,一个实例就是一个容器
docker service update --replicas n 服务名 
# 降为3个服务实例
docker service update --replicas 3 my-nginx
# 回滚到上次的服务实例个数
docker service rollback my-nginx 

4、使用docker 来部署应用集群,十分的方便!

# 查看服务在哪些节点上运行
docker service ps my-nginx

一个机器,可以运行多个容器,容器相互隔离!,可以看到nginx服务运行在不同的docker节点上,有节点运行多个容器构成一个服务7个容器实例

5、假设可以设置两个状态:高并发 和 正常流量,rollback 来回切换服务的容器实例个数

docker service rollback 服务名 

6、7个nginx容器的服务my-nginx的端口是怎么暴露的?

大家疑问:为什么一个容器可以被多台机器访问 Swarm 集群管理,对外暴露的是一个服务,负载均衡=> 服务!

为什么启动了多个容器还是可以访问,80端口对内(容器),对外只有服务的一个8888(在swarm集群上),访问的时候swarm负载均衡到具体的容器节点

==对外就是一个服务,但是一个服务可以部署在多个节点上,每一个节点又可以启动多个容器服务!容器在内部自身运行,相互隔离!==

灰度发布

上面使用docker service 解决了服务水平扩展的问题,下面来解决如何灰度发布服务的问题!

灰度发布:项目上线 => 替换之前的版本!==> 一点点更新!

docker service update --help
# 更新服务,更新版本
# --update-parallelism 最大并行更新服务数,0 就是所有一起更新
#  --update-delay duration    Delay between updates (ns|us|ms|s|m|h)
docker service update --image nginx:1.18.0-alpine --update-parallelism 1 --update-delay 10s my-nginx

按照自己配置的规则,一点点更新迭代项目上线,依旧保证服务的高可用!(更新的时候总有服务对外是可用的)

3、核心概念

1、swarm : 集群的管理和编排,docker自带的!docker在启动的时候可以初始化一个节点,或者加入一个节点!

docker swarm join-token worker
docker swarm join-token manager 

2、node:就是docker的一个实例,docker的节点!服务器的数量。节点是可以动态的扩缩容的,只需要加入即可。

  • 管理节点中的容器
    • Manager nodes : 调度任务,管理容器….. 在这里进行操作!每个节点可以跑多个容器
    • Worker nodes: 工作的具体容器执行,不对外! 无法操作的!每个节点可以跑多个容器
    • 可以角色互换

3、service:就是一个完整的服务,nginx 为例,一个服务下有多个运行的实例!这是一个核心!创建服务就需要在使用指定的容器镜像!

4、task:docker容器中执行的命令!

集群和单机其实十分相似!只是多了节点和管理的概念!

4、重新部署wp博客

跑一个项目,多个服务(docker-compose.yaml) 编排!

前面我们用docker-compose up 启动一个wp博客服务,下面我们使用docker swarm启动wp博客的服务集群

docker-compose.yml 文件不用修过

[root@alibaba my_wordpress]# vim dokcer-compose.yml
version: '3.8'
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql  # 数据的目录挂载
     restart: always  # 
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress   # mysql实例的root密码
       MYSQL_DATABASE: wordpress  # 创建一个wordpress数据库
       MYSQL_USER: wordpress			# 创建一个数据库用户/密码
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"		# 暴露端口,宿主机8080映射到容器内的80
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306    # 服务名:端口 mysql实例连接
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress		# 连接的用户/密码
       WORDPRESS_DB_NAME: wordpress  # 连接的数据库
volumes:
   db_data: {}  # 具名挂载,表示dock
# wp博客下线,之前挂在的数据不会被删除的
[root@alibaba my_wordpress]# docker-compose down
Removing my_wordpress_wordpress_1 ... done
Removing my_wordpress_db_1        ... done
Removing network my_wordpress_default

# 以服务的形式启动wp博客
[root@alibaba my_wordpress]# docker service create  -p 8080:80 --name wpblog wordpress

微服务->使用Dockerfile构建镜像->使用docker-composd.yml编排容器->通过docker swarm 上线集群

访问wp博客:http://47.113.95.179:8080

# 动态扩容wp博客的服务实例个数
docker service update --replicas 3 wpblog 

# 扩容后有个问题,mysql数据库变成了每个docker节点下都有一个,数据的一致性有问题,应该把数据库独立出来连接
# 修过dokcer-compose.yml
[root@alibaba my_wordpress]# vim dokcer-compose.yml 
version: '3.8'

 services:
   wordpress:
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: 172.18.196.184:3306
       WORDPRESS_DB_USER: jude
       WORDPRESS_DB_PASSWORD: jude#666
       WORDPRESS_DB_NAME: wordpress2
# 创建服务镜像       
[root@alibaba my_wordpress]# dcoker-compose create 
# 创建服务
[root@alibaba my_wordpress]# docker service create  -p 8000:80 --name wpblog wordpress
# 动态扩容服务实例
docker service update --replicas 3 wpblog

访问http://47.113.95.179:8080,进入界面选择语言,进行相关设置,登录博客

Post Directory