一、私有仓库概述
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
