Docker实战学习

企业实战

Docker-compose

Docker Compose来轻松高效的管理编排容器,定义运行多个容器

步骤:

  1. define your app's environment with a Dockerfile
  2. Define the services that make up your app in docker-compose.yml
  3. run docker-compose up 启动,run docker-compose down停止

安装compose

# 1. 
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 2. 
sudo chmod +x /usr/local/bin/docker-compose

# 3. 
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 4.
docker-compose --version

compose 命令

1. docker-compose 

-f --file docker-compose.yml   # FILE指定Compose模板文件,默认为docker-compose.yml

2. docker-compose up       # 启动所有服务
-d                         # 在后台运行服务器
-f docker-compose.yml      # 指定compose.yml文件

3. docker-compose ps       # 列出向项目中目前所有容器

4. docker-compose stop     # 停止正在运行的容器

5. docker-compose down     # 停止和删除容器,网络,

6. docker-compose logs     # 查看服务容器的输出默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过–no-color来关闭颜色

7. docker-compose build    # 构建(重新构建)项目中的服务容器

8. docker-compose restart  # 重启项目中的服务

9. docker-compose start    # 启动已经存在的服务容器

10. docker-compose version # 打印version版本 

实战练习(来自docker官网)

1.
 mkdir composetest
 cd composetest

2. app.py
"""
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)  # redis为域名,对应hosts

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)
"""


3. 编写docker-compose.yml
4. 启动docker-compose up
5. 启动后  默认服务名为  文件名_服务名_num
	例如:code_web_1  # code目录下的web服务,num副本数量
	  集群状态,副本数量不只有一个运行实例

默认规则

1. 网络规则
docke-compose 启动后,自动维护了一个网络 composetest_default (当前目录名称),服务间访问,不会使用ip,直接使用redis:6379

2.  如果在同一个网络下,可以直接使用域名访问
cache = redis.Redis(host='redis', port=6379)

yaml编写规则

# 只有三层

version: "3"  # 版本
services:   # 服务
	web:    # 服务1
		image: redis   # 镜像
		build: /root/my_app   # Dockerfile所在目录
		command: pipenv run python app.py   # 执行命令
		container_name: my_web    # 容器名
		depends_on:       # 启动顺序在redis和mysql之后
			- redis
			- mysql
		ports:            # 端口映射,暴露容器端口到主机的任意端口或指定端口(类似docker run -p)
			- "3000"
			- "8000:8000"
			- "127.0.0.1:8001:7801"
		expose:          # 端口映射,暴露容器端口到其他容器,不暴露给主机(类似docker run --link)
			- "6379"    
		volumes:          # 挂载一个存在的数据卷容器
			- /var/lib/mysql     # Docker 会自动在创建一个数据卷,匿名挂载
			- /opt/data:/var/lib/mysql    # 绝对路径挂载
			- datavolume:/var/lib/mysql   # 具名挂载
		volumes_from:            # 从另一个服务或容器挂载其数据卷
			- redis
		entrypoint: /entrypoint.sh
		environments:
			- "MYSQL_ROOT_PASSWORD=123"
		links:    # 不推荐吧,在web的/etc/hosts里配置db的ip,  例如: 192.168.10.1  db 
			- db
			- myserver:db  # 在容器web中,容器myserver的名字就是db, 可以连接数据库  http://db:6379
		
	redis:   # 服务2
	
	mysql:   # 服务3

volumes:   # 全局配置
networks:
configs:

实例:

version: "3.9"
services:
  web:
  	container_name: my_web
    build: .
    ports:  # 暴露端口
      - "5000:5000"
    depends_on:   # web依赖于db和redis, 启动顺序先启动db和redis最后启动web
      - db
      - redis
    command: pipenv run flask run
    environment:
      - a=b
    volumes:
      - ./data:/var/xxx
  redis:
    image: "redis:alpine"
    
  db:
    image: mysql

Docker-swarm

集群方式的部署,四台服务器,我自己用virtualbox + centos7 * 4

节点:

  • 管理节点(manager):操作都在manager节点上
  • 工作节点

搭建集群:

  1. docker swarm --help

  2. 私网和公网

  3. 对node1 机器执行 docker swarm init --advertise-addr 私网地址 --listen-addr 私网地址

    例如:

    $ docker swarm init --advertise-addr  # 初始化节点 添加--advertise-addr参数的原因是大多数情况下我们的主机都不只有一张网卡。而一个swarm集群需要辨明集群所在的子网络是哪张网卡的 --listen-addr指出的是这个集群暴露给外界调用的HTTPAPI的socket地址
    """
    To add a worker to this swarm, run the following command:
    
        docker swarm join --token SWMTKN-1-56f5ccl2kyls04d5uxx1wwva9rv9ijtt4zs8jwcvxroxstf0s6-d5k6pk82emis2rpla7qevqe60 192.168.0.115:2377         # 复制到其他机器执行,可以加入为worker节点
    
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
    """
    
    # 初始化节点
    docker swarm init 
    
    # 生成一个加入manager或worker的token
    docker swarm join-token manager
    docker swarm join-token worker
    """
    To add a worker to this swarm, run the following command:
        docker swarm join \
        --token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
        192.168.99.100:2377
    """
    
    # 查看节点(只有manger节点可以使用, 比如我现在四台虚拟机,则node ls为四个)
    docker node ls
    """
    ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
    ruyjls193xrvtdvt4h9b8020l *   master     Ready     Active         Leader           20.10.6
    mg6qegsok9i19spfo8el7ec9j     node2      Ready     Active                          20.10.6
    48fstkzfi627kze80eqd60tbc     node3      Ready     Active         Reachable        20.10.6
    aikez4xzcvy9602hjxhynxnaa     node4      Ready     Active                          20.10.6
    """
    
    # 然后node1和node3位manger, node2 和node4位worker
    # 在manager node 中创建服务,
    docker service create --replicas 1 --name helloworld alpine ping docker.com
    
    # 查看服务
    docker service ls 
    
    # 查看服务详细信息
    docker service inspect --pretty helloworld
    
    # 查看那些node正在运行这个service
    docker service ps helloworld
    
    # 对service扩缩容
    docker service scale 服务名(或id)=个数
    例如: docker service scale helloworld=3
    
    # 对删除service
    docker service rm helloworld   # docker ps 中对应的容器一会也会删除
    
    # 更新服务(例如redis:3.0.6,现在你想升级为redis3.0.7)
    docker service update --image redis:3.0.7 redis
    
    # 修改一个node的Availability可用性drain。DRAIN availability prevents a node from receiving new tasks from the swarm manager.  则这个node不会接收来自manager的tasks,manager会结束之前drain node的tasks,会重新在active的node上创建tasks
    docker node update --availability drain <NODE-ID>
    例如:docker node update --availability drain master 
    
    

遇到的问题

[root@localhost ~]# docker swarm join --token SWMTKN-1-0hv0so8y1bl4hp9ahzand12rp82c8afrea6m7n22ae9gktx8bf-2oh0ty4vecnfm3tbin515hz30 192.168.0.115:2377
"""
   Error response from daemon: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 192.168.0.115:2377: connect: no route to host"
"""

# manager机器的防火墙导致
systemctl status firewalld.service  # 查看防火墙状态
systemctl stop firewalld.service    # 停止防火墙
systemctl disable firewalld.service   # 永久停止

Raft协议

双主双从:假设一个节点挂了,其他节点是否可用?

实验:

  1. 将docker1的机器docker服务停止,宕机,双主,另外一个主节点也不能使用

    Docker实战学习

  2. 可以将其他节点离开,则显示Down的状态

  3. 当三个机器为管理节点时候,有一个宕机,其余两个仍然可用。如果有两个为管理节点,一个宕机,另一个不能用了。

总结:

  • 集群要保证可用,至少3个机器为管理节点

实战: 动态扩缩容

# 1. 创建服务
docker service create -p 8888:80 --name my_nginx nginx

# 2. 调整为3个副本,动态扩缩容
docker service update --replicas 3 my_nginx 
docker service scale my_nginx=3    # 法二

# 3. 访问服务
curl 192.168.0.116:8888

概念总结

swarm: 集群的管理和编号,docker可以初始化一个swarm集群,其他节点可以加入(管理者,工人)。

**Node: ** 对应的docker节点,多个节点组成一个网络集群(管理,工作者)

Service: 任务,可以在管理节点或者工作节点来运行,核心。

**Task: ** 容器内的命令,细节任务

其他命令:

--mode string   # 创建的服务,以什么模式运行 Service mode (replicated, global, replicated-job, or global-job)

docker service create --mode replicated --name my_nginx nginx
docker service create --mode gobal --name my_nginx nginx  # 每个node都有nginx

网络

overlay
ingress

CI/CD之jenkins

上一篇:容器云技术选择之kubernetes和swarm对比


下一篇:IPFS系列 多节点搭建 二