一、 Docker概述
1. Docker为什么出现
- 传统
开发jar,运维来做,一般用虚拟机来实现。 - 现在
开发打包部署上线, 一套流程做完。
2. Docker和虚拟机的对比
虚拟机的缺点
- 资源占用十分多。
- 冗余步骤多。
- 启动很慢。
Docker和虚拟机技术的不同之处
- 传统虚拟机,虚拟出一条硬件,运行一 个完整的操作系统 ,然后在这个系统上安装和运行软件。
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了。
- 每个容器间是互相隔离每个容器内都有一个属于自己的文件系统,互不影响。
Docker的优势
- 应用更快捷的交付和部署
- 更便捷的升级和扩缩容
- 更简单的系统运维
- 更高效的计算资源利用!
3. Docker的基本组成

镜像(image):
docker镜像就好比是一个模板 ,可以通过这个模板来创建容器服务, tomcat镜像===> run ==> tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器( container) :
Docker利用容器技术,独立运行一个或者一 个组应用 ,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统
仓库( repository) :
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub (默认是国外的)
阿里…都有容器服务器(配置镜像加速! )
4. 底层原理
Docker是什么工作的?
Docker是一个Client - Server结构的系统, Docker的守护进程运行在主机上。通过Socket从客户端访问 !
DockerServer接收到Docker-Client的指令,就会执行这个命令!

Docker为什么比VM快?
- Docker有着比虚拟机更少的抽象层。
- docker 利用的是宿主机的内核, vm需要是Guest OS.
所以说,新建一个容器的时候, docker不需要想虚拟机-样重新加载一个操作系统内核 ,避免引导。虚拟机是加载Guest OS ,分钟级别的,而docker是利用宿主机的操作系统吗,省略了这个复杂的过程,秒级!
二、Docker的常用命令
1. 帮助命令
docker version # 显示docker版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
2. 镜像命令
docker images 查看所有主机上的镜像
~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 6 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的ID
镜像重命名
# 命令格式:
docker tag 镜像id 仓库:标签
或:
docker tag 旧镜像名 新镜像名
生成一个新的镜像,和原镜像同一个ID 。
#删除旧镜像
docker rmi 旧镜像名
docker search 搜索镜像
docker search mysql
#可选项,通过搜藏来过滤
--filter=STARS=3000 # 搜索出来的镜像就是STARS大于3000的
docker pull 下载镜像
# 下载镜像
~$ docker pull mysql
Using default tag: latest # 如果不写tag,默认就是latest版本
latest: Pulling from library/mysql
a4b007099961: Pull complete #分层下载,docker image的核心,联合文件系统
e2b610d88fd9: Pull complete
38567843b438: Pull complete
5fc423bf9558: Pull complete
aa8241dfe828: Pull complete
cc662311610e: Pull complete
9832d1192cf2: Pull complete
f2aa1710465f: Pull complete
4a2d5722b8f3: Pull complete
3a246e8d7cac: Pull complete
2f834692d7cc: Pull complete
a37409568022: Pull complete
Digest: sha256:b2ae0f527005d99bacdf3a220958ed171e1eb0676377174f0323e0a10912408a # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
#等价于它
docker pull mysq1
docker pull docker. 10/library/mysq1: latest
#指定版本下载
docker pull mysq1:5.7
docker rmi 删除镜像
docker rmi -f 容器id
#删除指定的容器
docker rmi -f 容器id容器id容器id容器id # 删除多个容器
docker rmi -f $(docker images -aq) # 删除全部的容器
3. 容器的基本命令
注意:有了镜像才可以创建容器
docker pull centos
新建容器并启动
docker run[可选参数] image
# 参数说明
--name="Name " 容器名字 tomcat01 tomcat02, 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-P 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
-P 随机指定端口
#测试,启动并进入容器
wudengxiong@wudengxiong-virtual-machine:/etc/docker$ docker run -it centos /bin/bash
[root@f1de4ee962d4 /]# ls #查看容器内容centos
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@f1de4ee962d4 /]# exit #从容器中退回主机
exit
列出所有的运行的容器
$ docker ps 命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示容器的编号
-f #筛选查找
docker ps -a
列出容器筛选详解
过滤标志(-f或-filter)格式为key=value,如果超过一个过滤,就传递多个标志(如-filter "foo=bar" -filter "bif=baz")
目前支持的过滤有如下这些
id (容器的id)
label
name(容器名称)
exited (整数-容器退出状态码,只有在使用-all才有用)
status 容器状态(created,restarting,running,paused,exited,dead)
ancestor ([:],or) 过滤从指定镜像创建的容器
before (容器的名称或id),过滤在给定id或名称之后创建的容器
isolation (default process hyperv) (windows daemon only)
volume (数据卷名称或挂载点),--过滤挂载有指定数据卷的容器
network(网络id或名称),过滤连接到指定网络的容器
--format 为格式化输出。格式化选项(-format) 使用go模板来美化打印容器输出
例:docker container ps -f "name=myimg" 过滤容器名字为myimg的容器
before和since,只的是在某一个容器创建的时间之前或之后的容器
docker kill $(docker container ps -f "network=wordpress_default" --format {{.Names}})
go模板
.ID 容器的ID
.Image 镜像的ID
.Command 容器启动的命令
.CreatedAt 创建容器的时间点
.RunngingFor 从容器创建到现在过去的时间
.Ports 暴露的端口
.Status 容器的状态
.Size 容器硬盘的大小
.Names 容器的名称
.Label 指定label的值
.Mounts 挂载到这个容器的数据卷名称
docker 根据镜像名称查找容器并删除
退出容器
exit #直接容器停止并退出
Ctrl+p+Q #容器不停
删除容器
docker rm 容器id #删除指定容器
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 #强制停止当前容器
4. 常用其他命令
后台启动容器
# 命令 docker run -d 镜像名
docker run -d centos
06ff3ffc61febe6e4ea29fabcc2de833243e99bec11e210c48dde1b843fe9a89
# 问题docker ps,发现centos停止了。
# 常见的坑: docker 容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx.容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
docker logs -tf --tail 数量 容器 #没有日志
# 自己写一段shell脚本
$ docker run -d centos /bin/sh -c "while
> true;do echo a; sLeep 1 ; done"
# 显示所有容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0494ed2eb422 centos "/bin/sh -c 'while \n…" About a minute ago Up About a minute blissful_johnson
# 停止容器
$ docker stop 0494ed2eb422
0494ed2eb422
# 显示日志
$ docker logs -tf --tail 10 0494ed2eb422
2022-03-28T06:20:49.855487695Z a
2022-03-28T06:20:49.855687140Z /bin/sh: line 1: sLeep: command not found
2022-03-28T06:20:49.855829146Z a
-tf # 显示日志
--tail number # 要显示日志条数
查看容器中的进程信息
# 命令 docker top 容器id
docker top 36d3ef26dddd
UID PID PPID C STIME TTY TIME CMD
root 435723 435701 0 14:27 pts/0 00:00:00 /bin/bash
查看容器镜像元数据
# docker inspect 容器id
docker inspect 36d3ef26dddd
进入当前正在运行的容器
#我们通常容器都是使用后台方式运行的,需要进入容器。修改一些配置
#命令
#docker exec -it 容器id bashShell
$ docker exec -it 36d3ef26dddd /bin/bash
# 方式二
docker attach 容器ID
#测试
docker attach 36d3ef26dddd
正在执行当前的代码...
区别
# docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach #进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
#展示现在运行的容器
wudengxiong@wudengxiong-virtual-machine:$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd88fd8edfc0 centos "/bin/bash" 26 seconds ago Up 25 seconds brave_mcnulty
#进入容器
wudengxiong@wudengxiong-virtual-machine:$ docker attach bd88fd8edfc0
#特定目录创建test.java
wudengxiong@wudengxiong-virtual-machine:/$ docker attach bd88fd8edfc0
[root@bd88fd8edfc0 home]# ls
text.txt
[root@bd88fd8edfc0 home]# touch test.java
[root@bd88fd8edfc0 home]# read escape sequence
#进入root用户
wudengxiong@wudengxiong-virtual-machine:/$ su root
密码:
#容器中复制文件
root@wudengxiong-virtual-machine:/# docker cp bd88fd8edfc0:/home/test.java /home
#切换到复制目录
root@wudengxiong-virtual-machine:/# cd /home
#显示复制完成文件
root@wudengxiong-virtual-machine:/home# ls
test.java wudengxiong
查看容器的运行状态
docker stats

4. 命令练习
部署Nginx
#1. 搜索镜像,建议官网搜索
wudengxiong@wudengxiong-virtual-machine:/$ docker search nginx
#2. 下载镜像
dockers pull nginx
#3.运行测试
wudengxiong@wudengxiong-virtual-machine:/$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 months ago 141MB
# 4. 运行nginx容器
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口,容器内部端口
wudengxiong@wudengxiong-virtual-machine:/$ docker run -d --name nginx01 -p 3344:80 nginx
b38569627396ededae9b04e3586fb3be1dd07910e712b3b9bc3b77bf37a4b6f0
# 5. 检验运行是否成功
wudengxiong@wudengxiong-virtual-machine:/$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b38569627396 nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 6.访问页面源码
wudengxiong@wudengxiong-virtual-machine:/$ curl localhost:3344
# 7. 进入nginx容器
wudengxiong@wudengxiong-virtual-machine:/$ docker exec -it b38569627396 /bin/bash
root@b38569627396:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@b38569627396:/# cd /etc/nginx
root@b38569627396:/etc/nginx# ls
conf.d mime.types nginx.conf uwsgi_params
fastcgi_params modules scgi_params
安装tomcat
#官方的使用
docker run -it --rm tomcat:9.0
#我们之前的启动都是后台,停止了容器之后,容器还是可以查到docker run -it --rm, 一般用来测试。用完就删除
#下载再启动
docker pull tomcat
#启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
#测试访问没有问题
#进入容器
wudengxiong@wudengxiong-virtual-machine:~$ docker exec -it tomcat01 /bin/bash
root@6f260b0d36ab:/usr/local/tomcat# ls
#发现问题: 1. 1inux命令少了,2.没有webapps. 阿里云镜像的原因。默认是最小的镜像,所有不必要的都剔除掉。
#保证最小可运行的环境!
我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径 , webapps我们在外部放置项目,就自动同步到内部就好了!
部署es+kibana
# es暴露的端口很多!
# es十分的耗内存
# es的数据一般需要放置到安全目录!挂载
# --net somenetwork ?网络配置
$ wudengxiong@wudengxiong-virtual-machine:~$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.5.2
# 查看镜像
wudengxiong@wudengxiong-virtual-machine:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 months ago 141MB
tomcat latest fb5657adc892 3 months ago 680MB
elasticsearch 7.5.2 929d271f1798 2 years ago 779MB
#启动单点
wudengxiong@wudengxiong-virtual-machine:~$ docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.2
#测试容器是否启动
localhost:9200
# 增加内存限制,修改配置文件 -e 环境配置修改
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" docker.elastic.co/elasticsearch/elasticsearch:7.5.2
5. 可视化
- portainer (先用这个)
什么是portainer?
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
#测试
访问http://ip:8088/#/init/admin
通过以后进入页面

选择访问

三、Docker镜像讲解
- 镜像是什么
镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
将所有的应用和环境,直接打包为docker镜像,就可以直接运行。
- 如何得到镜像:
●从远程仓库下载
●朋友拷贝给你
●自己制作一个镜像DockerFile
1.Docker镜像加载原理
-
UnionFs (联合文件系统)
我们下载的时候看到一层层的下载就是这个。 UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
-
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。 boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel,Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。 -
Docker为啥内容那么小
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs. 虚拟机是分钟级别,容器是秒级!
2. 分层理解
最大的好处,我觉得莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。

上图中的镜像层跟之前图中的略有区別,主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版

文中情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
在这里插入图片描述

Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
3. commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1. 启动tomcat
wudengxiong@wudengxiong-virtual-machine:~$ docker run -it -p 8080:8080 tomcat
# 2. 进入tomcat容器中
wudengxiong@wudengxiong-virtual-machine:~$ docker exec -it ade2474f5ccc /bin/bash
# 3. 复制webapps.dist/*的文件到webapps中
root@ade2474f5ccc:/usr/local/tomcat# cp webapps.dist/* webapps
# 4. 显示容器id
wudengxiong@wudengxiong-virtual-machine:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ade2474f5ccc tomcat "catalina.sh run" 9 minutes ago Up 9 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp peaceful_proskuriakova
# 5.提交镜像版本
wudengxiong@wudengxiong-virtual-machine:~$ docker commit -m="add webapps app" -a="my" ade2474f5ccc mytomcat:1.0
sha256:b27376b88e363422bb888af7b552da9c0b819ff2cb00a2e9db33ba0ddd44eb5a
# 6.检测镜像是否上传成功
wudengxiong@wudengxiong-virtual-machine:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 b27376b88e36 9 seconds ago 684MB
nginx latest 605c77e624dd 2 months ago 141MB
tomcat latest fb5657adc892 3 months ago 680MB
portainer/portainer latest 580c0e4e98b0 12 months ago 79.1MB
docker.elastic.co/elasticsearch/elasticsearch 7.5.2 929d271f1798 2 years ago 779MB
elasticsearch 7.5.2 929d271f1798 2 years ago 779MB
4. 容器数据卷
-
什么是容器卷*
MySQL,容器删除了,删库跑路!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的! -
使用数据卷
直接使用命令挂载 -v
-v, --volume list Bind mount a volume
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
docker run -it -v /home/ceshi:/home centos /bin/bash
#通过 docker inspect 容器id 查看
文件就可以在主机上的/home/ceshi和容器上的/home这两个目录中交换了,即使容器停掉,也可以编辑文件。
- mysql数据同步测试
#获取MySQL镜像
wudengxiong@wudengxiong-virtual-machine:~$ docker pull mysql:5.7
# 参考官网hub
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#启动
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
-- name 容器名字
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功之后,我们在本地使用sqlyog来测试一下
# sqlyog-连接到服务器的3306--和容器内的3306映射
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!
5. 具名和匿名挂载
# 匿名挂载
-v 容器内路径!
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
docker volume ls
DRIVER VOLUME NAME
local 9c0bc7c104e68043dd5bc459d4d6722e36cdcf508130530107f785b4dd377d6d
local juming-nginx
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!
# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
docker volume ls
DRIVER VOLUME NAME
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷
wudengxiong@wudengxiong-virtual-machine:~$ docker volume inspect juming-nginx
[
{
"CreatedAt": "2022-03-29T13:41:04+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data下
如果指定了目录,docker volume ls 是查看不到的。
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
拓展
# 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
四、 Dockerfile
1. 初试Dockerfile
Dockerfile 就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像。
# 创建一个dockerfile文件,名字可以随便 建议Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
#这里的每个命令,就是镜像的一层!
#构建脚本
root@wudengxiong-virtual-machine:/home/docker-test-volum# docker build -f /home/docker-test-volum/dockerfile -t my/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Using cache
---> 523313a3d31a
Step 3/4 : CMD echo "----end----"
---> Using cache
---> d73fe3cc927c
Step 4/4 : CMD /bin/bash
---> Using cache
---> f9692e5886b0
Successfully built f9692e5886b0
Successfully tagged my/centos:1.0
#查看镜像构建情况
root@wudengxiong-virtual-machine:/home/docker-test-volum# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my/centos 1.0 f9692e5886b0 About a minute ago 231MB
# 启动自己写的镜像
root@wudengxiong-virtual-machine:/home/docker-test-volum# docker run -it f9692e5886b0 /bin/bash
# 显示挂载的卷
[root@69c77a211b6b /]# ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
查看卷挂载
docker inspect 容器id

测试一下刚才的文件是否同步出去了!
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
2. 数据卷容器

--volumes-from list Mount volumes from the specified container(s)
# 测试,我们通过刚才启动的
#创建容器一 docker01
docker run -it --name docker01 my/centos:1.0
#创建容器二 docker02,与docker01共享数据
docker run -it --name docker02 --volumes-from docker01 my/centos:1.0
#创建容器三 docker03,与docker01共享数据
docker run -it --name docker03 --volumes-from docker01 my/centos:1.0
#创建文件查看两个容器是否数据同步
测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
测试依旧可以访问
- 多个mysql实现数据共享
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候,可以实现两个容器数据同步!
- 结论:
容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
3. DokcerFile介绍
dockerfile 是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
- 编写一个dockerfile文件
- docker build 构建称为一个镜像
- docker run运行镜像
- docker push发布镜像(DockerHub 、阿里云仓库)
但是很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!
4. DockerFile构建过程
基础知识:
- 每个保留关键字(指令)都是必须是大写字母
- 执行从上到下顺序
- #表示注释
- 每一个指令都会创建提交一个新的镜像,并提交!
Dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!Docker镜像逐渐成企业交付的标准,必须要掌握!
- DockerFile:构建文件,定义了一切的步骤,源代码
- DockerImages:通过DockerFile构建生成的镜像,最终发布和运行产品。
- Docker容器:容器就是镜像运行起来提供服务。
5. DockerFile 常用指令
| 指令 | 含义 |
|---|---|
| FROM | # 基础镜像,一切从这里开始构建 |
| MAINTAINER | # 镜像是谁写的, 姓名+邮箱 |
| RUN | # 镜像构建的时候需要运行的命令 |
| ADD | # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录 |
| WORKDIR | # 镜像的工作目录 |
| VOLUME | # 挂载的目录 |
| EXPOSE | # 保留端口配置 |
| CMD | # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。 |
| ENTRYPOINT | # 指定这个容器启动的时候要运行的命令,可以追加命令 |
| ONBUILD | # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。 |
| COPY | # 类似ADD,将我们文件拷贝到镜像中 |
| ENV | # 构建的时候设置环境变量! |
- 实战测试
1.编写Dockerfile文件
vim mydockerfile-centos
#脚本内容
FROM centos:7.9.2009
MAINTAINER wu<2501749984@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 文件路径 -t 镜像名:[tag] .
docker build -f mydockerfile-centos -t mycentos:0.1 .
测试运行
#检查镜像是否成功
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 0.1 ff0c066f8a80 3 minutes ago 580MB
#运行镜像
docker run -it ff0c066f8a80 /bin/bash
#工作目录改变了
[root@22970fcaa517 local]# pwd
/usr/local
我们可以列出本地进行的变更历史
#docker history 镜像id
docker history ff0c066f8a80
6.CMD 和 ENTRYPOINT区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
- 测试CMD
#编写dockerfile-cmd-test脚本文件
vim dockerfile-cmd-test
#脚本内容
FROM centos
CMD ["ls","-a"]
#构建镜像
$ docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-a"]
---> Running in fd76b6ad6a7e
Removing intermediate container fd76b6ad6a7e
---> e36440a9b8db
Successfully built e36440a9b8db
Successfully tagged cmdtest:latest
#运行镜像
$ docker run e36440a9b8db
.
..
.dockerenv
#追加命令 -l
$ docker run e36440a9b8db -l
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# cmd的情况下 -l 替换了CMD["ls","-a"]。 -l 不是命令所有报错
- 测试ENTRYPOINT
#编写dockerfile-cmd-entrypoint脚本文件
vim dockerfile-cmd-entrypoint
#脚本内容
FROM centos
ENTRYPOINT ["ls","-a"]
#构建镜像
$ docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 0514dc1ba9ae
Removing intermediate container 0514dc1ba9ae
---> 3b563f678bac
Successfully built 3b563f678bac
Successfully tagged cmdtest:latest
#运行镜像
$ docker run 3b563f678bac
.
..
.dockerenv
#追加命令 -l
$ docker run 3b563f678bac -l
total 56
drwxr-xr-x 1 root root 4096 Mar 30 01:21 .
drwxr-xr-x 1 root root 4096 Mar 30 01:21 ..
-rwxr-xr-x 1 root root 0 Mar 30 01:21 .dockerenv
...
7. 实战:Tomcat镜像
- 准备镜像文件,tomcat压缩包和jdk压缩包
wudengxiong@wudengxiong-virtual-machine:/home/tomcat$ ll
总用量 161128
drwxrwxr-x 2 wudengxiong wudengxiong 4096 3月 30 14:17 ./
drwxrwxrwx 8 root root 4096 3月 30 14:16 ../
-rwxrwxrwx 1 wudengxiong wudengxiong 5963037 3月 30 14:09 apache-tomcat-8.5.77-src.tar.gz*
-rwxrwxrwx 1 wudengxiong wudengxiong 159019376 3月 30 14:13 jdk-8u11-linux-x64.tar.gz*
- 编写dockerfile文件
FROM centos:7.9.2009
MAINTAINER wu<2501749984@qq.com>
COPY README /usr/local/README #复制文件
ADD jdk-8u11-linux-x64.tar.gz /usr/local/ #复制解压
ADD apache-tomcat-9.0.59.tar.gz /usr/local/ #复制解压
RUN yum -y install vim
ENV MYPATH /usr/local #设置环境变量
WORKDIR $MYPATH #设置工作目录
ENV JAVA_HOME /usr/local/jdk1.8.0_11 #设置环境变量
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.59 #设置环境变量
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib #设置环境变量分隔符是:
EXPOSE 8080 #设置暴露的端口
CMD /usr/local/apache-tomcat-9.0.59/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.59/logs/catalina.out # 设置默认命令
- 构建镜像
# 因为dockerfile命名使用默认命名 因此不用使用-f 指定文件
$ docker build -t mytomcat:0.1 .
- 运行镜像
$ docker run -d -p 8080:8080 --name tomcat02 -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.59/webapps/test -v /home/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.59/logs mytomcat:0.1
6.访问测试
8. 发布镜像
dockhub上发布
- 地址 https://hub.docker.com/
- 确定这个账号可以登录
- 登录
docker login -u wudengxiong
Password:
WARNING! Your password will be stored unencrypted in /home/wudengxiong/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
- 提交push镜像
root@wudengxiong-virtual-machine:/home/tomcat# docker push wudengxiong/mytomcata:3.0
The push refers to repository [docker.io/wudengxiong/mytomcata]
cc9515116f54: Pushed
361d932f7f4f: Pushed
0e673c569c5c: Pushed
c9ea22821ee2: Pushed
174f56854903: Pushed
3.0: digest: sha256:408f5a256d34a30a790d344c7d7481a8c0ae8a3845f21ece08d1d3dfc41d9c23 size: 1373
仓库中多了对应的镜像

注意:
# 会发现push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法
# 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t wu/mytomcat:0.1 .
# 第二种 使用docker tag #然后再次push
$ docker tag 容器id wu/mytomcat:1.0 #然后再次push
#当出现denied: requested access to the resource is denied
#可能需要重新登录
#或者镜像改个名(tag标签,详细用法见上)
阿里云镜像上发布
看官网 很详细https://cr.console.aliyun.com/repository/
$ sudo docker login --username=zchengx registry.cn-shenzhen.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像
版本号]
# 修改id 和 版本
sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:1.0
# 修改版本
$ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]
五、 Docker网络
1. 理解Docker0
# 清除所有镜像
docker rmi -f $(docker images -aq)
# 查看镜像情况
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
#清楚所有容器
docker rm -f $(docker ps -aq)
# 查看容器情况
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#查看网络情况
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:12:52:6f brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 10.80.0.190/16 brd 10.80.255.255 scope global dynamic noprefixroute ens33
valid_lft 1395sec preferred_lft 1395sec
inet6 fe80::67ce:6cf3:d041:e5d9/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:fc:6d:e5:98 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:fcff:fe6d:e598/64 scope link
valid_lft forever preferred_lft forever
# lo: 本地回环地址
# ens33: 网卡设备
# docker0: docker0地址
运行tomcat
# 测试 运行一个tomcat
docker run -d --name tomcat01 tomcat
#查看网络情况
ip addr
#发现ip得到一个veth0b91e1f@if26 ip地址,docker分配!
27: veth0b91e1f@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether de:1b:82:31:e5:20 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::dc1b:82ff:fe31:e520/64 scope link
valid_lft forever preferred_lft forever
#我们这里的inet6显示并非数字,可以通过查看容器查看对应ip
docker inspect 容器ID
"IPAddress": "172.17.0.3",
# 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以!
# 可以ping成功
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 比特,来自 172.17.0.2: icmp_seq=1 ttl=64 时间=0.069 毫秒
64 比特,来自 172.17.0.2: icmp_seq=2 ttl=64 时间=0.038 毫秒
原理
1. 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!
2. 启动一个容器测试,发现又会多一对网络
我们发现这个容器带来网卡,都是一对对的veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
3. 测试下tomcat01和tomcat02是否可以ping通
docker exec -it tomcat02 ping 172.17.0.2
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ping": executable file not found in $PATH: unknown
#发现报错,不能ping,需要在容器中安装ping
apt update && apt install -y iproute2 && apt install -y net-tools && apt install -y iputils-ping
#直接执行这个命令太慢了,安装个容器镜像
sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
#再执行就ping成功了
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.098 ms
结论:tomcat01和tomcat02公用一个路由器,docker0。
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip。
小结: Docker使用的是Linux的桥接,宿主机是一个Docker容器的网桥 docker0

Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
只要容器删除,对应的网桥一对就没了!
2. -link
项目不重启,数据ip换了,我们希望可以处理这个问题,使用名字直接ping通
$ docker exec -it tomcat02 ping tomca01 # ping不通
ping: tomca01: Name or service not known
# 运行一个tomcat03 --link tomcat02
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
acec7673548e18c8f9b125eb91862d3013143123162d2eedd991e7ccd6693417
# 用tomcat03 ping tomcat02 可以ping通
$ 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.112 ms
docker network inspect 网络id 网段相同
docker inspect tomcat03
"Links": [
"/tomcat02:/tomcat03/tomcat02"
],
#查看tomcat03里面的/etc/hosts发现有tomcat02的配置
$ docker exec 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 b93d89b72dc6
172.17.0.4 acec7673548e
–link 本质就是在hosts配置中添加映射
现在使用Docker已经不建议使用–link了!
自定义网络,不适用docker0!
docker0问题:不支持容器名连接访问!
3. 自定义网络
#查看所有的docker网络
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1e786536a800 bridge bridge local
d5552f8573d9 host host local
44fc33fa41a0 none null local
网络模式
bridge :桥接 docker(默认,自己创建也是用bridge模式)
none :不配置网络,一般不用
host :和所主机共享网络
container :容器网络连通(用得少!局限很大)
# 直接启动的命令 --net bridge,而这个就是我们的docker0
# bridge就是docker0
$ docker run -d -P --name tomcat01 tomcat
等价于 => docker run -d -P --name tomcat01 --net bridge tomcat
自定义一个网络
# docker0,特点:默认,域名不能访问。 --link可以打通连接,但是很麻烦!
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker network ls
NETWORK ID NAME DRIVER SCOPE
1e786536a800 bridge bridge local
d5552f8573d9 host host local
1976a0caf0cf mynet bridge local
44fc33fa41a0 none null local
查看mynet内容
docker network inspect mynet;
[
{
"Name": "mynet",
"Id": "1976a0caf0cf0d2587e8d41d1fc9c8753c7f618a6981ad50307be831ebaaeb56",
"Created": "2022-03-31T16:26:49.635307456+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": {}
}
]
#启动两个Tomcat,再次查看网络情况
docker run -d -P --name tomcat-net-01 --net mynet tomcat
b1f496af3a0f176f2d73cde4aff38634b24adcf4ccf08edb04340fa1b94498cf
docker run -d -P --name tomcat-net-02 --net mynet tomcat
cd6ed78fcd841feb62f0087aad55beee4823865b08e8b34c4b01745a579cd34d
# 再次查看网络情况
docker network inspect mynet
[
{
"Name": "mynet",
"Id": "1976a0caf0cf0d2587e8d41d1fc9c8753c7f618a6981ad50307be831ebaaeb56",
"Created": "2022-03-31T16:26:49.635307456+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": {
"b1f496af3a0f176f2d73cde4aff38634b24adcf4ccf08edb04340fa1b94498cf": {
"Name": "tomcat-net-01",
"EndpointID": "ea15ef6a03f209d7464f3e08216ccefa6080b6267d92abc93e7873e6715a87f1",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"cd6ed78fcd841feb62f0087aad55beee4823865b08e8b34c4b01745a579cd34d": {
"Name": "tomcat-net-02",
"EndpointID": "a4c41dd21b7f52e6799457ee6f71554eec02a5dd7310c1853c3a04a5f117b810",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 在自定义的网络下,服务可以互相ping通,不用使用–link
root@cd6ed78fcd84:/usr/local/tomcat# 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.098 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.104 ms
root@b1f496af3a0f:/usr/local/tomcat# 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.060 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.066 ms
我们自定义的网络docker当我们维护好了对应的关系,推荐我们平时这样使用网络!
4. 网络连通
测试docker0和mynet的连接
docker exec -it tomcat-net-02 ping tomcat01
ping: tomcat01: Temporary failure in name resolution
#发现不能ping通
network connect
docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
要将tomcat02 连通 tomcat-net-01 ,连通就是将 tomcat02加到 mynet网络
一个容器两个ip(tomcat01)
#将tomcat02加入到mynet中
docker network connect mynet tomcat02
# tomcat-net-01和tomcat02进行ping测试
docker exec tomcat-net-01 ping tomcat02
PING tomcat02 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.097 ms
# tomcat-net-01和tomcat03进行ping测试
docker exec tomcat-net-01 ping tomcat03
ping: tomcat03: Temporary failure in name resolution
02连通 ,加入后此时,已经可以tomcat02 和 tomcat-01-net ping通了
03是依旧不通的
结论:假设要跨网络操作别人,就需要使用docker network connect 连通!
5. Redis集群

#创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个redis配置,要用root账号创建
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个redis
#redis1
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
#redis2
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
#redis3
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
#redis4
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
#redis5
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
#redis6
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
docker exec -it redis-1 /bin/sh
#redis默认没有bash
#搭建redis集群
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
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# docker搭建redis集群完成!
6. SpringBoot项目打包Docker镜像
- 构建SpringBoot项目
- 打包运行
- 编写dockerfile
- 构建镜像
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
- 发布运行
- 测试使用
以后我们使用了Docker之后,给别人交付就是一个镜像即可!
狂神说docker(最全笔记)
六、 Docker-compose
Compose是Docker公司推出的-一个工具软件,可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动关闭这些容器。
1. 用途
Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义- -组相关联的应用容器为一个项目( roject)。
可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose解决了容器与容器之间如何管理编排的问题。
2. 安装
#官网
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
# 建议使用迅雷下载二进制文件
# 下载的文件会输出到 /usr/local/bin/docker-compose
#下载太慢可以使用下面网站替换github
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#更改文件的写权限
sudo chmod +x /usr/local/bin/docker-compose
#查看docker-compose版本
docker-compose --version
#如果不想用了,可以通过下面的命令卸载
sudo rm /usr/local/bin/docker-compose
3. 核心概念
一文件
docker-compose.yml
两要素
- 一个个应用容器实例,比如订单微服务、库存微服务、mysq|容器、nginx容器或者redis容器
- 由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
4. 步骤
- 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
- 使用docker-compose.yml定义一个完整业务单元,安排好整体应用中的各个容器服务。
- 最后,执行docker-compose up命令来启动并运行整个应用程序,完成一 键部署上线
5. 常用命令
| 命令 | 作用 |
|---|---|
| docker-compose -h | 查看帮助 |
| docker-compose up | 启动所有docker-compose服务 |
| docker-compose up -d | 启动所有docker-compose服务并后台运行 |
| docker-compose down | 停止并删除容器、网络、卷、镜像。 |
| docker-compose exec yml里面的服务id | 进入容器实例内部docker-compose exec docker-compose.yml文件中写的服务id /bin/bash |
| docker-compose ps | 展示当前docker-compose编排过的运行的所有容器 |
| docker-compose top | 展示当前docker-compose编排过的容器进程 |
| docker-compose logs yml里面的服务id | 查看容器输出日志 |
| docker-compose config | 检查配置 |
| docker-compose config -q | 检查配置,有问题才有输出 |
| docker-compose restart | 重启服务 |
| docker-compose start | 启动服务 |
| docker-compose stop | 停止服务 |
6. 编排微服务
- 以前的基础版
- SQL建表建库
- 一键生成说明
- 改POM
- 写YML
- 主启动
- 业务类
- mvn package命令将微服务形成新的jar包并上传到Linux服务器/mydocker目录下
- 编写Dockerfile
#基础镜像使用java
FROM java:8
#作者
MAINTAINER wu
#VOLUME指定临时文件目录为/tmp,在主机/varlib/docker目录下创建了一个临时文件并链>接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中并更名为wu_docker.jar
ADD wu_docker.jar wu_docker.jar
#运行jar包
RUN bash -c 'touch /wu_docker.jar'
ENTRYPOINT ["java","-jar","/wu_docker.jar"]
#暴露8081端口作为微服务
EXPOSE 8081
- 构建镜像
docker build -t wu_docker:1.6 .
以前的方法
- MySQL环境搭建
#启动MySQL
docker run -d -p 3306:3306 --name mysql57 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/logs:/logs -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
#进入mysql
docker exec -it mysql57 bash
root@7f566c357fcd:/# mysql -uroot -p
Enter password:
#创建数据库和数据表
mysql> create database db2022;
#检验数据的创建情况
mysql> select * from t_user;
- Redis环境搭建
#启动redis
docker run -p 6379:6379 --name redis608 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
#进入redis
docker exec -it redis608 bash
redis-cli -p 6379
#检验连接情况
127.0.0.1:6379> keys pattern
(empty array)
- 启动微服务
docker run -d -p 8081:8081 97d32ab48712
#访问地址测试
http://localhost:8081/swagger-ui.html#/
- 缺点
- 先后顺字要求固定,先mysql+redis才能微服务访问成功
- 多个run命令…
- 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产IP写死(可以但是不推荐),要么通过服务调用
现在的方法
-
服务编排
-
编写docker-compose.yml文件
yml文件内容就相当于run的相关命令
version: "3"
services:
microService:
image: wu_docker:1.6
container_name: ms01
ports:
- "8081:8081"
volumes:
- /app/microService:/data
networks:
- atguigu_net
depends_on:
- redis
- mysql
redis:
image: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /app/redis/redis.conf:/etc/redis/redis.conf
- /app/redis/data:/data
networks:
- atguigu_net
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'db2022'
MYSQL_USER: 'wu'
MYSQL_PASSWORD: '123456'
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- atguigu_net
command:
--default-authentication-plugin=mysql_native_password #解决外部无法访问
networks:
atguigu_net:
-
第二次修改微服务工程docker_ boot
- 写YML:通过服务名访问,IP无关
- mvn package命令将微服务形成新的jar包并上传到Linux服务器/mydocker目录下
- 编写Dockerfile
- 构建镜像
docker build -t wu_docker:1.6 .
-
执行docker-compose up或者执行docker-compose up -d
-
进入mysql容器实例并新建库db2022+新建表t_user
-
测试通过
-
Compose常用命令口
docker-compose stop
390

被折叠的 条评论
为什么被折叠?



