docker网络与服务编排与集群

一、私有仓库概述

1.概述

对于开源的镜像,如 redis,nginx 等,可以通过官方仓库 Docker Hub,或者国内的阿里云等共有仓库下载获取到镜像。但是企业内对于自己的研发产品不可能往公共仓库去发布镜像的,一般都会搭建私有的镜像仓库,保障内部研发的镜像对内可用,外部是无法获取的。

作用:

  • 安全
  • 内网可以访问

搭建方式:

  • 官方提供的 registry,不提供图形化界面
  • 开源的 Harbor,提供图形化界面

2、registry 本地镜像

1)概述

registry 用于保存 docker 镜像,包括镜像的层次结构和元数据。

启动容器时,docker daemon 会试图从本地获取相关的镜像;本地镜像不存在时,其将从 registry 中下载该镜像并保存到本地;拉取镜像时,如果不知道 registry 仓库地址,默认从 Docker Hub 搜索拉取镜像

2)registry环境搭建

第一步:下载registry容器镜像

bash 复制代码
docker pull registry
docker images

第二部:创建用于挂载至 registry 镜像启动的仓库中,便于容器镜像持久保存

bash 复制代码
mkdir /opt/registry

第三步:启动容器获取镜像仓库

bash 复制代码
docker run -d -p 5000:5000 --restart=always -v /opt/registry:/var/lib/registry registry

第四步:验证 - 查看镜像列表

bash 复制代码
curl http://192.168.22.137:5000/v2/_catalog

3)本地上传镜像

第一步:编辑配置文件 /etc/docker/daemon.json,并重启 docker 服务

bash 复制代码
vim /etc/docker/daemon.json

# 添加受信任的传输方式地址
"insecure-registries": ["http://192.168.217.155:5000"]

重启docker服务

bash 复制代码
systemctl daemon-reload
systemctl restart docker

第二步:给镜像打标签

bash 复制代码
docker tag centos:7 192.168.217.155:5000/centos:v1
docker images

第三步:上传打好标签的镜像

bash 复制代码
docker push 192.168.217.155:5000/centos:v1

这里打好标签直接上传,再次访问私有镜像仓库发现已经上传上去了

4)远程拉取镜像

第一步:修改/usr/lib/systemd/system/docker.service

bash 复制代码
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
>>>修改为
ExecStart=/usr/bin/dockerd

第二步:创建并编辑/etc/docker/daemon.json

bash 复制代码
"insecure-registries": ["http://192.168.22.137:5000"]

第三步:重启docker

bash 复制代码
systemctl daemon-reload
systemctl restart docker

第四步:下载镜像

bash 复制代码
docker pull 192.168.22.137:5000/centos:v1

5)registry 添加用户名密码

第一步:添加用户

bash 复制代码
# 安装所需工具包
yum install httpd-tools -y

# 创建用户账号密码
mkdir -p /opt/data/auth/
htpasswd -Bbn xiaobai 123456 >> /opt/data/auth/htpasswd

第二部:启动仓库

bash 复制代码
docker run --name registry -d -p 5000:5000 --restart=always \
-v /opt/data/auth/:/auth/ \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
-v /opt/registry:/var/lib/registry/ registry:latest

创建立好之后尝试上传镜像仓库

需要登录,登录上即可上传

bash 复制代码
# 登入镜像
docker login 192.168.22.137:5000

# 登出镜像
docker logout 192.168.22.137:5000

此时能够拉去和推入镜像

二、docker网络

1.概述

Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥 (docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container‑IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container‑IP 直接通信。

Docker 网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container‑IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run 创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过 [宿主机 IP]:[容器端口] 访问容器。

2.三种网络模式

通过以下命令可以查看docker的网络模式

bash 复制代码
docker network ls

1)bridge

bridge:所有容器连接到桥,就可以使用外网,使用 NAT 让容器可以访问外网,默认网络

bash 复制代码
# 创建一个容器,镜像包含yum源 
docker run -it --name=centos01 centos_yum /bin/bash

# 安装ip工具
yum install iproute -y
ip a s

2)host

所有的容器与 docker host 在同一网络中,可以让容器访问,甚至可以让外网主机访问容器中的服务,但是存在一个问题,如果主机中有多个容器,可能存在问题(端口冲突)

bash 复制代码
docker run -it --network=host --name=centos_test centos_yum /bin/bash
yum install iproute -y
ip a s

和主机相同

3)none

使用 none 网络,意味着没有网络,无法上网,外界也无法访问容器内部

bash 复制代码
docker run -it --network=none --name=centos03 centos:7 /bin/bash

3.实现主机跨容器之间的通信

1)Flannel概述

flannel 是一个专门用于跨主机网络通信的解决方案技术;

flannel 将 tcp 数据包封装在另一种网络数据包里进行路由转发,以及通信;

flannel 可以让不同的 docker 主机创建的容器,共同拥有一个集群中唯一的 ip 地址。

实现原理:

  • Flannel 为每个 host 分配一个 subnet,容器从 subnet 中分配 IP,这些 IP 可以在 host 间路由,容器间无需使用 nat 和端口映射即可实现跨主机通信。
  • 每个 subnet 都是从一个更大的 IP 池中划分的,flannel 会在每个主机上运行 flanneld 的 agent,负责从池子中分配 subnet。
  • Flannel 使用 etcd 存放网络配置、已分配的 subnet、host 的 IP 等信息
  • Flannel 数据包在主机间转发是由 backend 实现的,目前已经支持 UDP、VxLAN、host‑gw、AWS VPC 和 GCE 路由等多种 backend。

2)flannel部署

准备两台主机一台node1安装etcd flannel 另一台node2安装flannel

1.设置主机名

2.配置/etc/hosts

3.关闭防火墙

4.安装软件 etcd flannel

bash 复制代码
# 1.安装etcd flanned
yum -y install etcd flannel

# 2.配置 etcd
vim /etc/etcd/etcd.conf
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001"

# 3.开启 etcd 服务及验证
systemctl enable etcd && systemctl start etcd
netstat -tnlp
etcdctl set testdir/testkey0 1000
etcdctl get testdir/testkey0

# 4.配置 flannel
vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"

# 5.在 etcd 中添加网段
etcdctl mk /atomic.io/network/config '{"Network":"172.20.0.0/16"}'

# 6.启动flannel
systemctl enable flanneld && systemctl start flanneld

# 7.配置flannel 与 docker 结合 /run/flannel/subnet.env
cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.20.0.0/16
FLANNEL_SUBNET=172.20.61.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

# 8.配置 docker daemon(需要第7步的读取分配的ip一致)
vim /etc/docker/daemon.json
"bip": "172.20.61.1/24",
"mtu": 1472

# 9.重启 docker daemon
systemctl daemon-reload
systemctl restart docker

# 10.创建容器验证网络
docker run -it --name=centos04 centos:7 /bin/bash

node2与上述配置相同只是不同配置etcd,etcd只需要配置一台

此时配置好后查看两个不同主机下的docker的ip其中node1主机上的为172.20.61.3,node2主机上的为172.20.97.3

尝试ping不同主机的两台容器

ping不通,还有个防火墙没有关

需要将Chain FORWARD修改为ACCEPT

bash 复制代码
iptables -P FORWARD ACCEPT

此时都能互相ping通

三、服务编排

Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。它是一个定义和运行多容器的 docker 应用工具。使用 compose,你能通过 YMAL 文件配置你自己的服务,然后通过一个命令,你能使用配置文件创建和运行所有的服务。

Docker‑Compose 将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker‑Compose 运行目录下的所有文件(docker‑compose.yml,extends 文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例。

  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。每个服务都有自己的名字、使用的镜像、挂载的数据卷、所属的网络、依赖哪些其他服务等等,即以容器为粒度,用户需要 Compose 所完成的任务。
  • 项目(project):由一组关联的应用容器组成的一个完成业务单元,在 docker‑compose.yml 中定义。即是 Compose 的一个配置文件可以解析为一个项目,Compose 通过分析指定配置文件,得出配置文件所需完成的所有容器管理与部署操作。

Docker‑Compose 的工程配置文件默认为 docker‑compose.yml,可通过环境变量 COMPOSE_FILE 或‑f 参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。

2.安装与卸载

安装二进制文件,

bash 复制代码
# 强制下载,不走失效镜像,走国内加速
curl -L "https://ghproxy.net/https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋权
chmod +x /usr/local/bin/docker-compose

# 验证
docker-compose -v

3.常用命令

核心启动停止命令

bash 复制代码
# 1. 后台启动所有服务(最常用!)
docker-compose up -d

# 2. 前台启动(会打印日志,Ctrl+C 停止)
docker-compose up

# 3. 停止所有服务(不删除容器)
docker-compose stop

# 4. 启动已存在的服务
docker-compose start

# 5. 重启所有服务
docker-compose restart

# 6. 停止并删除所有容器、网络(保留镜像和数据卷)
docker-compose down

日志查看

bash 复制代码
# 1. 查看当前项目所有容器状态
docker-compose ps

# 2. 查看实时日志(最常用)
docker-compose logs -f

# 3. 查看某个服务的日志
docker-compose logs -f 服务名

# 4. 查看服务列表
docker-compose config --services

构建重建镜像

bash 复制代码
# 1. 构建/重新构建镜像(Dockerfile变更后用)
docker-compose build

# 2. 构建并启动(重新构建后直接后台运行)
docker-compose up -d --build

# 3. 只构建不启动
docker-compose build --no-cache

进入容器/执行命令

bash 复制代码
# 1. 进入指定服务的容器(最常用)
docker-compose exec 服务名 /bin/bash

# 示例:进入web服务容器
docker-compose exec web /bin/bash

# 2. 在容器中执行单行命令
docker-compose exec 服务名 命令

删除清理

bash 复制代码
# 1. 停止并删除容器、网络、镜像
docker-compose down --rmi all

# 2. 停止并删除容器、网络、数据卷
docker-compose down -v

# 3. 删除停止的容器
docker-compose rm
bash 复制代码
docker-compose up -d     # 后台启动
docker-compose stop      # 停止服务
docker-compose restart   # 重启服务
docker-compose logs -f   # 查看实时日志
docker-compose exec      # 服务名 /bin/bash 进入容器

4.案例应用

需求:编写compose模版文件,实现同时启动tomcat、mysql、redis容器

bash 复制代码
# 创建文件夹,递归创建
mkdir -p /usr/local/mycompose

# 进入文件夹
cd /usr/local/mycompose

# 创建docker-compose.yml文件
vim docker-compose.yml
bash 复制代码
version: '2'
services:
  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    container_name: "redis"
    networks:
      - dev
  mysql:
    image: mysql:5.6
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
    container_name: "mysql"
    networks:
      - pro
  tomcat:
    image: tomcat:8
    ports:
      - "8080:8080"
    volumes:
      - /usr/local/tomcat/webapps:/usr/local/tomcat/webapps
    container_name: "tomcat"
    networks:
      - pro
      - dev
networks:
  dev: 
    driver: bridge
  pro:
    driver: bridge
bash 复制代码
# 执行docker-compose文件,后台启动
docker-compose up -d

同样的可以同时停止这三个容器

bash 复制代码
docker-compose stop

删除所有镜像

bash 复制代码
docker-compose down

四、容器启动顺序

再启动容器的过程中,有些容器启动的依赖于其他容器,因此在启动过程中需要设置启动顺序以及依赖,因此添加以下操作

1. 使用 depends_on

depends_on 用于指定容器之间的依赖关系。当你在 docker‑compose.yml 文件中使用 depends_on 时,它会先启动依赖的容器,然后再启动当前容器。但是,需要注意的是,depends_on 并不保证容器启动就绪,它仅仅是告诉 Docker Compose 按照依赖关系顺序尝试启动容器。

bash 复制代码
version: '2'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      - db
      - redis
  db:
    image: mysql
  redis:
    image: redis

当我给tomcat设置连个依赖,mysql和redis,给redis设置mysql依赖之后启动

两次启动都是相同顺序,但是启动一个容器是需要时间的,按顺序启动不代表会按顺序成功启动,因此这里需要一个健康检测,当启动成功之后才会启动另一个

2.使用健康检查和等待脚本

一个更可靠的方法是使用容器的健康检查(health checks)和在应用启动脚本中添加等待逻辑。例如,你可以在应用启动脚本中添加逻辑来检查依赖服务是否可用。

bash 复制代码
version: '2'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
  db:
    image: mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10
  redis:
    image: redis
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

最终的脚本

bash 复制代码
version: '2'
services:
  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    container_name: "redis"
    depends_on:
      mysql:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3
    networks:
      - dev
  mysql:
    image: mysql:5.6
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
    container_name: "mysql"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10
    networks:
      - pro
  tomcat:
    image: tomcat:8
    ports:
      - "8080:8080"
    volumes:
      - /usr/local/tomcat/webapps:/usr/local/tomcat/webapps
    container_name: "tomcat"
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - pro
      - dev
networks:
  dev: 
    driver: bridge
  pro:
    driver: bridge

五、docker集群

1.概述

Docker Swarm 是 Docker 官方推出的容器集群管理工具,基于 Go 语言实现。使用它可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。

Docker Swarm 是生产环境中运行 Docker 应用程序最简单的方法。作为容器集群管理器,Swarm 最大的优势之一就是 100% 支持标准的 Docker API。各种基于标准 API 的工具比如 Compose、docker‑py、各种管理软件,甚至 Docker 本身等都可以很容易的与 Swarm 进行集成。大大方便了用户将原先基于单节点的系统移植到 Swarm 上,同时 Swarm 内置了对 Docker 网络插件的支持,用户可以很容易地部署跨主机的容器集群服务。

Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排工具,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。

2.需求概述

制作一个nginx镜像,需要将该nginx镜像运行指定数目到容器,而且容器是分散在不同的dcoker主机中的

3.环境概述

主机 / IP 作用 时间同步
node1/192.168.217.151 master (manager node) 主机
node2/192.168.217.153 worker
node3/192.168.217.156 worker

4.镜像准备

基于Dockerfile常见nginx镜像

bash 复制代码
mkdir /root/nginx
cd /root/nginx

创建nginx首页文件

bash 复制代码
echo "nginx is running!!! v1"  > index.html

编写Dcokerfile文件

bash 复制代码
vim Dockerfile
bash 复制代码
# 用于构建的centos_yum:v1镜像需要有yum源,和epel拓展源

FROM centos_yum:v1
RUN yum -y install nginx
ADD index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

创建v1镜像

bash 复制代码
docker build -t centos_nginx:v1 .

创建v2镜像,修改一下首页文件

bash 复制代码
echo "nginx is running!!! v2"  > index.html

docker build -t centos_nginx:v2 .

5.集群搭建

1)创建工作节点

将node1节点作为master节点

bash 复制代码
docker swarm init --listen-addr 192.168.22.151:2377

2)添加工作节点

将上面的红色的字体添加到工作节点,也就是另一台虚拟机

这个节点成功

一台主节点也就是master节点,一台工作节点

3)将镜像打包到node2节点

这里我们创建了的镜像放到私有仓库让另一台虚拟机拉取

bash 复制代码
# 将构筑的镜像 centos_nginx:v1 和 v2打上标签上传到私有仓库
docker tag centos_nginx:v1 192.168.22.151:5000/centos_nginx:v1
docker tag centos_nginx:v2 192.168.22.151:5000/centos_nginx:v2

# 上传到私有仓库
docker push 192.168.22.151:5000/centos_nginx:v1
docker push 192.168.22.151:5000/centos_nginx:v1

上传上去之后另一台虚拟机拉去上传的两个镜像

4)发布服务

bash 复制代码
docker service create --replocas 2 --publish 8080:80 -name nginxsvc 192.168.22.151:5000/centos_nginx:v1

此时两台主机都能访问到网页8080

5)常用指令

扩大或缩小

bash 复制代码
docker service scale nginxsvc=3
docker service scale nginxsvc=1

这里是位于主节点192.168.22.151

这里docker集群只要有一台nginx容器,存在就都能访问到什么原因,就是因为集群只要有一台nginx容器开启的状态就都访问的到,当请求到未开启nginx容器的服务器的时候会将请求转发到开启nginx容器的主机上,每个节点都是一个隐形的游览器

滚动更新

bash 复制代码
docker service update --image 192.168.22.151/centos-nginx:v2 nginxsvc

版本回退

bash 复制代码
docker service update --image 192.168.22.151/centos-nginx:v1 nginxsvc

和上述一致

删除服务

bash 复制代码
docker service rm nginxsvc
相关推荐
陳10301 小时前
Linux:进程间通信 和 简单进程池
linux·运维·服务器
数字化顾问2 小时前
(122页PPT)数字化架构的演进和治理(附下载方式)
java·运维·架构
zt1985q2 小时前
本地部署网页监控工具 Webmonitor 并实现外部访问
运维·服务器·网络·网络协议
匆匆那年9672 小时前
远程 Linux 校园网认证操作手册(本地浏览器法)
linux·运维·服务器
古城小栈3 小时前
K8s 之 ingress
云原生·容器·kubernetes
借你耳朵说爱你3 小时前
docker容器启动报错:library initialization failed - unable to allocate file descriptor table - out of memory
docker
万里侯3 小时前
微服务与人生:从服务网格看人际关系
微服务·容器·k8s
爱喝水的鱼丶4 小时前
SAP-ABAP:ABAP函数 NUMBER_GET_NEXT 详解:从编号范围对象获取下一个编号
运维·数据库·学习·sap·abap
Languorous.4 小时前
Windows 安装 Linux 虚拟机 / WSL 完整教程(新手零失败)
linux·运维·windows