Docker学习笔记

一、 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快?

  1. Docker有着比虚拟机更少的抽象层。
  2. 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

# 这个时候,可以实现两个容器数据同步!
  1. 结论:
    容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

3. DokcerFile介绍

dockerfile 是用来构建docker镜像的文件!命令参数脚本!
构建步骤:

  1. 编写一个dockerfile文件
  2. docker build 构建称为一个镜像
  3. docker run运行镜像
  4. docker push发布镜像(DockerHub 、阿里云仓库)
    但是很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

4. DockerFile构建过程

基础知识:

  1. 每个保留关键字(指令)都是必须是大写字母
  2. 执行从上到下顺序
  3. #表示注释
  4. 每一个指令都会创建提交一个新的镜像,并提交!

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镜像

  1. 准备镜像文件,tomcat压缩包和jdk压缩包
wudengxiong@wudengxiong-virtual-machine:/home/tomcat$ ll
总用量 161128
drwxrwxr-x 2 wudengxiong wudengxiong      4096 330 14:17 ./
drwxrwxrwx 8 root        root             4096 330 14:16 ../
-rwxrwxrwx 1 wudengxiong wudengxiong   5963037 330 14:09 apache-tomcat-8.5.77-src.tar.gz*
-rwxrwxrwx 1 wudengxiong wudengxiong 159019376 330 14:13 jdk-8u11-linux-x64.tar.gz*
  1. 编写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 # 设置默认命令
  1. 构建镜像
# 因为dockerfile命名使用默认命名 因此不用使用-f 指定文件
$ docker build -t mytomcat:0.1 .
  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上发布
  1. 地址 https://hub.docker.com/
  2. 确定这个账号可以登录
  3. 登录
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

  1. 提交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镜像

  1. 构建SpringBoot项目
  2. 打包运行
  3. 编写dockerfile
  4. 构建镜像
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
  1. 发布运行
  2. 测试使用

以后我们使用了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 .

构建项目内容

以前的方法

  1. 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;

  1. 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)
  1. 启动微服务
docker run -d -p 8081:8081 97d32ab48712
#访问地址测试
http://localhost:8081/swagger-ui.html#/
  1. 缺点
    • 先后顺字要求固定,先mysql+redis才能微服务访问成功
    • 多个run命令…
    • 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产IP写死(可以但是不推荐),要么通过服务调用

现在的方法

  1. 服务编排

  2. 编写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:
  1. 第二次修改微服务工程docker_ boot

    • 写YML:通过服务名访问,IP无关
    • mvn package命令将微服务形成新的jar包并上传到Linux服务器/mydocker目录下
    • 编写Dockerfile
    • 构建镜像
      docker build -t wu_docker:1.6 .
  2. 执行docker-compose up或者执行docker-compose up -d

  3. 进入mysql容器实例并新建库db2022+新建表t_user

  4. 测试通过

  5. Compose常用命令口

     docker-compose stop
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值