Docker入门
Docker能做什么
虚拟机技术:
虚拟机技术缺点:
- 资源占用十分多
- 冗余步骤多
- 启动很慢
容器化技术
容器化技术不是模拟的一个完整的操作系统。
比较Docker 和 虚拟机技术不用:
- 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在 宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件。所以就轻便了。
- 每个容器间是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响。
DecOps(开发、运维)
-
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
-
更便捷的升级和扩缩容
使用Docker之后,我们部署应用就和搭积木一样!
项目打包为一个镜像,(可以理解为一个应用,带着环境能直接跑起来),扩展 服务器A! 直接在服务器B上一键运行即可。
-
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的
-
更高效的计算资源利用
Docker 是 内核级别的虚拟化,可以在一个物理机上能运行很多的容器实例!服务器的性能可以被压着到极致!
Docker安装
Docker基本组成
![Docker架构图](https://i-blog.csdnimg.cn/blog_migrate/58c782a980cb005060ef392c6d8f3de6.png)
镜像(image):
docker镜像就好比一个模版,可以通过这个模版来创建容器服务,例:tomcat镜像 = == >run ===>tomcat01容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
容器(container):
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。
启动、停止、删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统。
仓库(repository):
仓库是存放镜像的地方!
仓库分为共有仓库和私有仓库!
Docker Hub(默认是国外的)
阿里云…都有容器服务(配置镜像加速!)
安装Docker
环境查看
#系统内核
root@ecs-7ed1:~# uname -r
4.15.0-136-generic
# 系统版本
root@ecs-7ed1:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
安装
帮助文档:
示例Ubuntu
# 1.卸载旧的版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 2.安装 apt 依赖包,用于通过HTTPS来获取仓库:
apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# 3.添加Docker官方GPG key
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add - #(阿里云版本)
# 4.验证key的指纹
sudo apt-key fingerprint 0EBFCD88
# 5.设置稳定版仓库repository
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"
# 更新apt包索引
sudo apt-get update
# 6.安装最新版的docker ce和containerd ce是社区版 ee是企业版
sudo apt-get install docker-ce docker-ce-cli containerd.io
#查看文档,可安装指定版本
# 7.查看docker版本
docker --version
# 8.测试hello-world
docker run hello-world
测试hello-world 结果:
1)不能找到hello-world镜像;2)pull拉取;3)拉取完成;4)运行hello-world
# 查看一下下载的hello-world镜像
root@ecs-7ed1:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
了解:下载docker
# 1.卸载依赖
sudo apt-get purge docker-ce docker-ce-cli containerd.io
# 2.删除镜像
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
# /var/lib/docker docker的默认工作路径
回顾hello-world流程
底层原理
Docker是怎么工作的?
Docker是一个Client - Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!
Docker-Server接收到Docker-Client的指令,就会执行这个命令!
Docker为什么比虚拟机VM快?
-
Docker有着比虚拟机更少的抽象层。
Hypervisor(虚拟机监视器),是运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件。
-
docker利用的是宿主机的内核,vm需要是Guest OS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,是分钟级别的,而==docker是利用宿主机的操作系统==,省略了这个复杂的过程,秒级!
现在GuestOS 支持所有系统
Docker的常用命令
帮助命令
docker version #显示docker的版本信息
docker info #显示docker
docker 命令 --help #
帮助文档地址:https://docs.docker.com/reference/
镜像命令
docker images 查看所有本地的主机上的镜像
root@ecs-7ed1:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像的ID
docker search 搜索镜像
root@ecs-7ed1:~# docker search mysql
NAME DESCRIPTION STARS O FFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11299 [ OK]
mariadb MariaDB Server is a high performing open sou… 4291 [ OK]
# 可选项,通过收藏来过滤
root@ecs-7ed1:~# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11299 [OK]
mariadb MariaDB Server is a high performing open sou… 4291 [OK]
docker pull 下载镜像
#下载镜像 docker pull 镜像名[:tag]
root@ecs-7ed1:~# docker pull mysql
Using default tag: latest #如果不写 tag ,默认就是latest。(最新的,tag是版本号)
latest: Pulling from library/mysql
e1acddbe380c: Pull complete #分层下载,docker image的核心 联合文件系统
bed879327370: Pull complete
03285f80bafd: Pull complete
ccc17412a00a: Pull complete
1f556ecc09d1: Pull complete
adc5528e468d: Pull complete
1afc286d5d53: Pull complete
6c724a59adff: Pull complete
0f2345f8b0a3: Pull complete
c8461a25b23b: Pull complete
3adb49279bed: Pull complete
77f22cd6c363: Pull complete
Digest: sha256:d45561a65aba6edac77be36e0a53f0c1fba67b951cb728348522b671ad63f926 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# 下面两个命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest #通过真实地址pull
#指定版本下载————版本根据docker hub中的所含版本,不能随意填写
root@ecs-7ed1:~# docker pull mysql:5.7
5.7: Pulling from library/mysql
e1acddbe380c: Already exists #表示已经存在
bed879327370: Already exists
03285f80bafd: Already exists
ccc17412a00a: Already exists
1f556ecc09d1: Already exists
adc5528e468d: Already exists
1afc286d5d53: Already exists
4d2d9261e3ad: Pull complete #新下载文件
ac609d7b31f8: Pull complete
53ee1339bc3a: Pull complete
b0c0a831a707: Pull complete
Digest: sha256:7cf2e7d7ff876f93c8601406a5aa17484e6623875e64e7acc71432ad8e0a3d7e
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像!
root@ecs-7ed1:~# docker rmi -f 容器id #删除指定的镜像
root@ecs-7ed1:~# docker rmi -f 容器id 容器id 容器id 容器id #删除多个指定镜像
root@ecs-7ed1:~# docker rmi -f $(docker images -ap) #删除全部的镜像
容器命令
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
--name='Name' #容器名字 tomcat01 tomcat02 , 用来区分容器
-d #后台方式运行
-i
-t #使用交互方式运行,进入容器查看内容。一般使用 -it
-p #指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
容器端口
-P 随机指定端口
# 测试,启动并进入容器
root@ecs-7ed1:~# docker run -it centos /bin/bash #shell程序bash??
[root@35ace831db17 /]# ls #查看容器内的centos,基础版本,很多命令都是不完善的!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#从容器中退出主机
[root@35ace831db17 /]# exit
exit
root@ecs-7ed1:~# ls
cmake-3.9.2 GolangStudy mysql-8.0.24 TinyWebServer
cmake-3.9.2.tar.gz gowork mysql-apt-config_0.8.10-1_all.deb webserver
go hello.go oasys_mysql
go1.16.7.linux-amd64.tar.gz maven oasys_mysql.sql
列出所有的运行容器
#docker ps 命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的n个容器
-q #只显示容器的编号
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@ecs-7ed1:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
35ace831db17 centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago hardcore_matsumoto
3f161b15937c hello-world "/hello" 24 hours ago Exited (0) 24 hours ago quirky_johnson
退出容器
exit #直接容器停止并退出。。。。。exit应该是终止没有前台程序的容器
Ctrl + P + Q #容器不停止退出
删除容器
docker rm 容器id #删除指定容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm -f $(docker ps -aq) #删除所有容器
docker ps -a -q | xargs docker rm #删除所有容器
启动和停止容器的操作
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
常用其他命令
后台启动容器
# 命令 docker run -d 镜像名
root@ecs-7ed1:~# docker run -d centos
#问题 docker ps,发现 centos 停止了
#常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
#nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
docker logs -f -t --tail 容器,没有日志
#自己编写一段shell脚本
root@ecs-7ed1:~# docker run -d centos /bin/sh -c "while true;do echo qiuzhiming;sleep 1;done"
#查看id
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb5718858632 centos "/bin/sh -c 'while t…" 3 seconds ago Up 2 seconds condescending_perlman
#显示日志
#--tail number 显示的日志条数
#-t 时间戳
#-f 是跟踪日志输出,相当于实时显示
root@ecs-7ed1:~# docker logs -t -f --tail 10 fb5718858632
2021-08-31T13:01:08.087901329Z qiuzhiming
2021-08-31T13:01:09.089473375Z qiuzhiming
2021-08-31T13:01:10.089974061Z qiuzhiming
2021-08-31T13:01:11.091694770Z qiuzhiming
2021-08-31T13:01:12.093801482Z qiuzhiming
2021-08-31T13:01:13.095234152Z qiuzhiming
查看容器中的进程信息
#docker top 容器id
root@ecs-7ed1:~# docker top fb5718858632
UID PID 当前进程id PPID 父进程id C STIME TTY TIME CMD
root 16796 16768 0 20:58 ? 00:00:00 /bin/sh -c while true;do echo qiuzhiming;sleep 1;done
root 20397 16796 0 21:51 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
#docker inspect 容器id
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令-方式一
docker exec -it 容器id bashshell
#测试
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb5718858632 centos "/bin/sh -c 'while t…" 12 hours ago Up 12 hours condescending_perlman
c9cd446d4fb4 centos "/bin/bash" 12 hours ago Up 12 hours lucid_jennings
root@ecs-7ed1:~# docker exec -it c9cd446d4fb4 /bin/bash
[root@c9cd446d4fb4 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 方式二
docker attach 容器id
#docker exec #进入容器开启一个新的终端,可以在里面操作(常用)
#docker attach #进入容器正在执行的终端,不会启动新的进程!如果进入的容器没有正在运行脚本,则效果和docker exec相同
#测试,第一次进入的容器后台无运行脚本,第二次进入的容器后台不停的在运行脚本。
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb5718858632 centos "/bin/sh -c 'while t…" 12 hours ago Up 12 hours condescending_perlman
c9cd446d4fb4 centos "/bin/bash" 13 hours ago Up 13 hours lucid_jennings
root@ecs-7ed1:~# docker attach c9cd446d4fb4
[root@c9cd446d4fb4 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@c9cd446d4fb4 /]# read escape sequence # 退出容器终端 Ctrl+P+Q
root@ecs-7ed1:~# docker attach fb5718858632
qiuzhiming
qiuzhiming
qiuzhiming
...
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
#测试。只要容器在,数据就在,和它正在运行与否无关
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9cd446d4fb4 centos "/bin/bash" 13 hours ago Up 13 hours lucid_jennings
root@ecs-7ed1:~# docker attach c9cd446d4fb4
[root@c9cd446d4fb4 home]# ls
[root@c9cd446d4fb4 home]# touch test.cpp
[root@c9cd446d4fb4 home]# ls
test.cpp
[root@c9cd446d4fb4 home]# exit
exit
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@ecs-7ed1:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9cd446d4fb4 centos "/bin/bash" 13 hours ago Exited (0) 12 seconds ago lucid_jennings
root@ecs-7ed1:~# pwd
/root
root@ecs-7ed1:~# ls
root@ecs-7ed1:~# docker cp c9cd446d4fb4:/home/test.cpp /root
root@ecs-7ed1:~# ls
test.cpp
# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现自动同步
小节
root@ecs-7ed1:~# docker --help
attach Attach local standard input, output, and error streams to a running container #当前shell下 attach 连接指定运行镜像
build Build an image from a Dockerfile #通过 Dockrfile 定制镜像
commit Create a new image from a container's changes #提交当前容器为新的镜像
cp Copy files/folders between a container and the local filesystem #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container #创建一个新的容器,同run,但不启动容器
diff Inspect changes to files or directories on a container's filesystem #查看 docker 容器变化
events Get real time events from the server #从 docker 服务获取容器实时事件
exec Run a command in a running container # 在已存在的容器上运行命令
export Export a container's filesystem as a tar archive # 导出容器的内容流作为一个tar归档文件[对应 import ]
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Import the contents from a tarball to create a filesystem image # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on Docker objects # 查看容器详细信息
kill Kill one or more running containers # kill指定容器
load Load an image from a tar archive or STDIN # 从一个tar包中加载一个镜像
login Log in to a Docker registry # 注册或者登陆一个 docker 源服务器
logout Log out from a Docker registry # 从当前 docker registry 退出
logs Fetch the logs of a container # 输出当前容器日志信息
pause Pause all processes within one or more containers # 暂停服务器
port List port mappings or a specific mapping for the container # 查看映射端口对应的容器内部源端口
ps List containers # 列出容器列表
pull Pull an image or a repository from a registry # 从镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to a registry # 推送指定镜像或者库镜像至docker源服务器
rename Rename a container # 重命名容器
restart Restart one or more containers # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或者多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save one or more images to a tar archive (streamed to STDOUT by default) # 保存一个镜像为一个 tar包[对应load]
search Search the Docker Hub for images #在docker hub中搜索镜像
start Start one or more stopped containers # 启动容器
stats Display a live stream of container(s) resource usage statistics # 显示容器资源使用信息
stop Stop one or more running containers #停止容器
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE # 给源中镜像打标签
top Display the running processes of a container # 查看容器中运行的进程信息
unpause Unpause all processes within one or more containers # 取消暂停容器
update Update configuration of one or more containers #更新容器配置
version Show the Docker version information # 查看docker版本号
wait Block until one or more containers stop, then print their exit codes # 截取容器停止时的退出状态值
作业练习
部署nginx
# 搜索镜像 search ,建议去官网docker hub上搜索,可以查看详细信息
# 下载镜像 pull
root@ecs-7ed1:~# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Already exists
e21006f71c6f: Pull complete
f3341cc17e58: Pull complete
2a53fa598ee2: Pull complete
12455f71a9b5: Pull complete
b86f2ba62d17: Pull complete
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
# 查看镜像
root@ecs-7ed1:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest dd34e67e3371 2 weeks ago 133MB
mysql latest 5a4e492065c7 2 weeks ago 514MB
hello-world latest d1165f221234 5 months ago 13.3kB
centos latest 300e315adb2f 8 months ago 209MB
# 运行镜像 -d后台运行,--name 命名, -p 暴露端口号,3344:80(宿主机端口:容器内部端口)打通宿主机与容器
root@ecs-7ed1:~# docker run -d --name nginx01 -p 3344:80 nginx
809eebe3695a2a14a84f37a6111da4c40dfeed135f3b4a04b976a2f63148dbea
#查看运行的容器
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
809eebe3695a nginx "/docker-entrypoint.…" 4 seconds ago Up 4 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
#测试,使用3344可以访问成功
root@ecs-7ed1:~# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
端口暴露
外部公网可以访问
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
809eebe3695a nginx "/docker-entrypoint.…" 14 minutes ago Up 14 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 进入容器
root@ecs-7ed1:~# docker exec -it nginx01 /bin/bash
# 查一下nginx在哪
root@809eebe3695a:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
# 进入目录
root@809eebe3695a:/# cd /etc/nginx
root@809eebe3695a:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
# 退出
root@809eebe3695a:/etc/nginx# exit
exit
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
809eebe3695a nginx "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 停止
root@ecs-7ed1:~# docker stop 809eebe3695a
809eebe3695a
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
思考:每次改动nginx配置文件,都需要进入容器内部,十分麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改?-v 数据卷技术!
部署tomcat
# 下载镜像
docker pull tomcat
# 运行镜像
docker run -d -p 3344:8080 --name tomcat01 tomcat
#此时用 IP:3344 测试访问成功但是无内容显示。而且缺少部分linux命令
# 这是阿里云镜像的原因:默认使用最小镜像,所有不必要的都剔除了,保证最小可运行环境
#进入容器,查看webapps中无内容
root@ecs-7ed1:~# docker exec -it tomcat01 /bin/bash
root@8456cf6ee5f9:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@8456cf6ee5f9:/usr/local/tomcat# cd webapps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# ls
# copy webcpps.dist的内容到webcpps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# cd ..
root@8456cf6ee5f9:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@8456cf6ee5f9:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@8456cf6ee5f9:/usr/local/tomcat# cd webapps
root@8456cf6ee5f9:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
#测试运行成功
**思考问题:**我们以后部署项目,如果每次都要进入容器是不是身份麻烦?我要是可以在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了!
docker容器 tomcat+网站
docker mysql
部署es+kibana
# es 暴露的端口很多
# es 十分耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork ? 网络配置
# 下载启动
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动之后 linux就卡住了 因为es很耗内存
root@ecs-7ed1:~# curl localhost:9200
{
"name" : "77a654314216",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "tc3RpVT6Q0iOkPei6Fd4vg",
"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"
}
# docker stats 查看cpu状态
root@ecs-7ed1:~# docker stats 77a654314216
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
77a654314216 elasticsearch 0.00% 1.253GiB / 3.852GiB 32.54% 1.47kB / 984B 11.4MB / 729kB 44
# 关闭,然后通过 -e 限制内存。 修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 测试通过
root@ecs-7ed1:~# curl localhost:9200
{
"name" : "47837f868e13",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ggOY5REmSoeXvwfVA_Eh4A",
"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"
}
# 查看占用内存。 显著下降
root@ecs-7ed1:~# docker stats 47837f868e13
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
47837f868e13 elasticsearch01 0.00% 351.1MiB / 3.852GiB 8.90% 2.24kB / 1.4kB 2.97MB / 729kB 44
思考:用kibana链接elasticsearch
可视化
- portainer (先用这个)
- Rancher (CI/CD时用) 持续集成和持续部署
portainer
Docker图像化界面管理工具,提供一个后台面板供我们操作!
# 启动
root@ecs-7ed1:~# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
外网访问
本地连接
Docker镜像
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量以及配置文件等。
如何获得镜像:
- 从远程仓库下载
- 朋友拷贝
- 自己制作一个镜像 DockerFile
原理
UnionFS 联合文件系统
bootfs:boot file system 启动内核kernel,不同系统基本一致
rootfs:root file system **不同系统的主要差别。**包含典型linux系统中的/dev , /proc , /bin , /etc 等标准目录和文件。只需包含基本命令,工具和程序库
分层理解
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
上图是每个镜像大的分层
下图将镜像的每层细分为多个文件
下图示意迭代更新文件5的原理
若pull新的镜像的分层,与原主机上的镜像分层的文件相同,则不需重新下载,可直接使用已下载镜像的层。(环境复用)
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供同一的视图。
Docker镜像都是只读的,当容器启动时,一个新的可写层被加到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层
commit提交镜像
docker commit # 提交容器成为一个新的副本
# 命令与git原理基本一致
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 运行tomcat
root@ecs-7ed1:~# docker run -d -p 8080:8080 tomcat
# 将webapps.dist里面所有的文件拷贝到webapps里面,其中-r必须有,表示目录递归拷贝 (已在部署tomcat部分操作)
# 提交镜像到本地
root@ecs-7ed1:~# docker commit -m="add webapps app" -a="sunwukong" fa14a6266117 tomcat02:1.0
查看提交结果:
测试在新的镜像tomcat02上创建容器
# 创建容器,失败。pull tomcat02失败,并没有直接运行本地的镜像
root@ecs-7ed1:~# docker run -d -p 3344:8080 tomcat02
Unable to find image 'tomcat02:latest' locally
docker: Error response from daemon: pull access denied for tomcat02, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.
# 在镜像名后加TAG,运行成功
root@ecs-7ed1:~# docker run -d -p 3344:8080 tomcat02:1.0
6d468dc745c72777f38af8432180a5f95e049d7a095c7103fba3dbcb4bf45b01
# 改用镜像id运行,成功
root@ecs-7ed1:~# docker run -d -p 3344:8080 f6a582ac8a28
15e4e09d9faa40ca2b3ae20fa35e1babe961a4169294723f9ec827a13d25647b
root@ecs-7ed1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15e4e09d9faa f6a582ac8a28 "catalina.sh run" 5 seconds ago Up 4 seconds 0.0.0.0:3344->8080/tcp, :::3344->8080/tcp pedantic_allen
# 外网访问成功
容器数据卷
什么是容器数据卷
docker是要将应用和环境打包成一个镜像
这样,数据就不应该在容器中,否则容器删除,数据就会丢失,这就是删库跑路
故容器之间要有一个数据共享技术
在Docker容器中产生的数据,同步到本地,这就是卷技术
本质上是一个==目录挂载==,将容器内的目录挂载到虚拟机上
**挂载:**指的就是将设备文件中的顶级目录连接到 Linux 根目录下的某一目录(最好是空目录),访问此目录就等同于访问设备文件。
参考:挂载讲解
目的:容器的持久化和同步操作
容器间可以数据共享
数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷。如果需要在删除容器的同时移除数据卷,可以在删除容器的时候使用 docker rm -v 这个参数。
使用数据卷
docker run -it -v -p
# -it 交互式进入
# -v volume卷技术
# -p 主机端口
# 测试
docker run -it -v /home/ceshi:/home/ centos /bin/bash
# docker inspect 容器id ,找到挂载信息Mounts
容器停止后,修改主机文件,再启动容器的时候,数据同样改变
双向同步
好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
假设我们将容器删除,发现,我们挂载到本地的数据卷依旧没有丢失,这就是先了容器数据持久化功能!
具名挂载和匿名挂载
# 匿名挂载
# -v 容器内路径!
-P 随机生成端口映射
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有卷的情况:
docker volume ls
# 这里发现,这种就是匿名挂载。我们使用 -v 只写了容器内的路径,没有写容器外的路径!会自动生成一个匿名的
# 具名挂载
# 通过 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 查看卷情况
docker volume ls
# 查看这个卷具体信息
docker volume inspect 卷名
# 所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径;ro rw 改变读写权限
# ro readonly 只读,只能在容器外部修改
# rw readwrite 可读可写,默认是rw
# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
初识DockerFile
DockerFile使用来构建docker镜像的文件!命令脚本!
# 镜像是一层一层的,脚本是一行一行的
# 指令都是大写的
# 这里的每个命令可以理解为镜像的一层
FROM centos
VOLUME ["volume01","volume02"] # 再创建镜像的时候就挂载出来
CMD echo "---end---"
CMD /bin/bash
# 构建build镜像
docker build -f dockerfile1 -t padaxing/centos:1.0 . # 最后的点很重要 镜像名不能有/
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
多个容器数据共享
多个mysql同步数据! 利用 --volumes-from 命令
# 测试
# 启动docker01,用之前建的padaxing/centos 1.0 镜像
docker run -it --name docker01 padaxing/centos:1.0 # 1.0必须写
# 当前这个ctrl+p+q不停止退出
# 依次启动docker02、docker03
docker run -it --name docker02 --volumes-from docker01 padaxing/centos:1.0
docker run -it --name docker03 --volumes-from docker01 padaxing/centos:1.0
# docker02继承docker01的volumes。可以验证,在docker01下加一个数据,在docker02下也会出现
# 在docker03的volume01下建立文件,在docker01的volume01下同样也有
# 即通过--volumes-from 可以实现不同容器间的数据共享
# 删除docker01,数据还在
# 原因:实际类似于硬链接。三个(多个)容器挂载到宿主机的相同卷,可通过 docker inspect 查看,容器卷关在在宿主机的同一目录下(即source相同)。所以即使删除一个容器,宿主机本地目录不会被删除,则不影响其它使用的容器数据。
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用位置。
但是如果持久化 -v 到了本地,即使所有容器删除了,本地数据是不会删除的。
DockerFile
步骤:开发、部署、运维。。。。缺一不可
DockerFile:构建文件。定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!
Docker容器:容器是镜像运行起来提供服务的
DockerFile介绍
是用来构建docker镜像的文件,可以理解为命令参数脚本
构建步骤:
- 编写一个dockerfile文件
- docker build 构建成为一个镜像
- docker run运行镜像
- docker push 发布镜像(DockerHub、阿里云镜像仓库 私有/共有)
这和写一个项目时一样的。
查看官方的DockerFile文件,可以在Docker Hub中查找镜像(下图)。选择一个版本,会跳转到github中的dockerfile文件。
可以看到官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像。
DockerFile基础知识
- 每个指令都必须是大写字母
- 按照从上到下顺序执行
- *#*表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
docker是面向开发的,我们以后要发布项目,做镜像,就要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为企业的交付标准,必须掌握!
DockerFile命令
FROM # 基础镜像 比如centos
MAINTAINER # 镜像是谁写的 姓名+邮箱
RUN # 镜像构建时需要运行的命令
ADD # 添加,比如添加一个tomcat压缩包
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 指定暴露端口,跟-p一个道理
RUN # 最终要运行的
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个(一个CMD中的最后一个命令)会生效,而且可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
COPY # 将文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战构建自己的centos
Docker Hub中99%的镜像都是从 FROM scratch 开始的
# 创建dockerfile文件,并编辑
root@ecs-7ed1:~# mkdir dockerfile
root@ecs-7ed1:~# cd dockerfile/
root@ecs-7ed1:~/dockerfile# ls
root@ecs-7ed1:~/dockerfile# vim mydocker-centos
# dockerfile文件内容
FROM centos
MAINTAINER padaxing<010301200@hai.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
# 构建镜像
docker build -f mydocker-centos -t mycentos:0.1 .
Successfully built b08c93da098f
Successfully tagged mycentos:0.1
# 测试构建的镜像
root@ecs-7ed1:~/dockerfile# docker run -it mycentos:0.1
[root@1cc49b0f5af5 local]# ls
bin etc games include lib lib64 libexec sbin share src
[root@1cc49b0f5af5 local]# pwd
/usr/local # 与dockerfile文件中的WORKDIR $MYPATH 相同
[root@1cc49b0f5af5 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 11 bytes 906 (906.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
对比之前的原生centos,很多命令vim,ifconfig都可以执行了。
可以通过docker history查看镜像的构建历史
root@ecs-7ed1:~/dockerfile# docker history b08c93da098f
IMAGE CREATED CREATED BY SIZE COMMENT
b08c93da098f 12 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
fa0807f4d458 12 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
178c87492d73 12 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
529bdb7fd679 12 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
2254913a6535 12 minutes ago /bin/sh -c yum -y install net-tools 29.5MB
357ec9e0edec 12 minutes ago /bin/sh -c yum -y install vim 68.1MB
eac37e85f6e8 12 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
74ed128d823b 12 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
15c22d1110f2 12 minutes ago /bin/sh -c #(nop) MAINTAINER padaxing<01030… 0B
300e315adb2f 8 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 8 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 8 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB
CMD与ENTRYPOINT
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个(一个CMD中的最后一个命令)会生效,而且可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
# 测试CMD
# CMD [] :要运行的命令是存放在一个数组结构中的
# build镜像
FROM centos
CMD ["ls","-a"] # 启动centos展示目录
# 测试ENTRYPOINT
run的时候可以直接加命令
实战:Tomcat镜像
1、准备镜像文件 tomcat 压缩包,jdk的压缩包!
2、编写dockerfile文件,官方命名Dockerfile
,build会自动寻找这个文件,就不需要 -f 指定了
tail -F 文件名 : tail命令启动时,文件不可访问或者文件稍后变得不可访问,都始终尝试打开文件
3、构建镜像
# docker build -t diytomcat .
4、启动镜像
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
# 先创建web.xml 和 index.jsp 文件
# 首先简单讲一下,web.xml的加载过程。当启动一个WEB项目时,容器包括(JBoss、Tomcat等)首先会读取项目web.xml配置文件里的配置,当这一步骤没有出错并且完成之后,项目才能正常地被启动起来。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
# index.jsp文件内容
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
Hello World!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>
发布项目之后测试
打印日志测试
cat catalina.out
发布自己的镜像
至DockerHub
1、地址 https://registry.hub.docker.com/ 注册自己的账号
2、确定这个账号可以登录
3、在我们服务器上登陆自己的账号
docker login -u 用户名 -p 密码
4、登陆完毕后就可以一觉自己的镜像了,,docker push
命令
docker push 用户名/镜像名:tag # 必须带tag
# 给镜像增加tag
docker tag 镜像id 新镜像名:修改的tag
提交的时候也是按照镜像的层级来进行提交的
至阿里云镜像服务上
1、登陆阿里云
2、找到容器镜像服务
3、创建命名空间
4、创建容器镜像
小结
Docker网络(铺垫 容器编排 集群部署!)
参考:
网络模式 | 简介 |
---|---|
Host | 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。 |
Bridge | 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。 |
None | 该模式关闭了容器的网络功能。 |
Container | 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。 |
自定义网络 | 略 |
测试
测试linux能否ping通容器内部
再次测试ip addr
再启动一个容器测试,发现又多了一对网卡
# 我们发现这个容器带来网卡,都是成对出现
# evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# Openstack,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
测试两个容器之间是否可以ping通
# 测试,可以ping通
root@ecs-7ed1:~# docker exec -it 1cc49b0f5af5 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.129 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.053 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.053 ms
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 71ms
rtt min/avg/max/mdev = 0.053/0.072/0.129/0.033 ms
原理图:
结论:容器之间有一个公用的路由器,docker 0
所有的容器在不指定网络的情况下,都是docker 0 路由的,docker会给我们的容器分配一个默认的可用IP
255.255.0.1/16
00000000.00000000.00000000.00000000
255.255.255.255
小结
Docker 使用的是Linux的桥接,宿主机中是一个Docker容器的网桥,docker 0
Docker 中的所有的网络接口都是虚拟的。虚拟的转发效率高!
只要容器删除,对应的网桥一对就没了
- -link
思考 一个场景,我们编写了一个微服务,database url = ip , 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以用名字来进行访问容器?
# 直接用容器名ping,失败
root@ecs-7ed1:~# docker exec -it romantic_dirac ping centosce
ping: centosce: Name or service not known
# --link 命令解决
root@ecs-7ed1:~# docker run -it -P --name centosce02 --link centosce mycentos:0.1
[root@2f62396223e0 local]# ping centosce
PING centosce (172.17.0.3) 56(84) bytes of data.
64 bytes from centosce (172.17.0.3): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from centosce (172.17.0.3): icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from centosce (172.17.0.3): icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from centosce (172.17.0.3): icmp_seq=4 ttl=64 time=0.057 ms
^C
--- centosce ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 54ms
rtt min/avg/max/mdev = 0.056/0.070/0.111/0.024 ms
[root@2f62396223edocker exec -it centosce02 ping centosce
PING centosce (172.17.0.3) 56(84) bytes of data.
64 bytes from centosce (172.17.0.3): icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from centosce (172.17.0.3): icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from centosce (172.17.0.3): icmp_seq=3 ttl=64 time=0.059 ms
^C
--- centosce ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 49ms
rtt min/avg/max/mdev = 0.059/0.062/0.065/0.002 ms
# 测试反向是否能ping通,失败
root@ecs-7ed1:~# docker exec -it centosce ping centosce02
ping: centosce02: Name or service not known
探究,docker network inspect NETWORKID
利用docker inspect 容器ID
,查看centosce02 本地配置了centosce容器的配置
# 查看 hosts 配置,在这里发现原理
root@ecs-7ed1:~# docker exec -it centosce02 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 centosce 96b487627e1f # 绑定
172.17.0.4 2f62396223e0
# 本质:--link 就是我们在 hosts 配置中增加了 172.17.0.3 centosce 96b487627e1f 映射
我们现在玩Docker 已经不建议使用 --link 了!
自定义网络!不适用docker0
docker0 问题:它不支持容器名连接访问!
自定义网络
# 查看所有的docker网络
root@ecs-7ed1:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
8aea018330c0 bridge bridge local
98037768e9fc host host local
88801a794175 none null local
网络模式
网络模式 | 简介 |
---|---|
Host | 容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。 |
Bridge | 此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。 |
None | 该模式关闭了容器的网络功能。 |
Container | 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。 |
自定义网络 | 略 |
测试
# 我们直接启动的命令默认是桥接模式 --net bridge,就是我们的docker0
root@ecs-7ed1:~# docker run -d -P --name tomcat01 tomcat
root@ecs-7ed1:~# docker run -d -P --name tomcat01 --net bridge tomcat
# docker0 特点,默认,域名不能访问, --link可以打通连接
# 我们可以自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16 子网地址(192.168.0.2~192.168.255.255)
# --gateway 192.168.0.1 网关(路由器)
root@ecs-7ed1:~# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e
root@ecs-7ed1:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
8aea018330c0 bridge bridge local
98037768e9fc host host local
ec634260bc68 mynet bridge local
88801a794175 none null local
# 我们自己的网络就创建好了
# 通过自己创建的网络创建两个容器
root@ecs-7ed1:~# docker run -it -P --name centos-net-01 --net mynet mycentos:0.1
root@ecs-7ed1:~# docker run -it -P --name centos-net-02 --net mynet mycentos:0.1
# 查看网络信息
root@ecs-7ed1:~# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e",
"Created": "2021-09-06T14:19:41.156516116+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": {
"9d92a018707dd27653c68d52acefa18b7c8acda30c535ec9f1cee8a47bee3591": {
"Name": "centos-net-01",
"EndpointID": "c60296191820dcdbab953bb82cb37eb81547730ad6a5cf9ec182b4794a3da5bf",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"f9b17003373507e68042d16293514be760ba76c2f135a24bf2c01f9de6ae5c2c": {
"Name": "centos-net-02",
"EndpointID": "a90ef766d1f22a816443271372b6e0bedff6db20d61d2b953b24b1365835ed57",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 测试两个容器之间能不能 ping 通
# ping IP,成功
root@ecs-7ed1:~# docker exec -it centos-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.090 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.059 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 32ms
rtt min/avg/max/mdev = 0.059/0.070/0.090/0.016 ms
# ping 容器名,成功。 不使用--link,也可以
root@ecs-7ed1:~# docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.057 ms
^C
--- centos-net-02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 28ms
rtt min/avg/max/mdev = 0.054/0.066/0.087/0.014 ms
创建网络之后查看ip addr
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:
redis - 不同的集群使用不同的网络,保证集群是安全和健康的。
mysql - 不同的集群使用不同的网络,保证集群是安全和健康的。
网络连通
测试不同网络下的容器之间 ping 不通。
root@ecs-7ed1:~# docker exec -it centos01 ping centos-net-01
ping: centos-net-01: Name or service not known
须使用connect将容器与网络连接
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
# 测试打通 centos01 到 mynet
root@ecs-7ed1:~# docker network connect mynet centos01
# 查看网络信息,发现容器处多一个centos01
# 连通之后就是将 centos01 放到了 mynet 网络下
# 就是一个容器两个 IP地址! --一个在bridge网络下 172.17.0.2;一个在mynet网络下 192.168.0.4
# 类似阿里云服务器:公网IP 私网IP
root@ecs-7ed1:~# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "ec634260bc6868ccd491bb9126249d7e811b6946aa2d3462b19eb34b05e17c4e",
"Created": "2021-09-06T14:19:41.156516116+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": {
"866174b67e0091714db22f309d5e7aec813cd0403d2e4156ef4bfe4b9b3ab880": {
"Name": "centos01",
"EndpointID": "b53e1e14d4dc2fbeff12fd073ebb3b6e336c98d7f574fa91e99ccf7b5392b16e",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"9d92a018707dd27653c68d52acefa18b7c8acda30c535ec9f1cee8a47bee3591": {
"Name": "centos-net-01",
"EndpointID": "c60296191820dcdbab953bb82cb37eb81547730ad6a5cf9ec182b4794a3da5bf",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"f9b17003373507e68042d16293514be760ba76c2f135a24bf2c01f9de6ae5c2c": {
"Name": "centos-net-02",
"EndpointID": "a90ef766d1f22a816443271372b6e0bedff6db20d61d2b953b24b1365835ed57",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 测试是否能ping 通,成功!!
root@ecs-7ed1:~# docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.129 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.058 ms
^C
--- centos-net-01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 28ms
rtt min/avg/max/mdev = 0.058/0.082/0.129/0.033 ms
**结论:**假设要通过网络操作其它容器,就需要使用 docker network connect
连通!
实战:部署Redis集群
# 创建 redis 网络
docker network create redis --subnet 172.38.0.0/16
# 通过shell脚本创建六个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
# 创建6个容器,节点
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 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 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
# 创建集群
root@ecs-7ed1:~# 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-replicas 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: d5f38eac055b1f200776b4d8f6e294fdbe6adfec 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 1391c63afef978e7c8db20a221d6f11865cd543a 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: aea97f79ad407ada284118f33e5622e1ffaf369a 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 8bb7d0eb00a8924f67a6bfbe46019875d024c05b 172.38.0.14:6379
replicates aea97f79ad407ada284118f33e5622e1ffaf369a
S: 01f579678eed6ebd4de339c52ced69958b6935fe 172.38.0.15:6379
replicates d5f38eac055b1f200776b4d8f6e294fdbe6adfec
S: 2da4d51a9b21c84c6e06dade77310d830e4e9e0f 172.38.0.16:6379
replicates 1391c63afef978e7c8db20a221d6f11865cd543a
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: d5f38eac055b1f200776b4d8f6e294fdbe6adfec 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 1391c63afef978e7c8db20a221d6f11865cd543a 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 01f579678eed6ebd4de339c52ced69958b6935fe 172.38.0.15:6379
slots: (0 slots) slave
replicates d5f38eac055b1f200776b4d8f6e294fdbe6adfec
M: aea97f79ad407ada284118f33e5622e1ffaf369a 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 2da4d51a9b21c84c6e06dade77310d830e4e9e0f 172.38.0.16:6379
slots: (0 slots) slave
replicates 1391c63afef978e7c8db20a221d6f11865cd543a
S: 8bb7d0eb00a8924f67a6bfbe46019875d024c05b 172.38.0.14:6379
slots: (0 slots) slave
replicates aea97f79ad407ada284118f33e5622e1ffaf369a
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 测试,在redis-3中set a值,然后停止运行redis-3。再次 get a值 ,返回成功。是从 从机 redis-4 中获取的值
节点主从信息
停止 redis-3 后,在从机 redis-4 中查到a值
再次查看节点信息,发现 redis-3已经fail,故障转移。redis-4变成master
SpringBoot微服务打包Docker镜像
狂神docker-39-SpringBoot微服务打包Docker镜像
Docker进阶
Docker Compose
简介
原来:dockerfile -> build -> run 手动操作,单个容器!
若 微服务,100个微服务!依赖关系。 很难实现
Docker Compose 来轻松高效地管理容器,定义运行多个容器。
官方介绍:
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features. (定义和运行多容器、YMAL配置文件、命令)
Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process:
- Define your app’s environment with a
Dockerfile
so it can be reproduced anywhere. (Dockerfile保证我们的项目在任何地方可以运行)- Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment. (services 什么是服务、docker-compose.yml 文件怎么写)- Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using the docker-compose binary. (启动项目)
作用:批量容器编排。
kaungshen:
Compose 是Docker官方的开源项目,需要安装!
Dockerfile保证我们的项目在任何地方可以运行。 web服务、redis、mysql、nginx…多个容器。 需要多个build & run
Compose:重要概念
- 服务services:容器、应用。(web、redis、mysql…)
- 项目project。一组关联的容器。
# Compose.yml 文件举例。 两个服务web、redis。web links redis
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
# docker-compose up 100个服务!!
安装Compose
# 1、下载
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 2、授权
sudo chmod +x /usr/local/bin/docker-compose
# 3、检查是否安装成功
docker-compose version
体验——官网文档实战
体验项目地址----Docker官网文档 —python应用。计数器。redis!
# 1、为项目创建目录
# 2、创建app.py文件:应用
# 3、创建依赖包
# 4、创建Dockerfile文件:应用打包为镜像
# 5、创建yml文件,定义服务(服务需要的环境,完整的上线服务)
# 6、启动项目build and run
docker-compose up
# 7、测试,成功
root@ecs-7ed1:~# curl localhost:5000
Hello World! I have been seen 1 times.
自动的默认规则
查看镜像 docker images ——自动下载
# 查看镜像 docker images ——自动下载
root@ecs-7ed1:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
composetest_web latest b878a824af5d 11 minutes ago 184MB
<none> <none> 7dc492a51c16 2 hours ago 41.9MB
redis alpine f6f2296798e9 11 days ago 32.3MB
python 3.7-alpine ab6374cb8b8e 11 days ago 41.9MB
# docker service ls
root@ecs-7ed1:~# 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.
默认的服务名 : 文件名_服务名_num
多个服务器。集群。A B _num 副本数量
服务redis服务 => 4 个副本
集群状态。服务都不可能只有一个运行实例。弹性、HA(高可用集群)、高并发
kubectl service 负载均衡。
3、网络规则
# 查看网络,新建composetest_default网络
root@ecs-7ed1:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
8aea018330c0 bridge bridge local
14b69e745911 composetest_default bridge local
98037768e9fc host host local
ec634260bc68 mynet bridge local
88801a794175 none null local
dbd3209213ec redis bridge local
# 查看composetest_default网络,有web_1、redis_1容器
root@ecs-7ed1:~# docker network inspect composetest_default
[
{
"Name": "composetest_default",
"Id": "14b69e74591176587aa499e1295dd76830870b4376a379639d7c7f858672720d",
"Created": "2021-09-08T10:45:50.492279984+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"9f0b074df478b53b0e1f14bc70ebdd2e8892b6c5db201c1b4f1d1617127ba990": {
"Name": "composetest_web_1",
"EndpointID": "db66e6645c02fe592e4d12d93ea15a45d1f4836c7bb00935e3c91ed56d295ad6",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"a30b19e67d705949e24c03167af6c45d1944f0ee96bb74de168ef028c9989b28": {
"Name": "composetest_redis_1",
"EndpointID": "62578f91ce49569554d84cb60a6cb3c4330c0f5126507fc498cf8644d7890646",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "composetest",
"com.docker.compose.version": "1.29.2"
}
}
]
10个服务 => 项目 (项目中的内容都在同个网络下。域名访问)
mysql : 3306 ——> 通过mysql去访问,而不是通过ip。
如果在同一个网络下,我们可以直接通过域名访问。保证高可用
停止:
- 直接 Ctrl + C
- docker-compose down
yaml规则
docker-compose.yaml 核心!!!
参考 : 官方文档
多写多看:1、官方文档;2、开源项目
# 3层!
version:'' # 1、版本
services: # 2、服务
服务1: web
# 服务配置 docker容器的配置
images
build
network
......
服务2: redis
......
服务3: redis
......
# 3、其它配置 网络/卷、全局规划
volumes:
network:
configs:
depends_on
deploy
开源项目——wordpress
博客wordpress: 官方文档wordpress博客项目
下载程序、安装数据库、配置…
compose应用 => 一键启动!
1、下载项目(docker-compose.yaml)
2、如果需要文件。Dockerfile
3、文件准备齐全(直接一键启动项目!)
测试,成功
前台启动 docker-compose up
后台启动 docker-compose up -d
实战
步骤:
- 编写项目微服务
- Dockerfile 构建镜像
- docker-compose.yml 编排项目
- 丢到服务器 一键启动:docker-compose up
假设项目要重新部署打包
docker-compose up --build # 重新构建!
总结:
项目 compose :三层
- 工程 Project
- 服务
- 容器 运行实例! docker k8s
Docker Swarm
参考 : 官方文档
掌握 搭建集群、启动服务、动态管理容器
工作模式
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.
- 节点:管理节点、工作节点
- Raft一致性算法
- 操作都在manager
搭建集群
# 4个节点,两主两从
# manager节点
[root@k8s-master ~]# docker swarm init --advertise-addr 192.168.142.111
Swarm initialized: current node (lsmof9xcbrhxgtego47r7c8kk) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# 两个从节点
[root@k8s-node1 ~]# docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
This node joined a swarm as a worker.
# 在manager节点测试
[root@k8s-master ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
lsmof9xcbrhxgtego47r7c8kk * k8s-master Ready Active Leader 18.06.1-ce
nei92zfk2sy9u71yx425sz1sp k8s-node1 Ready Active 18.06.1-ce
whidxgyl1dbedftspqrd6mga4 k8s-node3 Ready Active 18.06.1-ce
# 加入manager节点,先获取令牌token
[root@k8s-master ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-2vokifkkn0d7lolh9fzs801gc 192.168.142.111:2377
# 在新增manager节点执行命令
[root@k8s-node3 ~]# docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
This node joined a swarm as a worker.
# 在manager节点测试
[root@k8s-master ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
lsmof9xcbrhxgtego47r7c8kk * k8s-master Ready Active Leader 18.06.1-ce
nei92zfk2sy9u71yx425sz1sp k8s-node1 Ready Active 18.06.1-ce
gl8jytd5om2fizqvmlt6n1ilr k8s-node2 Ready Active Reachable 18.06.1-ce
whidxgyl1dbedftspqrd6mga4 k8s-node3 Ready Active 18.06.1-ce
常见错误:
# 1.x509: certificate has expired or is not yet valid
时间不同步问题
# 2.error: connection error: desc = "trt: no route to host"
关闭manager防火墙: systemctl stop firewalld
加入 新的节点!
# 获取令牌
docker swarm join-token manager
docker swarm join-token worker
Raft一致性协议
双主双从:假设一个节点挂了! 其他节点是否可用???
Raft协议:保证大多数节点存活才可以用。。存活的节点数至少 > 1 ,则集群至少 大于3台!
实验:
-
将docker master1 机器停止,宕机! 由于是双主,另外一个主节点也不能使用了!
# 在manager1 上停止docker [root@k8s-master ~]# systemctl stop docker # 在另一台manager节点上测试,失败 [root@k8s-node2 ~]# docker node ls Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded# # 原因:存活节点==1 # 再次启动原manager1,测试,发现本节点不再是leader,原Reachable变成Leader [root@k8s-master ~]# systemctl start docker [root@k8s-master ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION lsmof9xcbrhxgtego47r7c8kk * k8s-master Ready Active Reachable 18.06.1-ce nei92zfk2sy9u71yx425sz1sp k8s-node1 Ready Active 18.06.1-ce gl8jytd5om2fizqvmlt6n1ilr k8s-node2 Ready Active Leader 18.06.1-ce whidxgyl1dbedftspqrd6mga4 k8s-node3 Ready Active 18.06.1-ce
-
可以其他节点离开
docker swarm leave
命令,Ready 变成 Down -
工作在work节点,管理在manager!
-
设置成3个manager节点,实验是否高可用!
# 同 1 实验。关闭 当前leader节点,在其他manager节点测试,发现,可正常操作 [root@k8s-node2 ~]# systemctl stop docker # k8s-node1上测试 [root@k8s-node1 ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION lsmof9xcbrhxgtego47r7c8kk k8s-master Ready Active Leader 18.06.1-ce 81n0ez1ljhfr5fgua26ju695k * k8s-node1 Ready Active Reachable 18.06.1-ce nei92zfk2sy9u71yx425sz1sp k8s-node1 Down Active 18.06.1-ce gl8jytd5om2fizqvmlt6n1ilr k8s-node2 Down Active Unreachable 18.06.1-ce whidxgyl1dbedftspqrd6mga4 k8s-node3 Ready Active 18.06.1-ce
当重启所有虚拟机后,发现再次使用 docker node ls
命令,报错:
Error: 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.
# 处理:在一台manager节点上使用命令
[root@k8s-master ~]# docker swarm init --force-new-cluster
Swarm initialized: current node (lsmof9xcbrhxgtego47r7c8kk) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-103kz9hhfiohrq4tlara8w34n1qah8ciqlod9qvgtsbp9fqqmg-dvju5jbd4hlv7aroqr1i7neno 192.168.142.111:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
命令docker swarm init --force-new-cluster
需要在一台活着的manager节点上执行,其含义是:
- 在执行命令的node上重新初始化swarm cluster
- 这个cluster只包含当前自己一个node
- 这个cluster会试图重新创建所有的services (它本身是manager节点,包含之前所有的cluster信息)
- 这个cluster会把还活着的其他manager节点和worker节点自动加进来。
体会——服务 service
弹性、扩缩容!集群!
以后告别 docker run!
docker-compose up! 启动一个项目!
集群:swarm! docker service
容器 = > 服务!
容器 = > 服务! = > 副本!
redis 服务 => 10个副本! (同时开启10个redis容器)
# docker service 创建服务、动态扩展服务、动态更新服务
灰度发布:金丝雀发布! ——升级不影响使用!
docker run # 容器启动!不具有扩缩容
docker service # 服务! 具有扩缩容、滚动更新!
# 启动服务service
[root@k8s-master ~]# docker service create -p 8888:80 --name my-nginx nginx
fhn2mxqa8tdwxqz5w7lkxqxe5
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
# 查看服务
[root@k8s-master ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
idbm3cir2u0z my-nginx.1 nginx:latest k8s-node1 Running Running about a minute ago
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
fhn2mxqa8tdw my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
# REPLICAS 副本,此时为 1
# 在其它三个节点中 使用 docker ps 命令,查看副本运行在哪个节点
[root@k8s-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bdf887a6ad51 nginx:latest "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 80/tcp my-nginx.1.idbm3cir2u0zvrxao1v1ynalu
# 创建更多的副本
# 1、使用docker service update --replicas 3 my-nginx
[root@k8s-master ~]# 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
# 查看副本运行情况
[root@k8s-master ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
idbm3cir2u0z my-nginx.1 nginx:latest k8s-node1 Running Running 4 minutes ago
0u03mamg3syo my-nginx.2 nginx:latest k8s-master Running Running 3 minutes ago
vxsdfiokn1mf my-nginx.3 nginx:latest k8s-node2 Running Running 4 minutes ago
# 2、使用 scale 命令
[root@k8s-master ~]# 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
# update --replicas num 命令与 scale 命令区别
# 测试发现并无差别,两者缩容时,都会将容器删除rm
# update更多的应用场景在于image的升级导致的运行中的服务需要更新等等
遇见的问题:创建副本时,一直卡在preparing状态
# 移除 服务
[root@k8s-master ~]# docker service rm my-nginx
my-nginx
服务,集群中的任意的节点都可以访问。服务可以有多个副本动态扩缩容实现高可用!
弹性、扩缩容!
swarm => k8s 副本、服务器、多容器!
概念总结
-
swarm
集群的管理和编号。docker 可以初始化一个 swarm 集群,其他节点可以加入。(manager、worker)
-
Node
就是一个 docker 节点。多个节点姐组成一个网络集群。(manager、worker)
-
Service
任务,可以在管理节点或者工作节点来运行。**核心!**用户访问
-
Task
容器内的命令,细节任务!
命令执行细节:命令 --> 管理 --> API --> 调度 --> 工作节点(创建Task容器,维护创建!)
逻辑是不变的,对比K8S
- 不同模式
# replicated 与 global
# replicated 内部调度器则会根据当前集群的资源使用情况在不同的node上启停容器
# global 强制在每个node上都运行一个且最多一个副本
# --mode string
docker service create --mode replicated --name my-nginx nginx
docker service create --mode global --name my-nginx nginx
# 默认是 replicated
网络模式: “PublishMode”: “ingress”
Overlay:覆盖网络 Overlay参考
ingress:特殊的Overlay网络! 具有 负载均衡 的功能! IPVS VIP !
虽然 docker 在四台机器上,实际网络是同一个! ingress 网络 ,使集群变成一个整体
Docker Stack
docker stack --help
docker-compose 单机部署项目!
Docker Stack部署,集群部署!
# 单机
docker-compose up -d wordpress.yaml
# 集群
docker stack deploy wordpress.yaml
# docker-compose 文件 注意deploy
Docker Secret
docker secret --help
安全! 配置密码,证书!
Docker Config
docker config --help
配置
扩展到K8S
云原生时代
Go语言! 必须掌握!