赞
踩
三体:弱小和无知不是生存的障碍,傲慢才是。
从基础到进阶,每个视频都有认真看,做笔记和练习,以此篇分享整个学习过程
画图网页
docker学习
一款产品:开发--上线 两套环境 应用环境,应用配置
开发 ---- 运维
问题:我在我电脑上可以运行,版本更新,导致服务不可用,对于运维来说,考验十分大
环境配置十分麻烦,每一个机器都要部署环境(集群redis,ES ,hadoop...)费时费力
发布一个项目(jar+(redis mysql jdk ES)) 项目能不能都带上环境安装打包
之前在服务器配置一个应用的环境 redis mysql jdk ES ,配置超麻烦,不能够跨平台,Windows,最后发布到Linux
传统:开发jar,运维来做
现在:开发打包部署上线,一套流程做完
开发APP应用:Java --- apk -- 发布(应用商店)--- 张三使用apk ---安装即可用
开发运维环境:Java -- jar(环境)--- 打包项目带上环境(镜像) -- (docker仓库:商店)-- 下载我们发布的镜像--直接运行即可
docker给以上问题,提出解决方案
docker的思想来自于集装箱
jre -- 多个应用(端口冲突)---原来都是交叉的
隔离:docker核心思想,打包装箱,每个箱子是相互隔离的
水果 生化武器
docker通过隔离机制,可以将服务器利用到极致
本质:所有的技术都是因为出现一些问题,我们需要解决,才去学习
2010年,几个搞IT的年轻人,就在美国成立了一家公司dotCloud
做一些pass的云计算服务,LXC有关的容器技术
他们将自己的技术(容器化技术)命名就是docker
docker刚刚诞生的时候,没有引起行业的注意,dotCloud,就活不下去
2013年,docker开源
开源
开放源代码
docker越来越多的人发现了docker的优点,火了,docker每个月都会更新一个版本
2014年4月9日,docker1.0发布
docker为什么这么火?因为十分轻巧
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在Windows中装一个Vmware,通过这个软件我们开源虚拟出来一台或者多台电脑,笨重
虚拟机也是属于虚拟化技术,docker容器技术,也是一种虚拟化技术
vm:Linux centos原生镜像(一个电脑) 隔离:需要开启多个虚拟机 几个G 启动:几分钟
docker:隔离,镜像(最核心的环境4m + jdk + mysql)十分的小巧,运行镜像就可以了 几个M KB 秒级启动
到现在,所有的开发人员都要会docker
聊聊docker
docker是基于GO语言开发的,开源项目
官网
docker的文档 ( docker的文档是超级详细的)
仓库地址
之前的虚拟机技术
虚拟机技术缺点
1. 资源占用十分多
2、冗余步骤多
3、启动很慢
容器化技术
容器化技术不是模拟的一个完整的操作系统
比较docker和虚拟机技术的不同
DevOps(开发、运维)
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了docker之后,我们部署应用就和搭积木一样
项目打包为一个镜像,扩展服务器A,服务器B
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的
更高效的计算资源利用
docker是内核级别的虚拟化,可以在一个物理机上运行多个容器实例,服务器的性能可以被压榨到极致
docker的基本组成
client docker_host repository
docker build docker daemon
docker pull containers images
docekr run
客户端 服务器 远程资源库
构建一个容器 守护进程
拉取一个容器 容器 镜像
运行一个容器
镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务
eg: tomcat镜像===>run==>tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
容器(container):
docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的
启动,停止,删除,基本命令
目前就可以把这个容器理解为一个简易的Linux系统
仓库(repository):
仓库就是存放镜像的地方,分为公有仓库和私有仓库
环境准备
1、Linux基础
2、centos7
3、远程连接服务器
环境查看
# 系统内核是 3.10以上
[root@k2 ~]# uname -r
5.4.194-1.el7.elrepo.x86_64
# 系统版本 [root@k2 ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
安装
安装步骤
1、 官方安装参考手册
2、确定是centos7及以上版本
3、yum 安装 gcc相关环境(需要确保 虚拟机可以上外网)
yum -y install gcc
yum -y install gcc-c++
4、 安装
# 1、卸载旧的版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # 2、需要的安装包 yum install -y yum-utils # 3、设置镜像的仓库 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 # 4、安装docker docker-ce 社区版 ee 企业版 yum install docker-ce docker-ce-cli containerd.io # 5、启动docker systemctl start docker # 6、查看是否安装成功 docker version # 7、hello-world docker run hello-world # 8、查看下载的这个 hello-world的镜像 docker images # 9、卸载docker 1)卸载依赖 yum remove docker-ce docker-ce-cli containerd.io 2)删除资源 rm -rf /var/lib/docker docker的默认工作路径 rm -rf /var/lib/containerd
[root@k2 ~]# yum remove docker \ > docker-client \ > docker-client-latest \ > docker-common \ > docker-latest \ > docker-latest-logrotate \ > docker-logrotate \ > docker-engine 已加载插件:fastestmirror 参数 docker 没有匹配 参数 docker-client 没有匹配 参数 docker-client-latest 没有匹配 参数 docker-common 没有匹配 参数 docker-latest 没有匹配 参数 docker-latest-logrotate 没有匹配 参数 docker-logrotate 没有匹配 参数 docker-engine 没有匹配 不删除任何软件包 [root@k2 ~]# yum install -y yum-utils 已加载插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.cn99.com * elrepo: hkg.mirror.rackspace.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com base | 3.6 kB 00:00 docker-ce-stable | 3.5 kB 00:00 elrepo | 3.0 kB 00:00 extras | 2.9 kB 00:00 mysql-connectors-community | 2.6 kB 00:00 mysql-tools-community | 2.6 kB 00:00 mysql57-community | 2.6 kB 00:00 updates | 2.9 kB 00:00 (1/3): elrepo/primary_db | 547 kB 00:00 (2/3): extras/7/x86_64/primary_db | 247 kB 00:00 (3/3): updates/7/x86_64/primary_db | 16 MB 00:39 软件包 yum-utils-1.1.31-54.el7_8.noarch 已安装并且是最新版本 无须任何处理 [root@k2 ~]# yum-config-manager \ > --add-repo \ > https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 已加载插件:fastestmirror adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo grabbing file https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo repo saved to /etc/yum.repos.d/docker-ce.repo [root@k2 ~]# yum makecache fast 已加载插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.cn99.com * elrepo: hkg.mirror.rackspace.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com base | 3.6 kB 00:00 docker-ce-stable | 3.5 kB 00:00 elrepo | 3.0 kB 00:00 extras | 2.9 kB 00:00 mysql-connectors-community | 2.6 kB 00:00 mysql-tools-community | 2.6 kB 00:00 mysql57-community | 2.6 kB 00:00 updates | 2.9 kB 00:00 元数据缓存已建立 [root@k2 ~]# yum install docker-ce docker-ce-cli containerd.io 已加载插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.cn99.com * elrepo: hkg.mirror.rackspace.com * extras: mirrors.cn99.com * updates: mirrors.cn99.com 软件包 3:docker-ce-20.10.16-3.el7.x86_64 已安装并且是最新版本 软件包 1:docker-ce-cli-20.10.16-3.el7.x86_64 已安装并且是最新版本 软件包 containerd.io-1.6.4-3.1.el7.x86_64 已安装并且是最新版本 无须任何处理 [root@k2 ~]# systemctl start docker [root@k2 ~]# docker version Client: Docker Engine - Community Version: 20.10.16 API version: 1.41 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. [root@k2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 8 months ago 13.3kB
1、登录阿里云
登录阿里云–产品与服务–容器服务–容器镜像服务
2、找到镜像加速地址
镜像工具–镜像加速器–加速器地址
3、配置使用
# 1、创建目录
sudo mkdir -p /etc/docker
# 2、编写配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://qjx6666.mirror.aliyuncs.com"]
}
EOF
# 3、重启服务
sudo systemctl daemon-reload
# 4、重启docker
sudo systemctl restart docker
run的运行流程图
docker是怎么工作的?
Docker是一个 Client-Server结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问
DockerServer接收到Docker-Client的指令,就会执行这个命令
docker为什么比vm快?
1、docker有着比虚拟机更少的抽象层
2、docker利用的是宿主机的内核,VM需要的是Guest OS
所以说,新建一个容器的时候,docker不需要像虚拟机一样,重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别的,docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级
docker version 显示docker的版本
docker info 查看docker的系统信息,包括镜像和容器的数量
docker 命令 --help 帮助命令
或者
[root@k2 ~]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
-a, --all Show all images (default hides intermediate images)
--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 Only show image IDs
docker images 查看所有本地主机上的镜像
[root@k2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 8 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a , --all 列出所有镜像
-q, --quiet 只显示镜像的id
docker search 搜索镜像
hub搜索镜像
或者
[root@k2 ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12635 [OK]
# 可选项,通过搜索来过滤
--filter=STARS=5000 搜索出来的镜像,STARS大于5000
[root@k2 ~]# docker search redis --filter=STARS=5000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redis Redis is an open source key-value store that… 10937 [OK]
docker pull 下载镜像
[root@k2 ~]# docker pull --help
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Pull an image or a repository from a registry
Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)
--platform string Set platform if server is multi-platform capable
-q, --quiet Suppress verbose output
# 下载镜像 docker pull 镜像名[:tag] [root@k2 ~]# docker pull mysql Using default tag: latest 如果不写tag,默认是latest latest: Pulling from library/mysql 72a69066d2fe: Pull complete 分量下载,docker image的核心 联合文件系统 93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 688ba7d5c01a: Pull complete 00e060b6d11d: Pull complete 1c04857f594f: Pull complete 4d7cfa90e6ea: Pull complete e0431212d27d: Pull complete Digest: sha256:e9027fe4d91c666666666666666f7738b66666666709 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest 真实地址 # 等价于 docker pull mysql docker pull docker.io/library/mysql:latest # 指定版本下载 docker pull mysql:5.7
docker rmi删除镜像
[root@k2 ~]# docker rmi -f 镜像ID # 删除指定镜像
[root@k2 ~]# docker rmi -f 镜像ID 镜像ID 镜像ID 删除多个镜像
[root@k2 ~]# docker rmi -f $(docker images -aq) 删除全部镜像
说明:有了镜像才可以创建容器,Linux,下载一个centos镜像来测试学习
[root@k2 ~]# docker pull centos
新建容器并启动
docker run [可选参数] image # 参数说明 --name="name" 容器名字 Tomcat01 tomcat02 用来区分容器 -d 后台方式运行 -it 使用交互方式运行,进入容器查看内容 -P 指定容器的端口, -P 8080:8080 -P ip:z主机端口:容器端口 -P 主机端口:容器端口 -P 容器端口 容器端口 -p 随机指定端口 # 测试,启动并进入容器 [root@k2 ~]# docker run -it mysql /bin/bash [root@6ae3c9bb6a51 /]# ls # 查看容器内的mysql,基础版本,很多命令都是不完整的 bin boot dev docker-entrypoint-initdb.d entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # 从容器中退回主机 [root@6ae3c9bb6a51 /]# exit exit [root@k2 /]# ls bin data etc lib media mydata proc run srv tmp var boot dev home lib64 mnt opt root sbin sys usr
列出所有运行的容器
# docker ps 命令
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器 + 带出历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号
[root@k2 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@k2 /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ae3c9bb6a51 centos "/bin/bash" 6 minutes ago Exited (0) 3 minutes ago adoring_vaughan
1c1c8a07c2ed feb5d9fea6a5 "/hello" 14 hours ago Exited (0) 14 hours ago quirky_mahavira
[root@k2 /]# docker ps -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ae3c9bb6a51 centos "/bin/bash" 9 minutes ago Exited (0) 5 minutes ago adoring_vaughan
[root@k2 /]# docker ps -aq
6ae3c9bb6a51
1c1c8a07c2ed
退出容器
exit # 直接容器停止并退出
ctrl+p+q # 容器不停止退出
[root@k2 /]# docker run -it centos /bin/bash
[root@2bc63e25611d /]# [root@k2 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bc63e25611d centos "/bin/bash" 17 seconds ago Up 17 seconds competent_almeida
删除容器
docker rm 容器id 删除指定容器,不能删除正在运行的容器,如果强制删除,rm -f
docker rm -f $(docker ps -aq) 删除所有容器
docker ps -a -q|xargs docker rm 删除所有容器
[root@k2 /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2bc63e25611d centos "/bin/bash" 3 minutes ago Up 3 minutes competent_almeida 6ae3c9bb6a51 centos "/bin/bash" 16 minutes ago Exited (0) 12 minutes ago adoring_vaughan 1c1c8a07c2ed feb5d9fea6a5 "/hello" 14 hours ago Exited (0) 14 hours ago quirky_mahavira 7f40b43e271b feb5d9fea6a5 "/hello" 16 hours ago Exited (0) 16 hours ago youthful_northcutt 10b62dbb98ac fe363d9a6ba4 "java -jar /app.jar …" 19 hours ago Exited (143) 15 hours ago 66-springboot-web [root@k2 /]# docker rm 2bc63e25611d # 不能删除正在运行的容器 Error response from daemon: You cannot remove a running container 2bc63e25611dea862ad877730bc87b2dc9ee7bcb5bfb50dc604dc146700f1b41. Stop the container before attempting removal or force remove [root@k2 /]# docker rm 6ae3c9bb6a51 6ae3c9bb6a51 [root@k2 /]# docker ps -aq 2bc63e25611d 1c1c8a07c2ed 7f40b43e271b 10b62dbb98ac [root@k2 /]# docker rm -f $(docker ps -aq) 2bc63e25611d 1c1c8a07c2ed 7f40b43e271b 10b62dbb98ac [root@k2 /]# docker ps -aq
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前的容器
[root@k2 /]# docker run -it centos /bin/bash [root@990384ccba9f /]# exit exit [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@k2 /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 990384ccba9f centos "/bin/bash" 25 seconds ago Exited (0) 18 seconds ago funny_elgamal [root@k2 /]# docker start 990384ccba9f 990384ccba9f [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 990384ccba9f centos "/bin/bash" About a minute ago Up 7 seconds funny_elgamal [root@k2 /]# docker stop 990384ccba9f 990384ccba9f [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
后台启动容器
# 命令 docker run -d 镜像名
[root@k2 ~]# docker run -d centos
# 问题docker ps 发现,centos停止了
# 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
[root@k2 /]# docker run -d centos
ed05d164f186f33599a6fc557632fac4fae02d6ab83e2aaec22ea5cca554640d
[root@k2 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@k2 /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed05d164f186 centos "/bin/bash" 3 minutes ago Exited (0) 3 minutes ago condescending_mcnulty
990384ccba9f centos "/bin/bash" 8 minutes ago Exited (0) 7 minutes ago funny_elgamal
查看日志
docker logs -tf --tail 容器,没有日志
# 自己编写一段shell脚本
[root@k2 /]# docker run -d centos /bin/sh -c "while true;do echo hello;sleep 2;done"
[root@k2 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e705ce9ef994 centos "/bin/sh -c 'while t…" About a minute ago Up About a minute priceless_lichterman
# 显示日志
--tf 显示日志
--tail number 要显示日志条数
[root@k2 /]# docker logs -tf --tail 10 e705ce9ef994
[root@k2 /]# docker run -d centos /bin/sh -c "while true;do echo hello;sleep 2;done" e705ce9ef994919a5749b594269ca6fb3dec38d1b1b03aa7b732e42faeb75030 [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e705ce9ef994 centos "/bin/sh -c 'while t…" 13 seconds ago Up 12 seconds priceless_lichterman [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e705ce9ef994 centos "/bin/sh -c 'while t…" About a minute ago Up About a minute priceless_lichterman [root@k2 /]# docker logs -tf --tail 10 e705ce9ef994 2022-05-26T09:42:34.542832791Z hello 2022-05-26T09:42:36.544598561Z hello 2022-05-26T09:42:38.546502476Z hello 2022-05-26T09:42:40.548252395Z hello ^Z [2]+ 已停止 docker logs -tf --tail 10 e705ce9ef994 [root@k2 /]# docker logs -tf e705ce9ef994 2022-05-26T09:41:18.474030912Z hello 2022-05-26T09:41:20.476489047Z hello
查看容器中进程信息 ps
# 命令 docker top 容器id
[root@k2 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e705ce9ef994 centos "/bin/sh -c 'while t…" 8 minutes ago Up 8 minutes priceless_lichterman
[root@k2 /]# docker top e705ce9ef994
UID PID PPID C STIME TTY TIME CMD
root 5624 27182 0 17:50 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2
root 27182 27163 0 17:41 ? 00:00:00 /bin/sh -c while true;do echo hello;sleep 2;done
查看镜像的元数据
# 命令 docker inspect 容器id
# 测试
[root@k2 /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e705ce9ef994 centos "/bin/sh -c 'while t…" 13 minutes ago Up 13 minutes priceless_lichterman
199564832c3e centos "/bin/sh -C 'while t…" 14 minutes ago Exited (127) 14 minutes ago recursing_lewin
[root@k2 /]# docker inspect e705ce9ef994
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置 # 命令 docker exec -it 容器id bashshell # 测试 [root@k2 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e705ce9ef994 centos "/bin/sh -c 'while t…" 21 minutes ago Up 21 minutes priceless_lichterman [root@k2 /]# docker exec -it e705ce9ef994 /bin/bash [root@e705ce9ef994 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@e705ce9ef994 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 09:41 ? 00:00:00 /bin/sh -c while true;do echo hello;sleep 2;done root 674 0 0 10:03 pts/0 00:00:00 /bin/bash root 698 1 0 10:03 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2 root 699 674 0 10:03 pts/0 00:00:00 ps -ef # 方式二 docker attach 容器id # 测试 [root@k2 /]# docker attach e705ce9ef994 正在执行当前代码....... [root@k2 ~]# docker rm -f $(docker ps -aq) # 前面循环没停,直接全停了 docker exec # 进入容器后开启一个新的终端,可以在里面操作 docker attach # 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
[root@k2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@k2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 5d0da3dc9764 8 months ago 231MB [root@k2 ~]# docker run -it centos /bin/bash [root@k2 ~]# docker run -it centos /bin/bash [root@93823941b78c /]# [root@k2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 93823941b78c centos "/bin/bash" 16 seconds ago Up 15 seconds romantic_sinoussi [root@k2 ~]# cd /home/ [root@k2 home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 93823941b78c centos "/bin/bash" About a minute ago Up About a minute romantic_sinoussi # 进入容器内部 [root@k2 home]# docker attach 93823941b78c [root@93823941b78c /]# cd /home/ [root@93823941b78c home]# ls # 在容器内新建一个文件 [root@93823941b78c home]# touch test.java [root@93823941b78c home]# ls test.java [root@93823941b78c home]# exit exit [root@k2 home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@k2 home]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 93823941b78c centos "/bin/bash" 3 minutes ago Exited (0) 7 seconds ago romantic_sinoussi # 查看当前主机目录 [root@k2 home]# ls idea kuan.java # 将文件拷贝到主机上 [root@k2 home]# docker cp 93823941b78c:/home/test.java /home/ [root@k2 home]# ls idea kuan.java test.java
拷贝是一个手动过程,未来我们使用-v 卷的技术,可以实现,自动同步 /home /home
attach Attach to a running Container # 当前 shell下 attach 连接指定运行镜像 build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像 commit Create a new image from a container changes # 提交当前容器为新的镜像 cp Copy files/folders from the containers filesystem to the host path # 从容器中拷贝指定文件或目录到宿主机中 create Create a new container # 创建一个新的容器,同run,但不启动容器 diff Inspect changes on a container's filesystem # 查看 docker 容器变化 events Get real time events form the server # 从 docker 服务获取容器实时事件 exec Run a command in an existing container # 在已存在的容器上运行命令 export Stream the containers of a container as a tar archive # 导出容器的内容流作为一个tar 归档文件【对应 import】 history show the history of an image # 展示一个镜像形成历史 images list images # 列出系统当前镜像 import create a new filesystem image from the contents of a tarball # 从 tar 包中的内容创建一个新的文件系统映像【对应 export】 info display system-wide infomation # 显示系统相关信息 inspect return low-level infomation on a container # 查看容器详细信息 kill kill a running container # kill 指定 docker 容器 load load an image from a tar archive # 从一个 tar 包中加载一个镜像【对应 save】 login register or login to the docker registry server # 注册或者登陆一个 docker 源服务器 logout log out from a docker registry server # 从当前 docker registry退出 logs fetch the logs of a container # 输出当前容器日志信息 port lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口 pause pause all processes within a container # 暂停容器 ps list containers # 列出容器列表 pull pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或者库镜像 push push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器 restart restart a running container # 重启运行的服务器 rm remove one or more containers # 移除一个或者多个容器 rmi remove one or more images # 移除一个或者多个镜像(无容器使用该镜像才可以删除,否则需删除相关容器才可继续或 -f 强制删除) run run a command in a new container # 创建一个新的容器并运行一个命令 save save an image to a tar archive # 保存一个镜像为一个tar包【对应 load】 search search for an image on the docker hub # 在 docker hub 中搜索镜像 start start a stopped container # 启动容器 stop stop a running container # 启动容器 tag tag an image into a repository # 给源镜像搭标签 top lookup the running processes of a container # 查看容器中运行的进程信息 unpause unpause a paused container # 取消暂停容器 version show the docker version infomation # 查看 docker 版本号 wait block until a container stops,then print its exit code # 截取容器停止时间的退出状态值
docker 的命令是十分多的,上面是最常用的容器和镜像的命令,之后会更多
Docker 安装 Nginx
# 1、搜索镜像 search 建议去docker上搜索,可以看到详细信息和帮助文档 [root@k2 ~]# docker search nginx # 2、下载镜像 [root@k2 ~]# docker pull nginx # 3、运行测试 [root@k2 ~]# docker images # 查看镜像 REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest de1111b9436b 36 hours ago 142MB # -d 后台运行 # --name 给容器命名 # -p 宿主机端口:容器内部端口 [root@k2 ~]# docker run -d --name nginx01 -p 3344:80 nginx 50666666ad4e9e6b9666666666c8ec08666666633 [root@k2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 50c35333a98 nginx "/docker-entrypoint.…" 57 seconds ago Up 57 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@k2 ~]# curl localhost:3344 # 查看浏览器 http://IP:3344/ # 进入容器 [root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 506666e98 nginx "/docker-entrypoint.…" 38 minutes ago Up 38 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@k3 ~]# docker exec -it nginx01 /bin/bash root@506666e98:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@5066666e98:/# cd /etc/nginx/ root@5066666e98:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params root@5066666e98:/etc/nginx# # 停止容器 root@503666w98:/etc/nginx# exit exit [root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 506666e98 nginx "/docker-entrypoint.…" 43 minutes ago Up 43 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@k3 ~]# docker stop 5066666e98 506666e98 # 查看浏览器 http://IP:3344/
[root@k2 home]# docker search nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 16850 [OK] [root@k2 home]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx a2abf6c4d29d: Pull complete a9edb18cadd1: Pull complete 589b7251471a: Pull complete 186b1aaa4aa6: Pull complete b4df32aa5a72: Pull complete a0bcbecc962e: Pull complete Digest: sha256:0d17b56666666669f762b016666653c9b31 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest [root@k2 home]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 4 months ago 141MB [root@k2 home]# [root@k2 home]# docker run -d --name nignx01 -p 3344:80 nignx Unable to find image 'nignx:latest' locally ^Z [1]+ 已停止 docker run -d --name nignx01 -p 3344:80 nignx [root@k2 home]# docker run -d --name nginx01 -p 3344:80 nginx 781c217839666666665b6243d02249945f64ca03ccffee64 [root@k2 home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 781c217839cb nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@k2 home]# curl localhost:3344 <!DOCTYPE html> <html> <head> <p><em>Thank you for using nginx.</em></p> </body> </html> [root@k2 home]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 781c217839cb nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 [root@k2 home]# docker exec -it nginx01 /bin/bash root@781c217839cb:/# whereis nginx nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@781c217839cb:/# cd /etc/nginx/ root@781c217839cb:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params root@781c217839cb:/etc/nginx#
端口暴露概念
思考:每次修改Nginx配置文件,都要进入容器内,特麻烦?在容器外部提供一个映射路径,达到容器外修改文件,容器内自动修改? -v数据卷
作业:docker装一个Tomcat
# 官方的使用 docker run -it --rm tomcat:9.0 # 我们之前的启动都是后台,停止了容器之后,容器还是可以查到 docker run -it --rm tomcat:9.0,一般用来测试,用完就删除 # 下载再启动 docker pull tomcat # 启动运行 docker run -d -p 3355:8080 --name tomcat01 tomcat # 测试访问没有问题 # IP:3355 访问失败 # 进入容器 docker exec -it tomcat01 /bin/bash ls # 发现问题:1、Linux命令缺失 2、没有WebApps,阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除,保证最小可运行的环境 [root@k3 ~]# docker exec -it tomcat01 /bin/bash root@c95eb14e8fd4:/usr/local/tomcat# root@c95eb14e8fd4:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@c95eb14e8fd4:/usr/local/tomcat# cd webapps root@c95eb14e8fd4:/usr/local/tomcat/webapps# ls root@c95eb14e8fd4:/usr/local/tomcat/webapps# cd .. root@c95eb14e8fd4:/usr/local/tomcat# cd webapps.dist/ root@c95eb14e8fd4:/usr/local/tomcat/webapps.dist# ls ROOT docs examples host-manager manager root@c95eb14e8fd4:/usr/local/tomcat/webapps.dist# cd .. root@c95eb14e8fd4:/usr/local/tomcat# cp -r webapps.dist/* webapps root@c95eb14e8fd4:/usr/local/tomcat# cd webapps root@c95eb14e8fd4:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager
思考:每次部署项目,都要进入容器内,特麻烦?在容器外部提供一个映射路径,webapps
docker 容器 tomcat + 网站
作业:部署es+kibana
# es 暴露的端口很多 # es 十分耗内存 # es 的数据一般需要放置到安全目录,挂载 # --net ? 网络配置 [root@k2 home]# docker network create somenetwork-net # 启动 elasticsearch docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2 # 启动了 Linux就卡住了,docker stats 查看CPU状态 # 查看docker stats # 赶紧关闭,增加内存的限制 # 赶紧关闭,增加内存的限制,修改配置文件 -e 环境配置修改 docker run -d --name elasticsearch02 --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2 [root@k3 ~]# curl localhost:9200 { "name" : "73ca196f0e2b", "cluster_name" : "docker-cluster", "cluster_uuid" : "Tp1Ui1grShONIGapLhiwgg", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f", "build_date" : "2020-03-26T06:34:37.794943Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
作业:使用 kibana连接es ? 思考网络如何才能连接过去
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Docker图形化界面管理工具,提供一个后台面板供我们操作
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:外网:8088
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
即:所有的应用,直接打包成Docker镜像,就可以直接跑起来!
UnionFS(联合文件系统)
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交,来一层层的叠加。同时可以将不同目录,挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像概念),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS(联合文件系统)。
bootfs(boot file system):主要包含bootloader和kernel(Linux内核),bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,而在Docker镜像的最底层也是bootfs这一层,这与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后,整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system):rootfs在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装进虚拟机的CentOS系统都是好几个G,为什么Docker这里才200M?
[root@k2 home]# docker images centos
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 5d0da3dc9764 8 months ago 231MB
对于一个精简的OS系统,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用Host(宿主机)的kernel(也就是宿主机或者服务器的boosfs+内核),自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs部分。
这就是我们之前说:虚拟机的启动是分钟级的,容器的启动是秒级的
分层的镜像
可以去下载一个镜像,注意观察下载的日志,可以看出是一层一层的在下载
多个镜像都是从相同的base镜像构建的,宿主机只需要在磁盘上保留一份Base镜像,同时内存中也只需要加载一份Base镜像,就可以应用在所有的容器服务之中了。而且镜像的每一层都可以被共享
使用 docker image inspect可以查看镜像元数据
[root@k2 home]# docker image inspect redis:latest
加深理解
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而整体的镜像包含了来自两个镜像层的6个文件。
上图中的鏡像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
如上边的三层镜像,Docker最终会把所有镜像层堆叠并合并,对外提供统一的视图,如下图
特点
如何提交一个自己的镜像
docker commit 提交容器成为一个新的副本
# 命令和Git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名.[tag]
实战测试
# 1、启动一个默认的tomcat
# 2、发现这个默认的tomcat 是没有webapps应用,镜像的原因,官方的镜像默认webapps 下面是没有文件的
# 3、自己拷贝进去了基本的文件
# 4、将修改后的容器通过commit提交为一个镜像,我们以后使用修改后的镜像即可,这就是修改后的镜像
[root@k3 ~]# docker exec -it tomcat /bin/bash root@e5fe938049b2:/usr/local/tomcat# root@e5fe938049b2:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@e5fe938049b2:/usr/local/tomcat# cd webapps root@e5fe938049b2:/usr/local/tomcat/webapps# ls root@e5fe938049b2:/usr/local/tomcat/webapps# cd .. root@e5fe938049b2:/usr/local/tomcat# cp -r webapps.dist/* webapps root@e5fe938049b2:/usr/local/tomcat# cd webapps root@e5fe938049b2:/usr/local/tomcat/webapps# ls ROOT docs examples host-manager manager webapps.dist root@e5fe938049b2:/usr/local/tomcat# exit exit [root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e5fe938049b2 tomcat "catalina.sh run" 3 minutes ago Up 3 minutes 0.0.0.0:3355->8080/tcp, :::3355->8080/tcp tomcat [root@k3 ~]# docker commit -a="davina" -m="add webapps app" e5fe938049b2 tomcat02:1.0 sha256:e7ecf7f1a0163db9ce1206e43721bd5a47308e81579d3c8a1dae1da39c390664 [root@k3 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat02 1.0 e7ecf7f1a016 24 seconds ago 689MB tomcat latest 5eb506608219 36 hours ago 685MB
如果想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比我们以前学习VM时候,快照
现在才算入门docker!!!
docker的理念回顾
将应用和环境打包成一个镜像
数据?
~
如果数据在容器中,那么容器删除,数据就会丢失
~~~~~
需求:数据持久化
MySQL,容器删了,删库跑路,
~~~
需求:MySQL数据可以存储在本地
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!也是目录的挂载,将我们容器内的目录,挂载到Linux上面
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!
方式一:直接使用命令来挂载 ~~~ -v
docker run -it -v 主机目录:容器内目录
# 测试
[root@k2 home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来时候,我们可以通过 docker inspect 容器id
测试文件的同步
再来测试
1、停止容器
2、宿主机上修改文件
3、启动容器
4、容器内的数据依然是同
好处:我们以后修改只需要在本地修改即可,容器内会自动同步
思考:MYsql的数据持久化的问题
# 获取镜像 docker pull mysql:5.7 # 运行容器,需要做数据挂载 # 安装启动mysql,需要配置密码 # 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=pwd -d mysql:tag # 启动我们的mysql -d 后台运行 -p 端口映射 -v 卷挂载 -e 环境配置 --name 容器名字 [root@k3 /]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 启动成功之后,在本地使用Navicat连接测试一下 连接到服务器的3310 ---- 3310和容器内的3306映射,就可以连接成功
[root@k3 /]# docker pull mysql:5.7 5.7: Pulling from library/mysql c32ce6654453: Pull complete 415d08ee031a: Pull complete 7a38fec2542f: Pull complete 352881ee8fe9: Pull complete b8e20da291b6: Pull complete 66c2a8cc1999: Pull complete d3a3a8e49878: Pull complete 172aabfba65c: Pull complete fea17d0b1d1e: Pull complete fff7f5411ca9: Pull complete c33d43428e07: Pull complete Digest: sha256:16e159331007eccc069822f7b731272043ed572a79a196a05ffa2ea127caaf67 Status: Downloaded newer image for mysql:5.7 docker.io/library/mysql:5.7 [root@k3 /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE tomcat02 1.0 e7ecf7f1a016 About an hour ago 689MB tomcat latest 5eb506608219 37 hours ago 685MB nginx latest de2543b9436b 42 hours ago 142MB mysql 5.7 a3d35804fa37 8 days ago 462MB portainer/portainer latest 12b0b8dced14 10 days ago 75.4MB centos latest 5d0da3dc9764 8 months ago 231MB elasticsearch 7.6.2 f29a1ee41030 2 years ago 791MB [root@k3 /]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 f3cc67b88ff4dbd55e63ec3327985ad7a9c1cdfb4bfefc6ceb7124f7eb123536
假设将容器删除
[root@k3 /]# docker rm -f mysql01 mysql01 [root@k3 /]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e5fe938049b2 tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:3355->8080/tcp, :::3355->8080/tcp tomcat [root@k3 /]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e5fe938049b2 tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:3355->8080/tcp, :::3355->8080/tcp tomcat [root@k3 mysql]# cd /home/ [root@k3 home]# ll 总用量 0 drwxr-xr-x. 2 root root 23 5月 20 00:08 ceshi drwxr-xr-x. 4 root root 30 5月 20 00:26 mysql [root@k3 home]# cd mysql/ [root@k3 mysql]# ll 总用量 4 drwxr-xr-x. 2 root root 6 5月 20 00:26 conf drwxr-xr-x. 5 polkitd root 4096 5月 20 00:26 data
发现,我们挂载到本地的数据卷依然没有丢失,这就实现了容器数据持久化功能
# 匿名挂载 -v 容器内路径 docker run -d -P --name nginx04 -v /etc/nginx nginx # 查看所有的volume的情况 [root@k3 mysql]# docker volume ls DRIVER VOLUME NAME local f171cbe47f213b28f4d483d5f70aaaa52e611ef1e5a0cca34375ccc3bd6f5a3e # 这里发现,这个匿名挂载,在 -v 只写了容器内的路径,没有写容器外的路径 # 具名挂载 [root@k3 mysql]# docker run -d -P --name nginx05 -v juming-nginx:/etc/nginx nginx 78c0aca70fcc020f8daf0e9da4475e3453f8f7be360cc2743f9706e1a48e2880 [root@k3 mysql]# docker volume ls DRIVER VOLUME NAME local juming-nginx # 通过 -v 卷名:容器内路径 查看一下这个卷
所有的docker容器内的卷,没有指定目录的情况下,都是在/var/lib/docker/volumes/xxxxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载
[root@k3 mysql]# docker run -d -P --name nginx04 -v /etc/nginx nginx
12b4da52e66666666666666666666666666cd312c197
[root@k3 mysql]# docker volume ls
DRIVER VOLUME NAME
local f171cbe47f2136666666666666666cca34375ccc3bd6f5a3e
[root@k3 mysql]# docker run -d -P --name nginx05 -v juming-nginx:/etc/nginx nginx
78c0ac666666666666666666666666643f9706e1a48e2880
[root@k3 mysql]# docker volume ls
DRIVER VOLUME NAME
local f171cbe46666666666666666666666cc3bd6f5a3e
local juming-nginx
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径::容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径 :ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有了限定
docker run -d -P --name nginx05 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内都是无法操作
DockerFile就是用来构建docker镜像的构建文件
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层
# 创建一个dockerfile文件,名字可以随机,建议dockerfile
# 文件中的内容 指令(大写)、参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo ".....end...."
CMD /bin/bash
# 这里的每个命令,就是镜像的一层
# 启动自己写的容器
这个卷和外部一定一个同步的目录
查看一下卷挂载的路径
[root@k3 ~]# cd /home/ [root@k3 home]# mkdir docker-test-volume [root@k3 home]# ll 总用量 0 drwxr-xr-x. 2 root root 23 5月 20 00:08 ceshi drwxr-xr-x. 2 root root 6 5月 20 21:58 docker-test-volume drwxr-xr-x. 4 root root 30 5月 20 00:26 mysql [root@k3 home]# cd docker-test-volume/ [root@k3 docker-test-volume]# vim dockerfile1 [root@k3 docker-test-volume]# cat dockerfile1 FROM centos VOLUME ["volume01","volume02"] CMD echo ".....end...." CMD /bin/bash [root@k3 docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen/centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos ---> 5d0da3dc9764 Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in 4b2875873838 Removing intermediate container 4b2875873838 ---> 16f999ab4e62 Step 3/4 : CMD echo ".....end...." ---> Running in 2167a8190a0b Removing intermediate container 2167a8190a0b ---> 5c2538632e52 Step 4/4 : CMD /bin/bash ---> Running in 96610439a302 Removing intermediate container 96610439a302 ---> f29e4091c083 Successfully built f29e4091c083 Successfully tagged kuangshen/centos:1.0 [root@k3 docker-test-volume]# vim dockerfile1 [root@k3 docker-test-volume]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE kuangshen/centos 1.0 f29e4091c083 8 minutes ago 231MB centos latest 5d0da3dc9764 8 months ago 231MB elasticsearch 7.6.2 f29a1ee41030 2 years ago 791MB [root@k3 docker-test-volume]# docker run -it f29e4091c083 /bin/bash [root@08e521953b67 /]# ls -l total 0 lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 360 May 20 14:13 dev drwxr-xr-x. 1 root root 66 May 20 14:13 etc drwxr-xr-x. 2 root root 6 Nov 3 2020 home lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64 drwx------. 2 root root 6 Sep 15 2021 lost+found drwxr-xr-x. 2 root root 6 Nov 3 2020 media drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt drwxr-xr-x. 2 root root 6 Nov 3 2020 opt dr-xr-xr-x. 288 root root 0 May 20 14:13 proc dr-xr-x---. 2 root root 162 Sep 15 2021 root drwxr-xr-x. 11 root root 163 Sep 15 2021 run lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x. 2 root root 6 Nov 3 2020 srv dr-xr-xr-x. 13 root root 0 May 17 11:08 sys drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp drwxr-xr-x. 12 root root 144 Sep 15 2021 usr drwxr-xr-x. 20 root root 262 Sep 15 2021 var drwxr-xr-x. 2 root root 6 May 20 14:13 volume01 drwxr-xr-x. 2 root root 6 May 20 14:13 volume02 [root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 08e521953b67 f29e4091c083 "/bin/bash" 9 minutes ago Up 9 minutes inspiring_golick e6d17d636007 centos "/bin/bash" 22 hours ago Up 22 hours laughing_joliot [root@k3 ~]# docker inspect 08e521953b67
测试一下,刚才的文件是否同步出去了
这种方式我们未来使用的非常多,因为我们通常会构建自己的镜像
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径
多个mysql同步数据
# 启动3个容器,通过刚才自己写的镜像启动
[root@k3 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kuangshen/centos 1.0 f29e4091c083 2 hours ago 231MB
centos latest 5d0da3dc9764 8 months ago 231MB
[root@k3 ~]# docker run -it --name docker01 kuangshen/centos:1.0
[root@438dd0283032 /]# [root@k3 ~]#
[root@k3 ~]#
[root@k3 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
438dd0283032 kuangshen/centos:1.0 "/bin/sh -c /bin/bash" About a minute ago Up About a minute docker01
08e521953b67 f29e4091c083 "/bin/bash" 2 hours ago Up 2 hours inspiring_golick
e6d17d636007 centos "/bin/bash" 24 hours ago Up 24 hours laughing_joliot
[root@k3 ~]# docker run -it --name docker02 --volumes-from docker01 kuangshen/centos:1.0
[root@32faf9bf5a79 /]#
[root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 32faf9bf5a79 kuangshen/centos:1.0 "/bin/sh -c /bin/bash" 3 minutes ago Up 3 minutes docker02 438dd0283032 kuangshen/centos:1.0 "/bin/sh -c /bin/bash" 6 minutes ago Up 6 minutes docker01 e6d17d636007 centos "/bin/bash" 24 hours ago Up 24 hours laughing_joliot [root@k3 ~]# [root@k3 ~]# [root@k3 ~]# docker attach 438dd0283032 [root@438dd0283032 /]# ls -l total 0 lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 360 May 20 16:12 dev drwxr-xr-x. 1 root root 66 May 20 16:12 etc drwxr-xr-x. 2 root root 6 Nov 3 2020 home lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64 drwx------. 2 root root 6 Sep 15 2021 lost+found drwxr-xr-x. 2 root root 6 Nov 3 2020 media drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt drwxr-xr-x. 2 root root 6 Nov 3 2020 opt dr-xr-xr-x. 304 root root 0 May 20 16:12 proc dr-xr-x---. 2 root root 162 Sep 15 2021 root drwxr-xr-x. 11 root root 163 Sep 15 2021 run lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x. 2 root root 6 Nov 3 2020 srv dr-xr-xr-x. 13 root root 0 May 17 11:08 sys drwxrwxrwt. 7 root root 171 Sep 15 2021 tmp drwxr-xr-x. 12 root root 144 Sep 15 2021 usr drwxr-xr-x. 20 root root 262 Sep 15 2021 var drwxr-xr-x. 2 root root 6 May 20 16:12 volume01 drwxr-xr-x. 2 root root 6 May 20 16:12 volume02 [root@438dd0283032 /]# cd volume01 [root@438dd0283032 volume01]# ls [root@438dd0283032 volume01]# touch docker01.txt [root@438dd0283032 volume01]# ls docker01.txt # 退到宿主机 ctrl+P+Q [root@k3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 32faf9bf5a79 kuangshen/centos:1.0 "/bin/sh -c /bin/bash" 6 minutes ago Up 6 minutes docker02 438dd0283032 kuangshen/centos:1.0 "/bin/sh -c /bin/bash" 9 minutes ago Up 9 minutes docker01 e6d17d636007 centos "/bin/bash" 24 hours ago Up 24 hours laughing_joliot [root@k3 ~]# docker attach 32faf9bf5a79 [root@32faf9bf5a79 /]# cd volume01 [root@32faf9bf5a79 volume01]# ls docker01.txt [root@32faf9bf5a79 volume01]#
# 测试,可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试依然可以访问
多个MySQL实现数据共享
[root@k3 home]# docker run -d -p 3310:3306 -v /home/mysql/conf -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@k3 home]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候,可以实现两个容器数据同步
结论:
1、容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
2、一旦持久化到了本地,本地的数据是不会删除的
dockerfile是用来构建docker镜像的文件! 就是命令参数脚本
构建步骤:
1、编写一个dockerfile文件
2、docker build 构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(DockerHub、阿里云镜像仓库)
基础知识:
1、每个保留关键字(指令)都必须是大写字母
2、执行从上到下顺序执行
3、# 表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交
dockerfile是面向开发的,以后发布项目,做镜像,就需要编写dockerfile 文件,这个文件十分简单
Docker镜像逐渐成为企业交付的标准,必须要掌握!
步骤:
开发,部署,运维…缺一不可
DockerFile:构建文件,定义一切的步骤,源代码
DokcerImages:通过dockerFile构建生成的镜像,最终发布和运行的产品
Dokcer容器:容器就是镜像运行起来,提供服务器
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的是需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动时要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile时,就会运行这个指令,触发指令
COPY # 类似ADD,将文件拷贝到镜像中
ENV # 构建的时候,设置环境变量
[root@k3 home]# cd /home
[root@k3 home]# mkdir dockerfile
[root@k3 home]# cd dockerfile
[root@k3 dockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 5d0da3dc9764 8 months ago 231MB
[root@k3 dockerfile]# docker run -it centos
[root@ff53460fa928 /]# pwd
/
[root@ff53460fa928 /]# vim
bash: vim: command not found
[root@ff53460fa928 /]# ifconfig
bash: ifconfig: command not found
[root@ff53460fa928 /]# [root@k3 dockerfile]#
[root@k3 dockerfile]# vim mydockerfile-centos
创建一个自己的centos
# 1、编写dockerfile的文件 [root@k3 dockerfile]# cat mydockerfile-centos FROM centos MAINTAINER davina<12346789@qq.com> 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 # 2、通过这个文件构建镜像 docker build -f mydockerfile-centos -t mycentos:0.1 . # 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] . # 3、测试运行 docker images docker run -it mycentos:0.1 pwd ifconfig vim test
对比:之前的原生的centos
1、工作目录是根目录
2、添加了一些命令
docker history (IMAGE ID)
CMD 和 ENTRYPOINT 区别
CMD # 指定容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动时要运行的命令,可以追加命令
测试cmd
# 1、编写dockerfile文件
vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 2、构建镜像
docker build -f dockerfile-cmd-test -t cmdtest .
# 3、run运行,ls -a 命令生效
docker run ...
# 想追加一个命令 -l ls -a
docker run ... -l
# cmd 的清理下 -l 替换了cmd ["ls","-a"] 命令 ,-l 不是命令,所以报错
测试entrypoint
# 1、编写dockerfile文件
vim dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls","-a"]
# 2、构建镜像
docker build -f dockerfile-entrypoint-test -t entrypointtest.
# 3、run运行,ls -a 命令生效
docker run ...
# 想追加一个命令 -l ls -a
docker run ... -l
dockerfile中的很多命令都十分相似,需要了解他们的区别,可以对比他们然后测试
1、准备镜像文件 tomcat 压缩包,jdk的压缩包
下载 xxxxx.tar.gz
2、编写dockerfile文件,官方命名 Dockerfile , build 会自动寻找这个文件,就不需要 -f
touch readme.txt
vim Dockerfile
FROM centos MAINTAINER davina<1234567@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-xxx.tar.gz /usr/local/ ADD apache-tomcat-xxx.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdkxxx ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-xxx ENV CATALINA_BASH /usr/local/apache-tomcat-xxx ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-xxx/bin/startup.sh && tail -F /usr/local/tomcat-xxx/bin/logs/cataline.out
docker build -t diytomcat .
3、构建镜像
docker build -t diytomcat .
docker images
4、启动镜像
docker run -d -p 9090:8080 --name davinatomcat -v /home/davina/build/tomcat/test:/usr/local/apache-tomcat-xxx/webapps/test -v /home/davina/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-xxx/logs diytomcat
5、访问测试
docker exec -it ... /bin/bash
ll
ls -l
curl localhost:9090
6、发布项目(由于做了卷挂载,直接在本地编写项目就可以发布)
cd /usr/ /test
mkdir WEB-INF
cd WEB-INF
vim web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
vim index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello.davina</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("......my test web logs ........ " );
%>
</body>
</html>
访问 localhost:9090/test
发现:项目部署成功,可以直接访问
我们以后的开发步骤:需要掌握Dockerfile的编写,之后的一切都是使用docker镜像来发布运行
发布到 DockerHub 上
1、地址 https://hub.docker.com/ 注册自己的账号
2、确定这个账号可以登录
3、在我们的服务器上提交镜像
docker login --help
docker login -u davina
4、提交自己的镜像
docker push davina/diytomcat:1.0
# push 镜像的问题
# 解决,增加一个 tag
docker tag [IMAGE ID] push davina/diytomcat:1.0
docker images
docker push davina/diytomcat:1.0
提交的时候,也是按照镜像的层级来提交的
发布到 阿里云上
1、登录阿里云
2、找到容器镜像服务
3、创建命名空间
4、创建容器镜像
5、浏览
清空所有环境
[root@k2 ~]# docker rm -f $(docker ps -aq)
3ef6f9de6ce9
a69d884b5f4b
[root@k2 ~]# docker rmi -f $(docker images -aq)
Untagged: nginx:latest
Untagged: nginx@sha256:2d17cc4981bf1e22a87ef3b3dd20fbb72c3868738e3f307662eb40e2630d4320
Deleted: sha256:de2543b9436b7b0e2f15919c0ad4eab06e421cecc730c9c20660c430d4e5bc47
Deleted: sha256:2deefd67059cad4693c3ec996e7db36c70b4b0aa77d6401ece78f7a6448a976c
Untagged: mysql:5.7
Untagged: mysql@sha256:16e159331007eccc069822f7b731272043ed572a79a196a05ffa2ea127caaf67
Deleted: sha256:2dfc45a2fa416c9a9d8e5eca5507872dce078db1512d7a88d97bfd77381b2e3c
[root@k2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@k2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
测试
三个网络
问题,docker 是如何处理容器网络访问的?
[root@k2 /]# docker run -d -P --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr , 发现容器启动的时候会得到一个 etho$if262 ip地址,docker分配的
[root@k2 /]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
..........
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
如果 ip addr 报错
[root@k2 /]# docker exec -it tomcat01 ip addr
OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown
[root@k2 /]# docker exec -it tomcat01 /bin/bash
root@c33985d3669a:/usr/local/tomcat#
root@c33985d3669a:/usr/local/tomcat# apt update && apt install -y iproute2
root@c33985d3669a:/usr/local/tomcat# exit
exit
# 思考,Linux 能不能ping通容器内部
[root@k2 /]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.029 ms
# Linux 可以,ping通docker容器内部
原理
1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,只要安装了docker,就会有一个网卡docker0 是桥接模式,使用的技术是evth-pair技术
再次测试 ip addr
[root@k2 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state
15: vethbc038f8@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
2、再启动一个容器测试,发现又多了一对网卡
[root@k2 /]# docker run -d -P --name tomcat02 tomcat
e8e8c66666666666665e05c8e3bd6db57f3
[root@k2 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state
15: vethbc038f8@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
17: vetha5232c9@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc
[root@k2 /]#
* 我们发现这个容器带来的网卡,都是一对一对的
* evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
* 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备
* OpenStac , Docker 容器之间的连接,OVS的连接,都是使用 evth-pair 技术
3、来测试下 Tomcat01 和Tomcat02 是否可以ping通
[root@k2 /]# docker exec -it tomcat02 ping 172.17.0.2
# 结论: 容器和容器之间可以互相ping
如果ping报错
[root@k2 /]# docker exec -it tomcat02 ping 172.17.0.2 OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown [root@k2 /]# docker exec -it tomcat02 /bin/bash root@e8e8cfbbcd61:/usr/local/tomcat# apt-get update && apt-get install iputils-ping Hit:1 http://deb.debian.org/debian bullseye InRelease Hit:2 http://deb.debian.org/debian bullseye-updates InRelease Hit:3 http://security.debian.org/debian-security bullseye-security InRelease Reading package lists... Done Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: iputils-ping 0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded. Need to get 49.8 kB of archives. After this operation, 116 kB of additional disk space will be used. Get:1 http://deb.debian.org/debian bullseye/main amd64 iputils-ping amd64 3:20210202-1 [49.8 kB] Fetched 49.8 kB in 0s (157 kB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package iputils-ping. (Reading database ... 12909 files and directories currently installed.) Preparing to unpack .../iputils-ping_3%3a20210202-1_amd64.deb ... Unpacking iputils-ping (3:20210202-1) ... Setting up iputils-ping (3:20210202-1) ... root@e8e8cfbbcd61:/usr/local/tomcat# exit exit [root@k2 /]# docker exec -it tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.072 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.038 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.042 ms [root@k2 /]#
绘制一个网络模型图
结论:tomcat01 和 tomcat02 是公用的一个路由器,docker0
~~~~~~
所有的容器不指定网络的情况下,都是docker0路由的,docker 会给容器分配一个默认的可用ip
小结
Docker 使用的是Linux的桥接,宿主机中是一个Docker容器的网络 Docker0
Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
只要容器删除,对应网桥一对就没了
思考一个场景,编写一个微服务,database url=ip; 项目不重启,数据库ip换掉了,希望可以处理这个问题,可以名字来访问容器
[root@k2 /]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何可以解决
# 通过 --link 就可以解决网络连接问题
[root@k2 /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
cb77a58df319ac2410355eb8153e4aaea2ed3c45a9b30d5de39f314b4b427346
[root@k2 /]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.077 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.045 ms
# 反向可以ping通吗?
[root@k2 /]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
其实 tomcat03就是在本地配置了Tomcat02的配置
# 查看 hosts 配置
[root@k2 /]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 e8e8cfbbcd61
172.17.0.4 cb77a58df319
本质探究:–link 就是我们在hosts配置中增加了一个 tomcat02映射
我们现在玩docker 已经不建议使用 --link 了
自定义网络,不适用 docker0
docker0 问题:不支持容器名连接访问
查看所有的docker网络
[root@k2 /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
29505cc77bbf bridge bridge local
b7c447beef3a host host local
09316664fa6e none null local
网络模式
bridge :桥接 docker (默认,自己搭建也使用bridge模式)
none : 不配置网络
host: 和宿主机共享网络
container:容器内网络连通
测试
[root@k2 /]# docker rm -f $(docker ps -aq)
9evgtgtge4514
[root@k2 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP>
3: docker0: <BROADCAST,MULTICAST,UP> mtu 1500
[root@k2 /]# docker run -d -P --name tomcat01 --net bridge tomcat
ad18666666666666e622241666666666666666
[root@k2 /]#
# 我们直接启动的命令 --net bridge ,这个就是我们的docker0 docker run -d -P --name tomcat01 tomcat docker run -d -P --name tomcat01 --net bridge tomcat # docker0 的特点:是默认的,域名不能访问, --link 可以打通连接 # 可以自定义一个网络 # --driver bridge # --subnet 192.168.0.0/16 # --gateway 192.168.0.1 [root@k2 /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet 74657fc8666666666666666abe68045561ed9 [root@k2 /]# docker network ls NETWORK ID NAME DRIVER SCOPE 29505cc77bbf bridge bridge local b7c447beef3a host host local 74657fc8f106 mynet bridge local 09316664fa6e none null local
自己的网络就创建好了
[root@k2 ~]# docker network inspect mynet [ { "Name": "mynet", "Id": "74657fc8f1666666666666661dabe68045561ed9", "Created": "2022-05-25T01:48:05.384514751+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16" "gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]
[root@k2 ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat fe44da6666666666666664063a4d730849e4 [root@k2 ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 9343d5f57666666666666666917db6666cc7bb5 [root@k2 ~]# docker network inspect mynet [ { "Name": "mynet", "Id": "7465766661dabe6666666666666661ed9", "Created": "2022-05-25T01:48:05.384514751+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16" "gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "9343d5f6666666666666cf3821ecc7bb5": { "Name": "tomcat-net-02", "EndpointID": "1384666666b80d6666669006b9268d9182571", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "fe44da666666666730849e4": { "Name": "tomcat-net-01", "EndpointID": "ffe7daf5666666666666ad80633e1", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
再次测试ping连接
[root@k2 ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.056 ms
不使用 --link,也可以ping名字
[root@k2 ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.042 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.057 ms
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐平时这样使用网络
好处:
Redis – 不同的集群使用不同的网络,保证集群是安全健康的
mysql – 不同的集群使用不同的网络,保证集群是安全健康的
[root@k2 ~]# docker run -d -P --name tomcat03 tomcat
d7a8b6666666666c053ca6666668273
[root@k2 ~]# docker run -d -P --name tomcat04 tomcat
c166666666625b121a66666666092cdb
[root@k2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c1a107b87899 tomcat "catalina.sh run" 7 seconds ago Up 6 seconds 0.0.0.0:49161->8080/tcp, :::49161->8080/tcp tomcat04
d7a8b82d1b95 tomcat "catalina.sh run" 11 seconds ago Up 11 seconds 0.0.0.0:49160->8080/tcp, :::49160->8080/tcp tomcat03
9343d5f57456 tomcat "catalina.sh run" 29 minutes ago Up 29 minutes 0.0.0.0:49159->8080/tcp, :::49159->8080/tcp tomcat-net-02
fe44da7e8adb tomcat "catalina.sh run" 30 minutes ago Up 30 minutes 0.0.0.0:49158->8080/tcp, :::49158->8080/tcp tomcat-net-01
[root@k2 ~]# docker exec -it tomcat03 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
# 测试打通 tomcat03 - mynet
[root@k2 ~]# docker network connect mynet tomcat03
# 连通之后就是将 tomcat03 放到 mynet 网络下
# 一个容器,两个ip地址:
# 比如阿里云服务器,一个公网ip,一个私网ip
[root@k2 ~]# docker network connect mynet tomcat03 [root@k2 ~]# docker network inspect mynet [ { "Name": "mynet", "Id": "74657fc86666666666e68045561ed9", "Created": "2022-05-25T01:48:05.384514751+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "9343d5f57456695e566666667bb5": { "Name": "tomcat-net-02", "EndpointID": "1384f2435fb80d745066666666d9182571", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "d7a8b82d1b956666666b996f9da4349c053ca1dd84f8273": { "Name": "tomcat03", "EndpointID": "0583fe2ffc6502adef3b766666666ec28761a63b0c6", "MacAddress": "02:42:c0:a8:00:04", "IPv4Address": "192.168.0.4/16", "IPv6Address": "" }, "fe44da7e8adb9616666666668eba22a34063a4d730849e4": { "Name": "tomcat-net-01", "EndpointID": "ffe7daf5853cb2b66666666666f1ad80633e1", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
# 03连通OK
[root@k2 ~]# docker exec -it tomcat03 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.080 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.056 ms
# 04 依然打不通
[root@k2 ~]# docker exec -it tomcat04 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
结论:假设要跨网络操作别人,就需要使用docker network connect 连通
shell脚本
# 创建网卡 docker network create redis --subnet 172.38.0.0/16 # 通过脚本创建六个redis配置 for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/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 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; docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ -v /mydata/redis/node-1/data:/data \ -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ -v /mydata/redis/node-6/data:/data \ -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; # 创建集群 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-rep licas 1
[root@k2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c1a107b87899 tomcat "catalina.sh run" 34 minutes ago Up 34 minutes 0.0.0.0:49161->8080/tcp, :::49161->8080/tcp tomcat04 d7a8b82d1b95 tomcat "catalina.sh run" 34 minutes ago Up 34 minutes 0.0.0.0:49160->8080/tcp, :::49160->8080/tcp tomcat03 9343d5f57456 tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:49159->8080/tcp, :::49159->8080/tcp tomcat-net-02 fe44da7e8adb tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:49158->8080/tcp, :::49158->8080/tcp tomcat-net-01 e06d18697809 tomcat "catalina.sh run" 17 hours ago Up 17 hours 0.0.0.0:49157->8080/tcp, :::49157->8080/tcp tomcat01 [root@k2 ~]# docker rm -f $(docker ps -aq) c1a107b87899 d7a8b82d1b95 9343d5f57456 fe44da7e8adb e06d18697809 [root@k2 ~]# docker network create redis --subnet 172.38.0.0/16 134b86666666695f576666666666beed [root@k2 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 29505cc77bbf bridge bridge local b7c447beef3a host host local 74657fc8f106 mynet bridge local 09316664fa6e none null local 134b8cc63439 redis bridge local [root@k2 ~]# docker network inspect redis [ { "Name": "redis", "Id": "134b8cc666666666666666d15c70d6beed", "Created": "2022-05-25T18:30:05.797037488+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.38.0.0/16" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] [root@k2 ~]# for port in $(seq 1 6); \ > do \ > mkdir -p /mydata/redis/node-${port}/conf > touch /mydata/redis/node-${port}/conf/redis.conf > cat << EOF >/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 [root@k2 ~]# cd /mydata/redis/ [root@k2 redis]# ls node-1 node-2 node-3 node-4 node-5 node-6 [root@k2 redis]# cd node-1/conf/ [root@k2 conf]# cat 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.11 cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes [root@k2 conf]# docker run -p 6371:6379 -p 16371:16379 --name redis-1 \ > -v /mydata/redis/node-1/data:/data \ > -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \ > -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; Unable to find image 'redis:5.0.9-alpine3.11' locally 5.0.9-alpine3.11: Pulling from library/redis cbdbe7a5bc2a: Pull complete dc0373118a0d: Pull complete cfd369fe6256: Pull complete 3e45770272d9: Pull complete 558de8ea3153: Pull complete a2c652551612: Pull complete Digest: sha256:83a3af3666664ba86ad966666e35d0 Status: Downloaded newer image for redis:5.0.9-alpine3.11 693f88a5f666666666611ea8a669d2494666666a900f [root@k2 conf]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 693f88a5f828 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 11 seconds ago Up 10 seconds 0.0.0.0:6371->6379/tcp, :::6371->6379/tcp, 0.0.0.0:16371->16379/tcp, :::16371->16379/tcp redis-1 ..... [root@k2 conf]# docker run -p 6376:6379 -p 16376:16379 --name redis-6 \ > -v /mydata/redis/node-6/data:/data \ > -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \ > -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; 51a543266666666666b3abf0 [root@k2 conf]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 51a54321333f redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 21 seconds ago Up 20 seconds 0.0.0.0:6376->6379/tcp, :::6376->6379/tcp, 0.0.0.0:16376->16379/tcp, :::16376->16379/tcp redis-6 d7a37b7e1e49 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up 59 seconds 0.0.0.0:6375->6379/tcp, :::6375->6379/tcp, 0.0.0.0:16375->16379/tcp, :::16375->16379/tcp redis-5 359020af8325 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6374->6379/tcp, :::6374->6379/tcp, 0.0.0.0:16374->16379/tcp, :::16374->16379/tcp redis-4 37e7191b1760 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6373->6379/tcp, :::6373->6379/tcp, 0.0.0.0:16373->16379/tcp, :::16373->16379/tcp redis-3 6d4da93dbfc3 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 0.0.0.0:6372->6379/tcp, :::6372->6379/tcp, 0.0.0.0:16372->16379/tcp, :::16372->16379/tcp redis-2 693f88a5f828 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 0.0.0.0:6371->6379/tcp, :::6371->6379/tcp, 0.0.0.0:16371->16379/tcp, :::16371->16379/tcp redis-1 [root@k2 conf]# docker exec -it redis-1 /bin/sh /data # ls appendonly.aof nodes.conf /data # 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-repl icas 1 Unrecognized option or bad number of args for: '-cluster' /data # 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-rep licas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 M: 7c7366666666641ae0dca 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: ef6666666666b4d5 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: d5d2666666dcbd39c 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: d966666666b18979c 172.38.0.14:6379 replicates d5d23736666666c7e9666bd39c S: 72588966666b44e 172.38.0.15:6379 replicates 7c73d5e6666666666666666dca S: 2a03a4d0db1aaa49c9e0003eb6b2831ec11b30ee 172.38.0.16:6379 replicates ef9977666666666d5 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ... >>> Performing Cluster Check (using node 172.38.0.11:6379) M: 7c7366666666666666666dca 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: ef66666666e266666666b4d5 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 2a03666666666666666630ee 172.38.0.16:6379 slots: (0 slots) slave replicates ef997769c6666666666666664d5 S: 72666666662666666666664e 172.38.0.15:6379 slots: (0 slots) slave replicates 7c73d6666666666666666666dca S: d9e06666666666666666679c 172.38.0.14:6379 slots: (0 slots) slave replicates d5d23666666666666666666669c M: d5666666666666666666d39c 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
进入集群,插数据
/data # redis-cli -c 127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:908 cluster_stats_messages_pong_sent:894 cluster_stats_messages_sent:1802 cluster_stats_messages_ping_received:889 cluster_stats_messages_pong_received:908 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:1802 127.0.0.1:6379> cluster nodes ef996666666fee6b4d5 172.38.0.12:6379@16379 master - 0 1653477040000 2 connected 5461-10922 2a03a4d066666661b30ee 172.38.0.16:6379@16379 slave ef9666666e6b4d5 0 1653477041517 6 connected 7c73d5e6666666dd66dca 172.38.0.11:6379@16379 myself,master - 0 1653477041000 1 connected 0-5460 7256666666d92f664e 172.38.0.15:6379@16379 slave 7c66661666660dca 0 1653477040717 5 connected d9e66666979c 172.38.0.14:6379@16379 slave d5d236666666d39c 0 1653477041000 4 connected d5d2666666bd39c 172.38.0.13:6379@16379 master - 0 1653477041724 3 connected 10923-16383 127.0.0.1:6379> set a b -> Redirected to slot [15495] located at 172.38.0.13:6379 OK
另开一个窗口,停了redis-3
[root@k2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51a54321333f redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 16 minutes ago Up 16 minutes 0.0.0.0:6376->6379/tcp, :::6376->6379/tcp, 0.0.0.0:16376->16379/tcp, :::16376->16379/tcp redis-6
d7a37b7e1e49 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 16 minutes ago Up 16 minutes 0.0.0.0:6375->6379/tcp, :::6375->6379/tcp, 0.0.0.0:16375->16379/tcp, :::16375->16379/tcp redis-5
359020af8325 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6374->6379/tcp, :::6374->6379/tcp, 0.0.0.0:16374->16379/tcp, :::16374->16379/tcp redis-4
37e7191b1760 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes 0.0.0.0:6373->6379/tcp, :::6373->6379/tcp, 0.0.0.0:16373->16379/tcp, :::16373->16379/tcp redis-3
6d4da93dbfc3 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 18 minutes ago Up 18 minutes 0.0.0.0:6372->6379/tcp, :::6372->6379/tcp, 0.0.0.0:16372->16379/tcp, :::16372->16379/tcp redis-2
693f88a5f828 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 24 minutes ago Up 24 minutes 0.0.0.0:6371->6379/tcp, :::6371->6379/tcp, 0.0.0.0:16371->16379/tcp, :::16371->16379/tcp redis-1
[root@k2 ~]# docker stop redis-3
redis-3
docker搭建Redis集群完成
172.38.0.13:6379> get a
^Z[1]+ Stopped redis-cli -c
/data # redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
172.38.0.14:6379> cluster nodes
2a66664d066666661b30ee 172.38.0.16:6379@16379 slave ef666666632410bd666664d5 0 1653477295000 6 connected
725866666925666666666e 172.38.0.15:6379@16379 slave 7c73d66666666666666666ca 0 1653477295280 5 connected
ef99766666666666666666 172.38.0.12:6379@16379 master - 0 1653477295000 2 connected 5461-10922
7c666666666666666666ca 172.38.0.11:6379@16379 master - 0 1653477296284 1 connected 0-5460
d56666666666666666d39c 172.38.0.13:6379@16379 master,fail - 1653477160569 1653477159000 3 connected
d9e0666666666666666666 172.38.0.14:6379@16379 myself,master - 0 1653477296000 7 connected 10923-16383
172.38.0.14:6379>
我们使用docker之后,所有的技术都会慢慢的变得简单起来
1、构建springboot项目
idea – Spring Initializr --下一步–Web (Spring Web)-- 完成
# 依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </dependency> </dependencies>
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello,davina";
}
}
运行后,查看网页
2、打包应用
3、编写dockerfile
# demo -- 新建 --文件-- Dockerfile 输入如下
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
# 上传到Linux里
[root@k2 ~]# cd /home/
[root@k2 home]# ls
[root@k2 home]# mkdir idea
[root@k2 home]# ll
总用量 0
drwxr-xr-x. 2 root root 6 5月 25 21:39 idea
[root@k2 home]# cd idea/
[root@k2 idea]# ll
总用量 18060
-rw-r--r--. 1 root root 18487524 5月 25 21:43 demo-0.0.1-SNAPSHOT.jar
-rw-r--r--. 1 root root 122 5月 25 21:43 Dockerfile
4、构建镜像
[root@k2 idea]# docker build -t davina . Sending build context to Docker daemon 18.49MB Step 1/5 : FROM java:8 8: Pulling from library/java 5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8b666618156666666669d Status: Downloaded newer image for java:8 ---> d23bdf5b1b1b Step 2/5 : COPY *.jar /app.jar ---> 814def847a05 Step 3/5 : CMD ["--server.port=8080"] ---> Running in c54e95b1fb61 Removing intermediate container c54e95b1fb61 ---> c8b5a40794dc Step 4/5 : EXPOSE 8080 ---> Running in cdee05e19fea Removing intermediate container cdee05e19fea ---> 9cce71680080 Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in 945e2c80dfd5 Removing intermediate container 945e2c80dfd5 ---> fe363d9a6ba4 Successfully built fe363d9a6ba4 Successfully tagged davina:latest [root@k2 idea]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE davina latest fe363d9a6ba4 18 seconds ago 662MB tomcat latest 5eb506608219 7 days ago 685MB redis 5.0.9-alpine3.11 3661c84ee9d0 2 years ago 29.8MB java 8 d23bdf5b1b1b 5 years ago 643MB
5、发布运行
[root@k2 idea]# docker run -d -P --name 66-springboot-web davina
10b66666666666666666666666666660b83
[root@k2 idea]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10b62dbb98ac davina "java -jar /app.jar …" 13 seconds ago Up 13 seconds 0.0.0.0:49163->8080/tcp, :::49163->8080/tcp 66-springboot-web
[root@k2 idea]# curl localhost:49163
{"timestamp":"2022-05-25T13:48:59.919+00:00","status":404,"error":"Not Found","path":"/"}[root@k2 idea]# curl localhost:49163/hello
hello,davina[root@k2 idea]#
我们使用docker之后,交付给别人一个镜像即可
------------------------------------------Docker 下半场----------------------------------------------
Docker
DockerFile build run 手动操作,单个容器
微服务,100个微服务,还有依赖关系
Docker Compose 轻松高效的管理容器,定义运行多个容器
官方介绍
https://docs.docker.com/compose/
定义和运行多个容器
YAML file 配置文件
single command 命令有哪些
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
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.
三个步骤:
1、 DockerFile 保证我们的项目在任何地方可以运行
2、 services 什么是服务
~~~~~~
docker-compose.yml 这个文件怎么写
3、启动项目
Using Compose is basically a three-step process:
Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
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官方的开源项目,需要安装
DockerFile 让程序在任何地方运行
docker-compose.yml 模板
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
docker-compose up 100个服务
compose:重要的概念
https://docs.docker.com/compose/install/
1、下载
curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# 这个可能快点
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.5.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
报错 curl: (35) Encountered end of file
[root@k2 ~]# DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} [root@k2 ~]# mkdir -p $DOCKER_CONFIG/cli-plugins # 下载报错 [root@k2 ~]# curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:02:00 --:--:-- 0 curl: (35) Encountered end of file # 1、查看防火墙状态 [root@k2 ~]# firewall-cmd --state not running # 2、开启防火墙 [root@k2 ~]# systemctl start firewalld.service # 再次查看防火墙状态 [root@k2 ~]# firewall-cmd --state running # 3、开启端口(以端口443为例) [root@k2 ~]# firewall-cmd --zone=public --add-port=443/tcp --permanent success # 4、重启防火墙 [root@k2 ~]# systemctl restart firewalld.service # 5、重新载入防火墙 [root@k2 ~]# firewall-cmd --reload success # 6、查看已开启的端口 [root@k2 ~]# firewall-cmd --list-ports 443/tcp # 再次下载 [root@k2 ~]# curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 25.2M 100 25.2M 0 0 3838k 0 0:00:06 0:00:06 --:--:-- 4797k
2、授权
sudo chmod +x /usr/local/bin/docker-compose
地址:https://docs.docker.com/compose/gettingstarted/
1、应用 app.py
2、Dockerfile 应用打包为镜像
3、docker-compose.yml 文件 (定义整个服务,需要的环境,比如:web、Redis)完整的上线服务
4、启动 compose 项目(docker-compose up)
[root@k2 bin]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 423 100 423 0 0 555 0 --:--:-- --:--:-- --:--:-- 555 100 16.7M 100 16.7M 0 0 4641k 0 0:00:03 0:00:03 --:--:-- 6810k [root@k2 bin]# cd /usr/local/bin/ [root@k2 bin]# ll 总用量 17176 -rw-r--r--. 1 root root 17586312 5月 28 00:55 docker-compose [root@k2 bin]# sudo chmod +x docker-compose [root@k2 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 [root@k2 bin]# cd /home/ [root@k2 home]# ll 总用量 0 drwxr-xr-x. 2 root root 88 5月 28 00:55 composetest [root@k2 home]# cd composetest/ [root@k2 composetest]# cat app.py 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) [root@k2 composetest]# cat requirements.txt flask redis [root@k2 composetest]# cat Dockerfile # 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"] [root@k2 composetest]# cat docker-compose.yml version: "3" services: web: build: . ports: - "8000:5000" redis: image: "redis:alpine" [root@k2 composetest]# ll 总用量 16 -rw-r--r--. 1 root root 514 5月 28 01:01 app.py -rw-r--r--. 1 root root 109 5月 28 01:04 docker-compose.yml -rw-r--r--. 1 root root 281 5月 27 19:05 Dockerfile -rw-r--r--. 1 root root 12 5月 27 19:04 requirements.txt [root@k2 composetest]# docker-compose up [root@k2 composetest]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0b66dd46c747 redis:alpine "docker-entrypoint.s…" 2 days ago Up 2 days 6379/tcp composetest_redis_1 0b9e54ee12f6 composetest_web "flask run" 2 days ago Up 2 days 0.0.0.0:8000->5000/tcp, :::8000->5000/tcp composetest_web_1 [root@k2 composetest]# curl localhost:8000 Hello World! I have been seen 1 times. [root@k2 composetest]# curl localhost:8000 Hello World! I have been seen 2 times. [root@k2 composetest]# curl localhost:8000 Hello World! I have been seen 3 times. [root@k2 composetest]# curl localhost:8000 Hello World! I have been seen 4 times.
报错
Creating network "composetest_default" with the default driver
ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-88260d8bd489 -j RETURN: iptables: No chain/target/match by that name.
(exit status 1))
原因是关闭防火墙之后docker需要重启,执行以下命令重启docker即可
[root@k2 composetest]# service docker restart
docker ps
如果启动的只有一个,或者没有,重新启动
docker-compose build
docker-compose up
docker ps
流程:
1、创建网络 Creating network
2、执行 docker-compose.yml
3、启动服务
docker-compose.yml
Creating composetest_web_1 … done
Creating composetest_redis_1 … done
1、文件名 composetest
2、服务
docker images
[root@k2 composetest]# docker service ls
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
3、网络规则
10个服务 => 项目(项目中的内容都在同个网络下,域名访问)
[root@k2 ~]# docker network inspect composetest_default
如果在同一个网络下,我们可以直接通过域名访问 HA
停止(在当前文件composetest目录下):
docker-compose stop 或者 ctrl+c
以前都是单个 docker run 启动容器
docker-compose ,通过docker-compose 编写yaml配置文件,可以通过compose 一键启动所有服务,停止
快速开始
通过docker compose 上构建一个简单的python web 应用程序,该应用程序使用flask框架并在Redis中维护一个计数器,用来记录该web应用被访问的次数
1、准备工作
yum install python-pip # pip 是 python 包管理工具
yum -y install epel-release # 报错的话执行
2、为项目创建目录
mkdir composetest
cd composetest
3、在项目目录中创建另一个名为 app.py 的文件
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)
在本例中,Redis是应用程序网络上Redis容器的主机名,我们使用Redis的默认端口6379
4、在项目目录中创建另一个名为requirements.txt 的文件,内容
flask
redis
5、在项目目录中创建另一个名为Dockerfile 的文件
FROM python:3.7-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
# 这告诉docker
从python:3.7 映像开始构建映像
将当前目录添加到 /code 映像中的路径中
将工作目录设置为 /code
安装 python 依赖项
将容器的默认命令设置为 python,app.py
6、在项目目录中创建另一个名为docker-compose.yml 的文件
version: "3"
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
redis:
image: "redis:alpine"
# 此compose文件定义了两个服务,web和Redis
使用从Dockerfile 当前目录中构建的图像
将容器上的公开端口5000 转发到主机上的端口8000。 我们使用flack web 服务器的默认端口5000
该Redis服务使用从 docker hub 注册表中提取的公共Redis映像
7、使用compose构建和运行应用程序,在项目目录中,通过运行 docker-compose up 启动应用程序
docker-compose up
8、查看
docker ps
9、访问
curl localhost:8000
默认的服务名是:文件名_服务名_num
多个服务器 ,集群模式 , _num 是副本数量
启动服务,比如Redis服务 => 4个副本
未来是集群状态,服务都不可能只有一个运行实例,都会是弹性的,10个副本,都可用 HA 高并发
kubectl service 负载均衡
docker 小结:
1、docker 镜像,run=> 容器
2、dockerfile 构建镜像(服务打包)
3、docker-compose 启动项目(编排、多个微服务/环境)
4、docker 网络
yaml 规则
https://docs.docker.com/compose/compose-file/compose-file-v3/
yaml 是docker-compose 的核心
# 只有3层 version: "" # 版本 services: # 服务 服务1:web # 服务配置 images build network .... 服务2:redis .... 服务3:redis .... # 其他配置 网络/卷、全局规则 volumes: networks: configs:
博客
下载程序、安装数据库、配置 …
compose 应用 => 一键启动
1、下载项目(docker-compose.yml)
2、如果想要文件:dockerfile
3、文件准备齐全(直接一键启动项目)
https://docs.docker.com/samples/wordpress/
[root@k2 home]# cd /home/my_wordpress/ [root@k2 my_wordpress]# ll 总用量 4 -rw-r--r--. 1 root root 641 5月 30 22:50 docker-compose.yml [root@k2 my_wordpress]# cat docker-compose.yml version: "3.3" 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: - "8001:80" restart: always environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: db_data: {} wordpress_data: {} [root@k2 my_wordpress]# docker-compose up 网页访问 http://localhost:8001/
前面是,前台启动
后台启动
docker -d
docker-compose up -d
掌握:docker 基础,原理,网络,服务,集群模式,错误排查,日志查看
Linux docker k8s
idea – Spring Initializr – Web(Spring Web),NoSQL(Spring Data Redis(Access+Driver))
1、编写项目微服务
# 1、编写HelloController package com.example.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @Autowired StringRedisTemplate RedisTemplate; @GetMapping("/hello") public String hello(){ Long views = RedisTemplate.opsForValue().increment("views"); return "hello,davina,views:"+views; } } # 2、编写application.properties server.port=8080 spring.redis.host=redis
2、dockerfile构建镜像
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
3、docker-compose.yml 编排项目
version: '3.3'
services:
davinaapp:
build: .
image: davinaapp
depends_on:
- redis
ports:
- "8080:8080"
redis:
image: "library/redis:alpine"
打jar包
4、丢到服务器
[root@k2 weifuwu]# ll
总用量 27048
-rw-r--r--. 1 root root 27686082 5月 31 00:13 demo1-0.0.1-SNAPSHOT.jar
-rw-r--r--. 1 root root 185 5月 31 00:13 docker-compose.yml
-rw-r--r--. 1 root root 120 5月 31 00:13 Dockerfile
[root@k2 weifuwu]# docker-compose up
http://ip:8080/hello
假设项目要重新部署打包
docker-compose up --build # 重新构建
小结:
未来公司只要有 docker-compose 文件,按照这个规则,启动编排容器
公司: docker-compose ,直接启动
网上开源项目:docker-compose 一键搞定
总结:
工程、服务、容器
项目 compose :三层
集群方式去部署,4台阿里云服务器, 2核 4g
和单机安装一样
技巧:shell同步操作(安装docker,配置阿里云镜像加速)
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.
If you haven’t already, read through the swarm mode overview and key concepts.
docker swarm init --advertise-addr ip初始化节点 docker swarm initdocker swarm join 加入一个节点
# 获取令牌
docker swarm join-token manager
docker swarm join-token worker
[root@k1 ~]# docker swarm init --advertise-addr 192.168.12.30 Swarm initialized: current node (twa2sqmjfhjf9ct4tve0s1c2f) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-3zscv60kuxs1w73666666666gtlfz8k 192.168.12.30:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. [root@k2 ~]#docker swarm join --token SWMTKN-1-3zscv60kuxs1w73666666666gtlfz8k 192.168.12.30:2377 This node joined a swarm as a worker. [root@k3 ~]# docker swarm join --token SWMTKN-1-3zscv60kuxs1w73666666666gtlfz8k 192.168.12.30:2377 This node joined a swarm as a worker. [root@k1 ~]# docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-3zscv6666666666666666ofit8j1a8666wvs 192.168.12.30:2377 [root@k4 ~]# docker swarm join --token SWMTKN-1-3zscv6666666666666666ofit8j1a8666wvs 192.168.122.30:2377 This node joined a swarm as a manager. [root@k1 ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION tw66666666s1c2f * k1 Ready Active Leader 20.10.16 twi666666s88fv4ai k2 Ready Active 20.10.16 xkd66666665aefh k3 Ready Active 20.10.16 4dh66666666e55y k4 Ready Active Reachable 20.10.16
1、生成主节点 init
2、加入(管理者、worker)
目标:双主双从
双主双从:假设一个节点挂了,其他节点是否可以用
Raft协议:保证大多数节点存活才可以用 >1 集群至少>3台
实验:
1、将docker1机器停止,宕机。双主,另一个主节点也不能使用
[root@k1 ~]# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
[root@k1 ~]#
[root@k4 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@k4 ~]# docker swarm join --token SWMTKN-1-3zsc33333u666666666j1a8e86d69jcowuwvs 192.168.12.30:2377
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
[root@k4 ~]# docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
[root@k1 ~]# systemctl start docker
[root@k1 ~]# docker node ls
2、可以将其他节点离开
[root@k2 ~]# docker swarm leave
Node left the swarm.
[root@k2 ~]#
[root@k1 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
tw66666666661c2f * k1 Ready Active Reachable 20.10.16
tw666666688fv4ai k2 Down Active 20.10.16
xk6666666666aefh k3 Ready Active 20.10.16
4dh666666665e55y k4 Ready Active Leader 20.10.16
[root@k1 ~]#
3、work就是工作的、管理节点操作,3台机器设置为了管理节点
[root@k1 ~]# docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-3zs6666666jcowuwvs 192.168.12.30:2377 [root@k2 ~]# docker swarm join --token SWMTKN-1-3zs6666666jcowuwvs 192.168.12.30:2377 This node joined a swarm as a manager. [root@k2 ~]# [root@k2 ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION tw6666666666666c2f k1 Ready Active Reachable 20.10.16 oyhx1v66666666660c * k2 Ready Active Reachable 20.10.16 twij666666668fv4ai k2 Down Active 20.10.16 xk666666666666aefh k3 Ready Active 20.10.16 4dh66666666666655y k4 Ready Active Leader 20.10.16 [root@k3 ~]# docker node ls Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager. 您在 /var/spool/mail/root 中有新邮件 [root@k3 ~]# [root@k1 ~]# systemctl stop docker Warning: Stopping docker.service, but it can still be activated by: docker.socket [root@k4 ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION twa2sqmjfhjf9ct4tve0s1c2f k1 Down Active Unreachable 20.10.16 oyhx1v4hmd9vo6w2czlo6m50c k2 Ready Active Unreachable 20.10.16 twijgssgk6ubkn6w6s88fv4ai k2 Down Active 20.10.16 xkd6pfurmecsrzpdjjqx5aefh k3 Ready Active 20.10.16 4dhqjmcdjwrt1vjwla685e55y * k4 Ready Active Leader 20.10.16 [root@k4 ~]# [root@k2 ~]# systemctl stop docker Warning: Stopping docker.service, but it can still be activated by: docker.socket [root@k4 ~]# docker node ls Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded [root@k4 ~]#
十分简单:集群,可用,3个主节点 >1台管理节点存活
Raft协议:保证大多数节点存活才可以用 高可用
弹性,扩缩容 ,集群
以后告别 docker run
docker-compose up 启动一个项目 ,单机
集群: swarm docker service
容器 => 服务
redis = 3份 ,容器
集群:高可用 , web -> redis (3台,不同的机器上)
体验:创建服务,动态扩展服务,动态更新服务
灰度发布,金丝雀发布
docker run 容器启动,不具有扩缩容性
docker service 服务, 具有扩缩容性 , 滚动更新
查看服务
[root@k1 ~]# docker service create -p 8888:80 --name my-nginx nginx
[root@k1 ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
1o66663bt my-nginx.1 nginx:latest k2 Running Running 22 hours ago
[root@k1 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
0f26666kr my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
[root@k2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a766669df nginx:latest "/docker-entrypoint.…" 22 hours ago Up 22 hours 80/tcp my-nginx.1.1o7ayjvgj3bteh9zsr5bgl20r
[root@k2 ~]#
[root@k1 ~]# docker service inspect my-nginx
动态扩缩容
[root@k1 ~]# docker service update --replicas 3 my-nginx my-nginx overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged # 四个节点,有一个docker ps,没东西,不影响网页访问 [root@k1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ae02e89974d7 nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp my-nginx.2.fd55b58a3lsq6jf2jeendfid3 [root@k1 ~]# [root@k2 ~]# docker ps [root@k3 ~]# docker ps [root@k4 ~]# docker ps # 网页访问: ip:8888/ (4个的ip都可以访问)
只要是一个服务,可以在集群中的任意节点访问。服务可以有多个节点,动态扩缩容,实现高可用
弹性 ,扩缩容
[root@k1 ~]# docker service update --replicas 10 my-nginx my-nginx overall progress: 10 out of 10 tasks 1/10: running [==================================================>] 2/10: running [==================================================>] 3/10: running [==================================================>] 4/10: running [==================================================>] 5/10: running [==================================================>] 6/10: running [==================================================>] 7/10: running [==================================================>] 8/10: running [==================================================>] 9/10: running [==================================================>] 10/10: running [==================================================>] verify: Service converged 您在 /var/spool/mail/root 中有新邮件 [root@k2 ~]# docker ps [root@k3 ~]# docker ps [root@k4 ~]# docker ps [root@k1 ~]# docker service update --replicas 1 my-nginx my-nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged [root@k2 ~]# docker ps [root@k3 ~]# docker ps [root@k4 ~]# docker ps
另一种扩缩容,更新副本数方式
[root@k2 ~]# docker service scale --help [root@k1 ~]# docker service scale my-nginx=5 my-nginx scaled to 5 overall progress: 5 out of 5 tasks 1/5: running [==================================================>] 2/5: running [==================================================>] 3/5: running [==================================================>] 4/5: running [==================================================>] 5/5: running [==================================================>] verify: Service converged [root@k1 ~]# docker service scale my-nginx=2 my-nginx scaled to 2 overall progress: 2 out of 2 tasks 1/2: running [==================================================>] 2/2: running [==================================================>] verify: Service converged
移除服务
[root@k1 ~]# docker service --help Usage: docker service COMMAND Manage services Commands: create Create a new service inspect Display detailed information on one or more services logs Fetch the logs of a service or task ls List services ps List the tasks of one or more services rm Remove one or more services rollback Revert changes to a service's configuration scale Scale one or multiple replicated services update Update a service Run 'docker service COMMAND --help' for more information on a command. [root@k1 ~]# docker service rm my-nginx my-nginx [root@k1 ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS
docker swarm 并不难,只要会搭建集群、启动服务、动态管理容器就可以
swarm
集群的管理和编号。docker可以初始化一个swarm集群,其他节点可以加入。(管理,工作者)
node
就是一个docker节点。多个节点就组成了一个网络集群。(管理,工作者)
service
就是一个任务。可以在管理节点或者工作节点运行。是核心。用户访问的是它。创建跟 docker run 一样
task
容器内的命令,一个细节任务
swarm 特点
1、docker engine 集成集群管理
使用docker engine cli 创建一个 docker engine 的swarm模式,在集群中部署应用程序服务
2、去中心化设计
swarm角色分为 manager 和worker 节点,manager节点故障不影响应用使用
3、扩容缩容
可以声明每个服务运行的容器数量,通过添加或删除容器数自动调整期望的状态
4、期望状态协调
swarm manager 节点不断监视集群状态,并调整当前状态和期望状态之间的差异。例如设置一个服务运行10个副本容器,如果两个副本的服务器节点崩溃,manager将创建两个
新的副本替代崩溃的副本,并将新的副本分配到可用的worker节点
5、多主机网络
可以为服务指定overlay网络,当初始化或者更新应用程序时,swarm manager 会自动为 overlay网络上的容器分配ip地址
6、服务发现
swarm manager 节点为集群中的每个服务分配唯一的DNS记录和负载均衡VIP。可以通过swarm内置的DNS服务器查询集群中每个运行的容器
7、负载均衡
实现服务副本负载均衡,提供入口访问。也可以将服务入口暴露给外部负载均衡器,再次负载均衡
8、安全传输
swarm 中的每个节点使用TLS相互验证和加密,确保安全的其他节点通信
9、滚动更新
升级时,逐步将应用更新到节点。如果出现问题,可以将任务回滚到先前版本
命令 ->管理 -> API -> 调度-> 工作节点(创建task容器)
服务副本与全局服务
调整service以什么方式运行
我们刚刚所有的服务都是随机分配的,我们的工作节点和我们的manageer节点都可以跑服务。但是我们的服务分为两种,一种是全局可以跑的service,还有一种是只能在副本上跑的service。全局的我们在任意节点都可以跑,但是工作节点,智能在我们的工作节点上跑。主要是通过命令的方式来进行操作的
--mode string
Service mode(replicated or global)(default "replicated")
docker service create --mode replicated --name mytom tomcat:8 #默认的方式
docker service create --mode global --name haha alphine ping baidu.com #指定方式执行
每个节点都有自己的日志收集器,过滤,把所有日志最终再传给日志中心,服务监控,状态性能
扩展:网络模式 “publishMode”:”ingress”
Swarm有三种网络模式:
overlay:在一个集群当中,即使我们跨机器,也可以把他集中起来。
ingress:特殊的overlay网络!具有负载均衡的功能,IPVS VIP
这个docker ingress就是我们的swarm的网络
[root@k1 ~]# docker network inspect ingress
docker-compose单机部署项目
Docker stack部署,集群部署
#单机
docker-compose up -d wordpress.yaml
#集群
docker stack deploy
# docker-compose 文件,使用dockerstack案例
安全 ,配置密码,。证书等等
配置
学习方式:网上找案例,跑起来,看帮助文档
k8s 10台机器以上
学习Go语言,是并发语言
docker 是go开发
k8s 是go 的项目
etcd 是go 的项目
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。