1. Docker 简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Dcoker 是基于 Go 语言开发的,是一个开源项目。
官网:www.docker.com/
仓库:hub.docker.com/,相当于 GitHub ,可以发布镜像
1.1 Docker 为什么会出现?
当开发一款产品的时候,需要有开发和上线两套环境,不同环境需要使用不同的配置。
公司中会有两个角色:开发和运维。
问题:当我开发人员开发好一款产品之后再自己的电脑上可以运行,如果版本更新的话会导致服务器不可用的,对于运维人员来说是非常麻烦的。
环境配置非常的麻烦,每一个机器都要部署环境(集群 Redis 、ES、Hadoop)等等非常的费时费力。
发布一个项目的时候是以 jar 的方式,但是需要依赖一些环境(Rdis、MySQL、JDK 等),项目不能都带上环境安装打包。
假设之前在服务器配置一个应用的环境 Redis、MySQL、JDK,配置非常的麻烦,不能够实现跨平台,开发系统 Windows ,发布到 Linux
传统的开发中:开发人员打 jar 包,运维人员来进行部署上线
现在:开发打包部署上线,一套流程做完。
假设开发一个 apk 应用
- java -- apk -- 发布(应用商店)-- 用户使用 apk -- 安装使用就可以
- java -- jar(环境)-- 打包项目带上环境(镜像)-- (Docker仓库)-- 下载发布的镜像 -- 直接运行就可以。
Docker 对于上面的问题提出解决方案。
Docker 的思想就来自于集装箱。
JRE -- 多个应用(端口冲突)-- 原来都是交叉的。
隔离:Docker 核心思想,打包装箱,每个箱子都是互相隔离的,Docker 通过隔离机制,可以将服务器利用到机制。
1.2 Docker 的历史
2010 年,几个做 IT 的年轻人,在美国成立了一家公司“dotCloud”
这个公司开始是做一些 pass 的云计算服务的,LXC 有关的容器技术,它们将自己的技术(容器化技术)命名就是 Docker,Docker 刚刚诞生的时候,没有引起行业的注意,公司坚持不下去。
所以就选择了开源,2013 年 Docker 开源,开源之后越来越多的人发现了 Docker 的优点,火了之后 Docker 每一个月都会更新一个版本。2014 年 4 月 9 日,Docker1.0 发布。
在容器技术出现之前,我们都是使用的虚拟机技术。
虚拟机:在 windows 中装一个 vmware,通过这个软件我们可以虚拟出来一台或者多台电脑,非常的笨重。
虚拟机也是属于虚拟化技术;Docker 容器技术,也是一种虚拟化技术。
1.3 Docker 能干什么
虚拟机技术
一个电脑,电脑中有一个内核,一个运行需要的库,然后所有开发的软件运行在这个电脑上。
虚拟机技术缺点:
容器化技术
容器化技术不是模拟的一个完整的操作系统。
- 比较不同
虚拟机是虚拟出一套硬件,运行一个完整的操作系统,在这个系统上安装和运行软件。
容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟硬件,所以非常的轻便,每个容器之间是相互隔离,每个容器内都有一个属于自己的文件系统,互不影响。
2. Docker 安装
2.1 Docker 的基本组成
- 镜像(image):
镜像就好比一个模板,可以通过这个模板来创建容器服务,假设有一个 tomcat 镜像,通过 run 方法运行,tomcat01 容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
- 容器(container):
利用容器技术做到独立运行一个或者一组应用,通过镜像来创建,可以假设容器就是一个简易的 Linux 系统
- 仓库(repository)
用来存放镜像的地方,仓库分为公有仓库和私有仓库
Docker Hub 默认的国外的,阿里云、腾讯云等都有容器服务器
2.2 安装 Dcoker
- 环境准备
一台 Linux 系统的服务器,CentOS 7
安装
参考地址:docs.docker.com/engine/inst…
sudo yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
sudo yum install -y yum-utils
# 国外的,非常慢
sudo yum-config-manager
--add-repo
https://download.docker.com/linux/centos/docker-ce.repo
# 阿里云镜像安装地址
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新 yum 软件包索引
yum makecache fast
sudo yum install docker-ce docker-ce-cli containerd.io
yum install docker-ce-18.06.1.ce-3.el7 docker-ce-selinux-18.06.1.ce-3.el7
sudo yum install docker-ce-18.06.1.ce-3.el7 docker-ce-cli-18.06.1.ce-3.el7 containerd.io
systemctl start docker
docker version
查看是否安装成功docker run hello-world
docker images
# 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 删除运行环境
rm -rf /var/lib/docker
/var/lib/docker //docker 的默认工作路径
2.3 Dcoker Run 的运行流程
Docker 是怎么工作的?
Docker 是一个 Client-Server 结构的系统,Docker 是守护进程运行在主机上,通过 Socket 从客户端访问,Docker Server 接收到 Docker-Client 的指令,就会执行这个命令。
Dcoker 为什么比 VM 快?
新建一个容器的时候,docker 不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载 GuestOS,是分钟级别的;docker 是利用宿主机的操作系统,省略了复杂的引导过程,是秒级的。
3. Docker 常用命令
3.1 帮助命令
docker version #显示 docker 的版本信息
docker info #显示 docker 的系统信息,包括镜像和容器数量
docker 命令 --help #帮助信息
帮助文档地址:docs.docker.com/reference/
3.2 镜像命令
-
docker images
查看所有本地的主机上的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 4 weeks ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的 id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 命令可选项
-a, --all 列出所有镜像
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
-q, --quiet 只显示镜像 id
-
docker search
搜索镜像
docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11587 [OK]
mariadb MariaDB Server is a high performing open sou… 4407 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 857 [OK]
# 可选项 ,过滤
--filter=STARS=3000 搜索出来的镜像就是 STARS 大于 3000 的
-
docker pull
下载镜像
docker pull mysql [:tags] # 下载最新的 [:tags]指定下载
Using default tag: latest # 如果不写 tag,默认就是 latest 最新版
latest: Pulling from library/mysql
b380bbd43752: Pull complete # 分层下载,docker image 的核心,联合文件系统,这回下了这几个层,如果下面指定别的版本进行下载,如果有重复就不会下载
f23cbf2ecc5d: Pull complete
30cfc6c29c0a: Pull complete
b38609286cbe: Pull complete
8211d9e66cd6: Pull complete
2313f9eeca4a: Pull complete
7eb487d00da0: Pull complete
4d7421c8152e: Pull complete
77f3d8811a28: Pull complete
cce755338cba: Pull complete
69b753046b9f: Pull complete
b2e64b0ab53c: Pull complete
Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87 # 签名
Status: Downloaded newer image for mysql:latest
-
docker rmi
删除镜像,可以通过镜像 id 删除或者镜像名
docker rmi -f IMAGE ID # 删除指定的容器,也可以通过空格间隔删除多个
docker rmi -f $(docker images -aq) # 删除全部的容器
3.3 容器命令
注意:我们有了镜像才可以创建容器
测试使用,下载一个 CentOS 镜像
docker pull docker # 最新版的
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" 容器启动后的名字,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080
-p # ip:主机端口:容器端口
-p # 主机端口:映射到容器端口(常用)
-p # 容器端口
-P 随机指定端口
# 使用容器
# 启动并进入容器
docker run -it centos /bin/bash
# 从容器中退回到主机
exit 容器停止并退出
Ctrl + P + Q 容器不停止退出
# 列出所有运行中的容器
docker ps 列出正在运行的容器
docker ps -a 列出当前正在运行的容器 + 历史运行过的容器
-n=? 显示最近创建的容器
-q 只显示容器的编号
删除容器
docker rm 容器id # 删除指定id 的容器
docker rm -f $(docker ps -aq) # 删除所有的容器
启动和停止容器
docker start 容器id
docker restart 容 器id
docker stop 容器id
docker kill 容器id
3.4 其他常用命令
问题:当我们使用后台启动容器 centos 的时候docker run -d 镜像名
,使用 docker ps 发现 centos 停止了。这里是常见的一个问题,容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用就会自动停止;假设 nginx 容器启动后,发现自己没有提供服务,就会立刻停止,就没有程序了。
-
docker logs
查看日志命令
docker logs -f -t --tail 5 容器 查看某一个容器的日志信息
-
docker top
查看容器中的进程信息
docker top 容器id
-
docker inspect
查看镜像的元数据
docker inspect
-
docker exec -it 容器id bashShell
进入容器后开启一个新的终端,可以在里面操作(常用)
进入当前正在运行的容器
我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
docker attach 容器id 进入容器正在执行的终端,不会启动新的进程。
-
docker cp
从容器中拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
3.5 总结
attach # 当前 shell 下 attache 连接指定运行镜像
build # 通过 Dockerfile 定制镜像
commit # 提交当前容器为新的镜像
cp # 从容器中拷贝指定文件或者目录到宿主机上
create # 创建一个新的容器,同run,但不启动容器
diff #查看docker 容器变化
events # 从 docker 服务获取容器实时时间
exec # 在已存在的容器上运行命令
export # 导出容器的内容流作为一个 tar 归档文件[对应 import]
history # 展示一个镜像形成历史
images # 列出系统当前镜像
import # 从tar 包中的内容创建一个新的文件系统镜像[对应export]
info # 显示系统相关信息
inspect # 查看容器详细信息
kill # kill 指定 docker 容器
load # 从一个 tar 包中加载一个镜像[对应save]
login # 注册或者登录一个docker 源服务器
logout # 从当前Docker registry 退出
logs # 输出当前容器日志信息
port # 查看映射端口对应的容器内部源端口
pause # 暂定容器
ps # 列出容器列表
pull # 从docker 镜像源服务器拉取指定镜像或者库镜像
push # 推送指定镜像或者库镜像至docker 源服务器
restart # 重启运行的容器
rm # 移除一个或者多个容器
rmi # 移除一个或者多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可以继续 或 -f 强制删除]
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个tar包[对应 load]
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看docker 版本号
wait # 截取容器停止时间的退出状态值
4. Docker 安装使用
4.1 Docker 安装 Nginx
docker search
也可以在 docker.hub 上搜索,可以看到帮助文档
docker pull nginx
docker run -d --name nginx01 -p 3344:80 nginx
-d # 后台运行
-name # 容器名
-p # 宿主机端口:容器内部端口
- 端口暴露的概念
4.2 Docker 安装 Tomcat
docker search tomcat
docker pull tomcat
docker run -d --name tomcat01 -p 8080:8080 tomcat
外网访问测试
通过外网我们访问可以看到,结果是 404,因为 docker 下载下来的这个 tomcat 不是一个完整版的
我们使用命令进入容器查看
docker exec -it tomcat01 /bin/bash
whereis tomcat
进入到 tomcat 的目录下,我们看到 webapps 目录下是空的,因为部署的项目是在这个目录下的,而看到这个文件夹是空的,所以表示并没有进行任何的项目部署,所以会出现 404 页面的情况,这个原因是阿里云镜像的原因,在下载的时候默认是找的最小的镜像,所以它会把不必要的都剔除掉,保证最小可运行的环境。我们在 webapps 的同级目录下可以 看到一个 webapps.dist 目录,将这个目录的内容全部复制到 webapps 里面,然后重新访问就可以看到 tomcat 的首页内容了。
5. 可视化面板 portainer
Docker 图形化界面管理工具,提供一个后台面板供我们操作。
开启命令
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
下载完成之后我们可以通过浏览器访问 ip地址:8088 端口号
6. 镜像
镜像是什么:镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
所有的应用直接打包成 docker 镜像就可以直接运行。
获得镜像的方式:1. 从远程下载 2. 别人拷贝 3. 自己制作一个镜像DockerFile
6.1 UnionFS(联合文件系统)
在我们下载镜像的时候可以看到一层层的下载
UnionFS:Union 文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union 文件系统是 Dcoker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
6.2 Docker 镜像加载原理
docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system) 主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等
平时我们安装的虚拟机 CentOS 都是好几个 G,为什么 Docker 只有几百M?
对于一个精简的 OS,rootfs 可能很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就可以了。由此可见对于不同的 Linux 发行版,bootfs 基本是一致的,rootfs 会有差别,因此不同的发行版可以公用 bootfs。虚拟机是分钟级别的,容器是秒级。
6.3 镜像分层
在我们下载一个镜像的时候,终端输出的日志中可以明显的看到是一层一层的进行下载。
为什么 Docker 镜像要采用这种分层的结构呢?
最大的好处,就是可以实现资源的共享,比如有多个镜像都从相同的 Base 镜像构建过来,那么宿主机只需要在磁盘上保留一份 base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过命令:docker image inspect 镜像
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
假设基于 Unbuntu Linux 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python 包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
下图中镜像包含 3 个镜像层
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,下图中,每个镜像包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件
下图中是一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,因为最上层的文件 7 是文件 5 的更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件,这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。每种存储引擎都是基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW。
下图中是系统显示相同的三层镜像,所有镜像层堆叠并合并,对外提供统一的视图。
特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层。
6.4 Commit 镜像
docker commit 提交容器成为一个新的副本
docker commit -m="信息描述" -a="作者" 容器id 目标镜像名:[TAG]
在我们平常是使用中,下载一个镜像使用时需要对其进行一些修改,扩充,如果我们想要保存当前容器的状态,可以通过 commit 来提交,获得一个镜像,就好比 VM 虚拟机的快照功能。
docker commit -m="add webapps" -a="lss" xxxxxx tomcat001:1.0
7. 容器数据卷
7.1 什么是容器数据卷
总的来说:容器的持久化和同步操作;容器间也是可以容器共享的
docker 的理念就是将应用和环境打包成一个镜像,如果数据存储在容器中,那当我们的容器被删除了,数据也会丢失。我们需要对数据进行持久化,加入 MySQL 的容器中存储了数据,容器突然被误删除了,那数据就会丢失了,所以我们需要将数据存储在本地。
容器之间可以有多个数据共享的技术,Docker 容器中产生的数据同步到本地,这就是卷技术,目录的挂载,将我们容器内的目录挂载到 Linux 上。
7.2 通过命令挂载
docker run -it -v 主机目录:容器内目录
# 测试
docker run -it -v /home/test:/home centos /bin/bash
执行命令之后,无论是在镜像里面修改指定的目录还是在宿主机上修改指定的目录,另一方都能收到相应的变化信息,这种情况就是挂载成功了。
启动之后我们可以通过 docker inspect 容器id 来查看
这里当我们停止运行容器之后,修改宿主机共享的文件的内容的,再次启动容器会发现数据也进行了相应的更新。双向的过程。
使用容器卷好处:绑定之后,我们修改本地的文件,在容器中也会进行同步修改。
7.3 安装 MySQL
docker search mysql
docker pull mysql:5.7
启动容器
这里应该注意,进入 mysql 需要有一个密码的配置
详细信息官网地址:registry.hub.docker.com/_/mysql
-d # 后台运行
-p # 端口映射 宿主机端口:容器端口
-v # 卷挂载
-e # 环境变量
--name # 容器名字
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
使用 SQL_yog 连接MySQL
创建一个 test 数据库
/home/mysql/data
目录下的内容7.4 具名挂载和匿名挂载
7.4.1 匿名挂载
-v 容器内路径
docker run -d -p 80:80 -v /etc/nginx nginx
查看所有的 volume 情况
docker volume ls
这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径 ,没有写容器外的路径
7.4.2 具名挂载
-v 卷名:容器内路径
docker run -d -p 80:80 -v nginx01:/var/nginx nginx
7.4.3 卷挂载路径查看
所有的 docker 容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
,我们通过具名挂载可以方便的找到我们的一个卷,大多数情况使用 具名挂载
7.4.4 确定挂载方式
如何确定是具名挂载、匿名挂载、还是指定路径挂载?
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
- 读写权限
docker run -d -p 80:80 -v nginx01:/var/nginx:ro nginx
docker run -d -p 80:80 -v nginx01:/var/nginx:rw nginx
#通过 -v 容器内路径:ro rw 改变读写操作
ro readonly #只读 说明这个路径只能通过宿主机来操作,容器内部是无法操作的
rw readwrite #可读可写
#设置了这两个容器的权限,容器对我们挂载出来的内容就有限定了。
7.5 简单使用 DockerFile
DockerFile 就是用来构建 docker 镜像的构建文件,就是一个命令脚本
在 /home/docker-test-volume 目录下创建一个 dockerfile01 脚本文件,这个脚本可以生成镜像,里面的每一个命令都是一层
# 文件中的内容 这里面的每一个命令就是镜像的一层
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash
使用命令构建镜像
在 dockerfile01文件同级目录下
docker build -f dockerfile1 -t lss/centos .
使用命令 docker images
查看我们刚才构建的镜像
启动一下自己写的容器
docker run -it a542aa955836 /bin/bash
在容器中的 volume01 下创建一个 container.txt
文件
这个卷和外部一定有一个同步的目录,这里的是匿名挂载
使用命令 docker inspect 5c26b2ee40af
查看详细的信息
7.6 数据卷容器
多个容器实现数据的同步
测试
docker run -it --name centos01 lss/centos
在启动一个 lss/centos 镜像
通过 --volumes-from 挂载到上一个启动的容器上实现数据的同步
--volumes-from # 相当于一个继承的关系
docker run -it --name centos02 --volumes-from centos01 lss/centos
在 centos01 的 volume01 文件夹下创建一个 test.java 文件
进入 centos02 后在 volume02 文件夹下也可以看到这个文件,实现了容器之间的数据同步。
因为这个镜像是自己创建的,在上面的 DockerFile 里面进行了设置,只设置了 volume01 和 volume02 文件夹是共享的卷,所以在别的文件夹中的内容是不能实现共享的。
加入一个 centos03 也挂载到 centos01上,然后删除掉 centos01 之后,这些共享的文件在 centos02 和 centos03 上并不会丢失的,这个文件都是双向拷贝存在的。
结论
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是一旦将数据同步到本地,本地的数据是不会删除的。
8. DockerFile
Dockerfile 就是用来构建 docker 镜像的文件,通过它来生成一个镜像文件发布出去,可以理解为一个命令参数脚本。
8.1 DockerFile 介绍
查看官网:registry.hub.docker.com/
这个文件里面就是一些构建的命令
很多官网镜像都是基础包,很多功能是没有的,我们通常会自己搭建自己的镜像。
8.2 DockerFile 构建和指令
构建时需要很多的指令
8.2.1 基础
- 每个关键字(指令)都是必须是大写字母
- 执行从上到下顺序执行
- ( # ) 表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
DockerFile 是面向开发的,以后要想发布项目,做镜像,就要编写 DockerFile 文件。
步骤:开发、部署、运维
DockerFile :构建文件,定义了一切的步骤,源代码
DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行
Docker容器:容器就是镜像运行起来提供服务
8.2.2 DockerFile 指令
FROM # 基础镜像,一切从这里开始
MAINTAINER # 镜像是谁写的 姓名 + 邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat 镜像,这个tomcat 压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候需要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似 ADD ,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
8.3 DockerFile 构建镜像
Docker Hub 中 99% 镜像都是从这个基础镜像过来的: FROM scratch,然后配置需要的软件和配置来进行构建。
FROM centos
MAINTAINER lss
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
docker build -f 文件名 -t 镜像名:[tag] .
docker build -f mydockerfile-centos -t centos:1.0 . # 注意后面这个 . 不能少
docker run -it mycentos:1.0 # 进入我们自己创构建的镜像
这里我们在 DockerFile 文件中有安装 net-tools 和 vim 的命令,所以在镜像中可以只用;官网的下载的原生的是不能使用的。
8.4 CMD 和 ENTRYPOINT 区别
- CMD:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
- ENTRYPOINT:指定这个容器启动的时候要运行的命令,可以追加命令
测试 CMD
FROM centos
CMD ["ls","-a"]
docker build -f dockerfile-cmd-test -t cmdtest .
docker run 037860b45b64
,在 run 的时候 ls -a
命令生效docker run 037860b45b64 -l
会出错因为 cmd 的情况下,-l 替换了 CMD ["ls","-a"] 命令,-l 不是命令所以报错
这里可以使用 docker run 037860b45b64 ls -l
查看
测试 ENTRYPOINT
FROM centos
# 与 CMD 区别之处
ENTRYPOINT ["ls","-a"]
docker build -f dockerfile-entrypoint-test -t entrytest .
docker run 368a821b1dcb
在执行的时候追加一个参数 docker run 368a821b1dcb -l
这里还是可以正常执行的,这里是直接拼接在 ENTRYPOINT 后面的
8.5 构建一个 tomcat 镜像
Dockerfile
,这样 build 的时候就会自动寻找这个文件,不需要使用 -f 指定了 FROM centos
MAINTAINER lss
COPY README.txt /readme.txt
ADD jdk-8u311-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.54.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.54
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.54/bin/logs/catalina.out
docker build -t dirtomcat . # 由于文件名是 Dockerfile ,所以不需要用 -f 参数去找文件
docker images
docker run -d -p 8080:8080 --name lss-tomcat -v /opt/build/tomcat/webapps:/usr/local/apache-tomcat-9.0.54/webapps/test -v /opt/build/tomcat/tomcat-logs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat
本地编写一个项目进行发布
上面启动镜像的时候就已经做了卷的挂载,所以我们直接在本地编写项目就可以实现同步发布了
在 /opt/build/tomcat/webapps/
文件夹(上面 -v 挂载的)下创建一个 WEB-INF 文件夹,在这个文件夹下创建一个 web.xml 文件
在 tomcat 目录下创建一个 index.jsp 文件
Hello Tomcat Docker!
至此已经实现了项目的发布
查看日志文件输出信息
9. 发布镜像
9.1 发布到 DockerHub
到 docker.hub 中注册一个账号登录进去
在服务器上提交镜像
登录
docker login -u lishisen -p ******
# 由于之间创建的镜像没有带版本号,所以提交的时候被拒绝了
# 增加一个 tag
docker tag 容器id lishisen/tomcat:1.0
# 然后提交就成功了
docker push lishisen/tomcat:1.0
可以看到,提交的时候也是按照镜像的层级来进行提交的。
9.2 发布到阿里云
创建一个命名空间
这个命名空间可能就是一个很大的项目
- 操作指南里面有详细的操作步骤
根据操作指南操作
docker login --username=李时森111 registry.cn-beijing.aliyuncs.com
docker tag [ImageId] registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/lishisen/lishisen-repo:[镜像版本号]
10. Docker 网络
10.1 Docker0
问题:docker 是如何处理容器网络访问的?
有一个 tomcat 容器,一个 mysql 容器,那这两个容器之间是怎样通信的,是使用那个网络进行通信的?
查看能够 ping 同容器内的 ip 地址
docker run -d -P --name tomcat01 tomcat
查看容器内部 ip 地址
在运行容器的时候加上 ip addr 命令
docker exec -it tomcat01 ip addr
# 注意这里下载的镜像如果这个命令不能用可能是镜像中没有这一个功能,可以上面安装过 net-tools 的 Dcokerfile 文件来自己重新构建一个镜像文件
启动后我们可以看到容器内部网络地址 ,容器启动的时候会得到一个 eth0@if33 的ip 地址,这是 docker 分配的。
我们使用 ping 命令是可以 ping 通这个 ip 地址的
原理
当我们每启动一个 docker 容器的时候,docker 就会给 docker 容器分配一个 ip 地址;在宿主机上,只要我们安装了 docker ,就会有一个 docker0 的网卡,是使用的桥接模式,使用 veth-pair 技术。
当我们上面的容器启动之后,在宿主机上使用 ip addr 查看,可以看到有刚才启动的容器的 ip 的相关信息。
我们每启动一个容器就会多一个网卡,这个启动的容器带来的网卡都是一对一对出现,这就是 veth-pair 技术:就是一对虚拟设备接口,它们都是成对出现的,彼此相连的。
也就是因为有了这个特性,veth-pair 充当作为一个桥梁,连接这各种的虚拟网络设备,实现宿主机和容器之间的互联。
加入我们开启了两个容器 tomcat01、tomcat02 ,这两个容器之间也是可以通过ping 命令测试连通的,所以说容器之间也是可以相互通信的。
两个容器之间的通信并不是直接通信的,当安装 Docker 后会有一个 docker0 的网卡,这个就相当于是一个路由器,当 tomcat01 与 tomcat02 建立连接时,以 veth-pair 技术实现两个网卡之间的互联,然后路由器通过广播的方式或注册IP地址的方式进行发送连接。
tomcat01 和 tomcat02 是共用一个路由器 docker0。
所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用的 ip
Docker 使用的 Linux 的桥接,宿主机是一个 Docker 容器的网桥 docker0
Docker 中的所有网络接口都是虚拟的,因为 虚拟的接口转发效率高。
只要删除容器,对应的一对网桥就没了
10.2 link
场景:有一个微服务,database url = ip:,每一次用 docker 启动 MySQL 都会分配一个新的 ip ,如果 ip 变化了项目中的地址就会失效了,我们在项目不重启的情况下,数据库的 ip 地址换掉了,希望可以通过名字来访问这个容器,以此来解决这个问题。Docker 中使用 --link 来解决这个问题
分别查看两个 tomcat 的网卡 ip 地址
ping 相互的 ip 地址是可以通的
但是 ping 容器的名字是不能 ping 通的
使用 --link 进行连接
再启动一个 tomcat03 容器,使用 --link 连接
docker run -d -p 8083:8080 --name tomcat03 --link tomcat01 tomcat
测试是否能通过容器名 ping 通
启动 tomcat03 可以 ping 通 tomcat01 通过容器名
注意: 相反 tomcat01 ping tomcat03 就会失败,正向连接可以,反向连接可能不可以
docker network ls
docker inspect 上一条命令出来的id
可以看到为每一个启动的容器分配一个 ip
tomcat03 在本地配置了 tomcat02 的配置
通过查看 tomcat03 容器的 hosts 文件可以看到
docker exec -it tomcat03 vim /etc/hosts
# 可以看到 tomcat03 的 hosts 中有 ip 地址和容器名的映射关系
但是相反的是,在 tomcat01 的 hosts 文件中不能看到映射关系,所以 tomcat01 不能通过容器名 ping 通 tomcat03
--link
的操作其实就是在 hosts 配置配置了一个 ip 地址和 容器名 的映射关系,这种方式已经不再使用了。
docker0 问题:不支持容器名进行连接访问
10.3 自定义网络
通过命令 docker network ls
查看所有的 docker 网络
网络模式:
- bridge:桥接模式(默认)
- none:不配置网络
- host:主机模式,和服务器共享网络
- container:容器内网络连通(局限性大)
构建自定义网络
# 直接启动的命令,默认是有一个 --net bridge,这个就是 docker0
docker run -d -P --name tomcat01 [--net bridge] tomcat
# docker0 特点:默认的,域名不能访问,使用 --link 可以实现互联
# --driver bridge 网络模式,桥接,默认也是 bridge
# --subnet 192.168.0.0/16 子网,可以包含 255*255 个子网
# --gateway 192.168.0.1 网关
# mynet 自定义网络的名字
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
自己的网络就创建好了
docker run -d -p 8081:8080 --name tomcat01 --net mynet tomcat
docker run -d -p 8082:8080 --name tomcat02 --net mynet tomcat
## 使用 docker inspect mynet 查看详细信息
测试是否能 ping 通
经过测试,通过 ip 地址和通过 容器名 都可以 ping 通
现在不适用 --link 也可以 ping 通了
我们自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐使用自定义的网络
好处:
redis:不同的集群使用不同的网络,保证集群是安全和健康的
mysql:不同的集群使用不同的网络,保证集群是安全和健康的
10.4 网络连通
在上面创建了一个自定义的网络,网段是 192.168.0.0,docker0 自带的网段上 172.18.0.0
两个网段的是不能连通的
在 docker0 上有两个 tomcat 容器,mynet 上有两个 tomcat 容器,这两个网段的容器也是不能 ping 通的,所以需要 docker0 上的容器连接到 mynet 上,实现两个不同网段的容器互联。
测试
tomcat01 容器连通 mynet 网络
docker network connect mynet tomcat01
docker inspect mynet # 查看详细信息
# 下图我们可以发现,连通之后直接把 tomcat01 放到了 mynet 下
# 官网:一个容器两个ip地址
docker exec -it tomcat01 ping tomcat-net-01
如果要跨网络操作别人,就需要使用 docker network connect 连通
11. 部署 Redis 集群
docker network create redis --subnet 172.38.0.0/16
for port in $(seq 1 6);
do
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
for port in $(seq 1 6);
do
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
done
docker exec -it redis-1 /bin/sh # 进到 redis-1 节点里面
# 执行命令创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
set a b
在集群中 set 一个值,显示的主机的 172.38.0.13 这个主机,然后使用命令 docker stop redis-3
停掉这个容器之后,在进入集群到 172.38.0.14 这个节点上,14 是 13 的从机,主机挂掉从机补上
docker 搭建 redis 集群完成。
12. Spring Boot 微服务打包 Docker 镜像
创建 Spring Boot 项目
Controller 请求返回 Hello,Docker
打包应用
把这个项目 package 打包成一个 jar 包,将这个 jar 包上传到 Linux 虚拟机上
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
docker build -t demo .
13. Docker Compose
13.1 介绍
官网:docs.docker.com/compose/
在上面的操作中,我们想要构建使用一个镜像的话需要进行:Dockerfile -- build -- run 手动操作,单个的容器。
如果说一个大的微服务项目中有成百个服务,并且的这些服务之间有着依赖关系,上面这种操作实现就会非常的繁琐。Docker Compose 就是用来进行轻松高校的管理容器,可以定义和运行多个容器。
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process:
Define your app’s environment with a Dockerfile
so it can be reproduced anywhere.
- 创建 Dockerfile 保证项目在任何地方可以运行
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 配置文件来定义服务
- 服务:容器、应用(web、mysql、redis ......)
Run docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up
using the docker-compose binary.
- 启动项目
作用:批量容器编排
Compose 是 Docker 官方开源的项目,使用前需要进行安装。
Dokcerfile 可以让程序在任何地方运行,简化了运维的部署,假设有一个 web 服务,这个服务需要 多个容器:redis、mysql、nginx...... 如果我们一个一个去 build 非常的麻烦。
可以写一个 Compose 批量把这些服务打包进来
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
# 在这个文件里面编排的容器,通过 docker-compose up 就可以一键启动
# 这些所有的服务运行起来就是一个完整的项目(一组关联的容器)
13.2 安装 Compose
官网地址:docs.docker.com/compose/ins…
# 官网的下载地址,非常的慢
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
# 国内的镜像
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose version
13.3 使用
官网:docs.docker.com/compose/get…
官网案例:python应用,计数器,使用 redis 进行计数
创建一个应用
就是创建一个目录
mkdir composetest
cd composetest
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)
- 创建一个需要的依赖包 requirements.txt
flask
redis
# syntax=docker/dockerfile:1
FROM 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
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
#######################################################
# 上面的官网给出的例子,可能是版本的问题,执行失败,可以使用下面的内容
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python","app.py"]
# 从 python3.6 镜像开始构建镜像
# 将当前目录添加到 . / code 镜像中的路径
# 将工作目录设置为 /code
# 安装 python 的依项
# 将容器的默认命令设置为 python app.py
version: "3.9"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
#######################################################
# 上面的官网给出的例子,可能是版本的问题,执行失败,可以使用下面的内容
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: "redis:alpine"
# 从 Compose 文件定义了两个服务 web 和 redis
# 使用 Dockerfile 当前目录中构建的镜像
# 将容器上的公开端口 5000 转发到主机上的端口 5000.
# redis 服务使用从 Docker Hub 注册表中提取的公共 redis 镜像
运行测试
在有 docker-compose.yml 的文件夹下执行下面的命令
docker-compose up
启动成功,包括两个服务,web 和 redis
流程:
在上面我们创建的文件名是 composetest,根据 docker-compose.yml
配置文件中的信息创建了两个服务
这些启动的服务的名字都是自动生成的,是一些默认规则。
启动之后是有两个服务的,可以使用 curl 访问得到返回值
docker-compose 中的依赖全部帮我们下载了
docker service ls
# 这个命令是查看集群中的服务,因为上面的例子不是集群的,所以会报错
默认的服务名: 文件名 _ 服务名 _ num
假如有多个服务器,集群,我们的一个服务可能会在 A 服务器上运行,也可能在 B 服务器上运行
_num 表示的是一个副本数量。
假如我们需要运行 redis 服务,有 4 个副本
项目中的内容都在同一个网络下,所以可以通过域名进行访问。
使用命令:docker network inspect composetest_default
可以查看网络信息的详情
快捷键:Ctrl + C
进入到 composetest 目录下执行命令:docker-compose down
13.4 Compose 编写配置规则 yaml
官网地址:docs.docker.com/compose/com…
Compose 的核心就是 docker-compose.yaml 配置文件
- docker-compose.yaml 配置文件有 3 层
version: '' # 版本 与 docker 引擎对应
services: # 服务
服务1: web
# 服务配置
image
build
network
......
服务2: redis
......
......
# 其他配置 网络/卷、全局配置
volumes:
network:
configs:
......
version
版本信息根据官网给出的信息
注意依赖这个配置信息
因为镜像的启动是有顺序的,假如上面的 web 需要先启动 redis
13.5 使用 Compose 一键部署 WP bok
官网案例:docs.docker.com/samples/wor…
version: "3.9"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
docker-compose up -d
13.6 实战--构建自己的微服务
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080--"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
version: 3.9
services:
lssapp:
build: .
image: lssapp
depends_on:
- redis
ports:
- "8080:8080"
redis:
image: "redis:alpine"
docker-compose up # 启动
如果项目需要重新构建可以使用这个命令
docker-compose up --build
14. Docker Swarm
14.1 环境搭建
在阿里云购买 4 台服务器用于做集群操作,选择按量收费就行
也可以在本地开 4 个虚拟机模拟集群操作
在 4 台服务器上安装 docker
14.2 介绍
官网地址:docs.docker.com/engine/swar…
工作模式:
Docker Engine 1.12 introduces swarm mode that enables you to create a cluster of one or more Docker Engines called a swarm. A swarm consists of one or more nodes: physical or virtual machines running Docker Engine 1.12 or later in swarm mode.
There are two types of nodes: managers and workers. 两个节点:管理节点、工作节点
操作都在 管理节点
14.3 操作
# 配置一下集群,将 docker01 节点成为一个主节点
# 初始化节点
docker swarm init --advertise-addr 192.168.253.155
# 初始完可以得到两个命令i
# 加入一个节点
docker swarm join
# 获取令牌,可以通过令牌让别的节点加入进来
docker swarm join-token manager
docker swarm join-token worker
# 在 docker02 节点上执行命令,将节点加入 docker01,加入过去的就是一个 worker
docker swarm join --token SWMTKN-1-10kwelhmau8q2l45uqp8jep709ns2mlro1csndykeeigvkl0vx-873o4olo10103ctckdl2ppadh 192.168.253.155:2377
# 在 docker01 主节点上执行命令,可以看到集群的节点信息
docker node ls
将 docker03 加入集群并初始化为 manage;将 docker04 加入集群并初始化为 worker;
集群搭建完成!!!
14.4 Raft 协议
上面的集群中搭建的两个主节点两个从节点,假设一个节点挂了,其他节点是否可用?
Raft 协议:保证大多数节点存活才可以用。
加入 docker01 节点宕机了,那么其他节点也都是不能使用了,包括另一个管理节点
docker01 节点再次启动之后,我们发现 Leader 变成了 docker03 的节点
# 使用命令离开一个节点
docker swarm leave
# 结果:Node left the swarm.
将 docker02 节点也加入到管理节点,再次停掉管理节点 docker01 其他管理节点还是可以操作的,剩余两个管理节点
再次停掉一个管理节点,剩余一个管理节点,这种情况是没有办法使用的
所以,为保证集群的可用性,有 3 个主节点,保证 > 1 台管理节点存活才能正常使用集群的操作(保证大多数节点存活才可以使用,高可用)
14.5 Swarm 集群弹性创建服务
弹性、扩缩容、集群
之前使用 docker-compose up 启动的一个项目也是单机的。
集群下面所有的东西都到了 swarm 里面,所有的东西都变成了 docker service。
容器 变成了 服务
假设 redis 需要启动三个,对于单体的来说就是启动了三个容器。
集群状态下,为了保证高可用,web 应用连接 redis,redis 有 3 台分布在不同的机器上,这个机器上不可能通过 ip 地址去访问,因为 ip 因为 docker 的ip地址会变化的,所以需要通过服务名来进行访问,这个集群就屏蔽了低等的节点的差异,只需要通过服务名就可以访问到集群。一个 redis 服务可能是好多个副本开启,假设一个挂掉了,其他的仍然可以使用。
操作
# 启动一个 nginx 的服务
docker service create -p 8888:80 --name my-nginx nginx
################################
docker run 容器启动,不具有扩缩容
docker service 服务启动,具有扩缩容等
查看服务,只启动一个容器,只有一个副本
这一个的情况下,如果访问量特别大,一个服务可能扛不住,需要多开几个服务,所以要做到动态的扩容
动态扩缩容
# 为 my-nginx 服务创建 3 个副本(扩缩容)
docker service update --replicas 3 my-nginx
# 也可以用这个命令进行服务的扩缩容
docker service scale my-nginx=10
启动的多个副本分配到集群内的各个主机上,这些服务在集群中的任意的节点都可以进行访问。服务可以有多个副本,动态的扩缩容,实现高可用。
14.6 概念的总结
swarm:集群的管理和编排,docker 可以初始化一个 swarm 集群,其他节点可以加入。有管理和工作两个角色。
Node:就是一个 docker 的节点,多个节点就组成了一个网络的集群。有管理和工作两个角色
Service:就是一个任务,可以在管理节点或者工作节点来运行,是核心,用户可以访问。启动方式 docker service
Task:容器内的命令的,是一个细节的任务。在创建容器的时候是一层一层的
命令 --> 管理 --> api --> 调度 --> 工作节点(创建 Task 容器维护创建)
服务副本与全局服务
所有的节点都是分配的,管理节点和工作节点都可以跑项目
项目可以分为全局运行和只能在副本上运行
可以设置项目只在副本上运行和全局运行
14.6.1 Docker Stack
# docker-compose 单机部署项目
docker-compose up -d wordpress.yml
# Docker Stack 部署---集群部署项目
docker stack deploy wordpress.yml
# docker-compose.yml 使用 stack
version: '3.4'
services:
mongo:
image: mongo
restart: always
networks:
- mongo_network
deploy:
restart_policy:
condition: on-failure
replicas: 2
mongo-express:
image: mongo-express
restart: always
networks:
- mongo_network
ports:
- target: 8081
published: 80
protocol: tcp
mode: ingress
environment:
ME_CONFIG_MONGODB_SERVER: mongo
ME_CONFIG_MONGODB_PORT: 27017
deploy:
restart_policy:
condition: on-failure
replicas: 1
networks:
mongo_network:
external: true
14.6.2 Docker Secret
进行安全配置,配置密码、证书等......
14.6.3 Docker Config
对容器进行统一的一些配置
学习参考视频:www.bilibili.com/video/BV1og…
学习参考视频:www.bilibili.com/video/BV1kv…