《狂神说Java》docker教程通俗易懂

文章目录

  • 前言
  • 一、Docker概述
    • 1. Docker为什么出现
    • 2. Docker的历史
    • 3. Docker能做什么
  • 二、Docker安装
    • 1. Docker的基本组成
    • 2. 安装Docker
    • 3. 阿里云镜像加速
    • 4. 回顾hello-world流程
    • 5. 底层原理
  • 三、Docker的常用命令
    • 1. 帮助命令
    • 2. 镜像命令
      • dokcer images
      • docker search
      • docker pull
      • docker rmi
    • 3. 容器命令
      • 新建容器并启动
      • 列出所有运行的容器
      • 退出容器
      • 删除容器
      • 启动和停止容器的操作
    • 4. 常用其他命令
      • 后台启动容器
      • 查看日志
      • 查看容器中进程的信息
      • 查看镜像的元数据
      • 进入当前正在运行的容器
      • 从容器内拷贝文件到主机上
    • 5. 小结
    • 6. 作业练习
      • docker安装nginx
      • docker安装tomcat
      • 部署ES+kibana
    • 7. 可视化
      • 什么是portainer ?
  • 四、Docker镜像讲解
    • 1. 镜像是什么
    • 2. Docker镜像加速原理
      • UnionFS(联合文件系统)
      • Docker镜像加载原型
    • 3. 分层理解
      • 分层的镜像
      • 特点
    • 4. commit镜像
      • 实战测试
  • 五、容器数据卷
    • 1. 什么是容器数据卷
    • 2. 使用数据卷
      • 直接使用命令来挂载:-v
    • 3. 实战:安装mysql
    • 4. 匿名和具名挂载
    • 5. 初识Dockerfile
    • 6. 数据卷容器
  • 六、DockerFile
    • 1. DockerFile介绍
    • 2. DockerFile的构建过程
      • 基础知识
    • 3. DockerFile的命令
    • 4. 实战测试
    • 5. 制作tomcat镜像
    • 6. 发布自己的镜像
      • 1. 发布到dockerhub上
      • 2. 发布到阿里云镜像服务上
    • 7. 小结
  • 七、Docker网络
    • 1. 理解docker0
      • 测试
      • 原理
    • 2. --link
      • 思考一个场景(高可用)
    • 3. 自定义网络
      • 查看所有的docker网络
      • 网络模式
      • 测试
    • 4. 网络连通
    • 5. 实战:部署redis集群
  • 八、SpringBoot微服务打包docker镜像


总结笔记,课程来自:https://www.bilibili.com/video/BV1og4y1q7M4?vd_source=345a382f2c86d3441cc342a80fc25545

前言

给大家分享《三体》中的一句话,很有感触:弱小和无知不是生存的障碍,傲慢才是。

  • Docker概述
  • Docker安装
  • Docker命令
    • 镜像命令
    • 容器命令
    • 操作命令
  • Docker镜像!
  • 容器数据卷!
  • DockerFile·Docker网络原理
  • IDEA整合Docker
  • Docker Compose
  • Docker Swarm
  • CI\CDJenkins

一、Docker概述

1. Docker为什么出现

一款产品:开发–上线 两套环境(应用环境,应用配置)
开发—运维。问题:我在我的电脑上可以运行!版本更新,导致服务不可用!对于运维来说,考验就十分大?
环境配置是十分的麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop…)费时费力。
发布一个项目(jar +(Redis MySQL jdk ES)),项目能不能都带上环境安装打包!
之前在服务器配置一个应用的环境Redis MySQL jdk ES Hadoop,配置超麻烦了,不能够跨平台。
Windows开发,最后发布到Linux:

  • 传统:开发jar,运维来做!
  • 现在:开发打包部署上线,一套流程做完!

java — apk – 发布(应用商店)—张三使用apk—安装即可用!
java — jar(环境)— 打包项目带上环境(镜像)—(Docker仓库:商店)—下载我们发布的镜像–直接运行即可!

Docker给以上的问题,提出了解决方案!

Docker的思想就来自于集装箱!
隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。

本质:所有的技术都是因为出现了一些问题,我们需要去解决,才去学习。

2. Docker的历史

2010年,几个搞IT的年轻人,就在美国成立了一家公司dotcloud做一些pass的云计算服务!
LXC有关的容器技术!他们将自己的技术(容器化技术)命名就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意!(dotCloud就活不下去)
开源(开放源代码)
2013年,Docker开源!
Docker越来越多的人发现了docker的优点!就火了,Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布!
Docker为什么这么火?十分的轻巧
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!(很笨重)
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!

vm:隔离,需要开启多个虚拟机!linux centos原生镜像(一个电脑!)需要几个G内存空间,开启需要几分钟!
docker:隔离,镜像(最核心的环境4m内存)十分的小巧,运行镜像就可以了!小巧!几个M或KB的内存空间,秒级启动!

聊聊Doker

Docker是基于Go语言开发的!开源项目!
官网:https://www.docker.com/
文档地址:https://docs.docker.com/
Doker镜像仓库地址:https://hub.docker.com/

3. Docker能做什么

之前的虚拟机技术

《狂神说Java》docker教程通俗易懂_第1张图片
虚拟机技术缺点:
1、资源占用十分多
2、冗余步骤多
3、启动很慢!

容器化技术

容器化技术不是模拟的一个完整的操作系统
《狂神说Java》docker教程通俗易懂_第2张图片

比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
  • 容器内的应用直接运行在宿主机的内核中,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了。
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

Devops(开发、运维)

应用更快速的交付和部署

传统:一堆帮助文档,安装程序!
Docker:打包镜像发布测试,一键运行!

更便捷的升级和扩缩容

使用了Docker之后,我们部署应用就和搭积木一样!
项目打包为一个镜像,扩展服务器A!服务器B!

更简单的系统运维

在容器化之后,我们的开发,测试环境都是高度一致的。

更高效的计算资源利用

Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
只要学不死,就往死里学!

二、Docker安装

1. Docker的基本组成

《狂神说Java》docker教程通俗易懂_第3张图片
镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像===>run==>tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

容器(container):
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统

仓库(repository):
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub(默认是国外的)阿里云.…都有容器服务器(配置镜像加速!)

2. 安装Docker

环境准备

  1. 需要会一点点的Linux的基础
  2. CentOS7
  3. 我们使用Xshell连接远程服务器进行操作

环境查看

# 系统内核是 3.10 以上的
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# uname -r
3.10.0-1160.66.1.el7.x86_64
# 查看系统版本
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装

查看文档:https://docs.docker.com/ (https://docs.docker.com/engine/install/centos/)

# 1.卸载旧的版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
# 2.需要的安装包
yum install -y yum-utils
# 3.设置镜像的仓库
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo # 默认是从国外的。

yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐使用阿里云的。


# 安装容器之前,更新yum软件包索引。
yum makecache fast
# 4.安装容器相关的。docker-ce(社区版)docker-ee(企业版)
yum install docker-ce docker-ce-cli containerd.io
# 5.启动docker
systemctl start docker
# 6.使用docker version查看是否安装成功

《狂神说Java》docker教程通俗易懂_第4张图片

# 7.测试hello-world
docker run hello-world

《狂神说Java》docker教程通俗易懂_第5张图片

# 8.查看一下下载的这个hello-world镜像

了解:卸载docker

# 1.卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2.删除资源
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

# /var/lib/docker  docker的默认工作路径

3. 阿里云镜像加速

  1. 登录阿里云,找到容器服务。
  2. 找到镜像加速地址。
  3. 配置使用。

4. 回顾hello-world流程

《狂神说Java》docker教程通俗易懂_第6张图片

5. 底层原理

Docker是怎么工作的?
Docker 是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
DockerServer 接收到Docker-Client的指令,就会执行这个命令!
《狂神说Java》docker教程通俗易懂_第7张图片
Docker为什么比VM快?
1、Docker有着比虚拟机更少的抽象层。
2、docker利用的是宿主机的内核,vm需要是Guest OS。
《狂神说Java》docker教程通俗易懂_第8张图片
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。
虚拟机是加载GuestOS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级!

三、Docker的常用命令

1. 帮助命令

docker version		# 显示docker的版本信息
docker info		  	# 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help 		# 帮助命令

帮助文档的地址:https://docs.docker.com/reference/

2. 镜像命令

dokcer images

查看所有本地的主机上的镜像

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   10 months ago   13.3kB
# 解释
REPOSITORY	镜像的仓库源
TAG			镜像的标签
IMAGE ID	镜像的id
CREATED		镜像的创建时间
SIZE		镜像的大小
# 命令参数可选项
 -a, --all         # 显示所有镜像 (docker images -a)
 -q, --quiet       # 仅显示镜像id (docker images -q)

docker search

搜索镜像

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker search mysql
NAME                           DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                          MySQL is a widely used, open-source relation…   12940     [OK]
mariadb                        MariaDB Server is a high performing open sou…   4957      [OK]
phpmyadmin                     phpMyAdmin - A web interface for MySQL and M…   587       [OK]
percona                        Percona Server is a fork of the MySQL relati…   582       [OK]
# 解释
# 命令参数可选项 (通过搜索来过滤)
--filter=STARS=3000 	# 搜索出来的镜像就是stars大于3000的

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker search mysql --filter=STARS=3000
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   12941     [OK]
mariadb   MariaDB Server is a high performing open sou…   4957      [OK]

docker pull

下载镜像

# 下载镜像:docker pull 镜像名[:tag]
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker pull mysql
Using default tag: latest			# 如果不写tag,默认就是latest,最新的版本
latest: Pulling from library/mysql
72a69066d2fe: Pull complete			# 分层下载,docker image的核心,联合文件下载
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest		# 真实地址

# 两个命令是等价的
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists		# 联合文件下载,已经存在的资源可以共用
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi

删除镜像

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f 镜像id					# 删除指定的镜像
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f 镜像id 镜像id 镜像id	# 删除多个镜像(空格分隔)
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f $(docker images -aq)	# 删除全部的镜像

3. 容器命令

说明:我们有了镜像才可以创建容器,linux,下载一个centos 镜像来测试学习。

docker pull centos

新建容器并启动

docker run [可选参数] image
# 参数说明
--name="name"		容器名字:用来区分容器
-d					后台方式运行:相当于nohup
-it					使用交互式运行:进入容器查看内容
-p					指定容器的端口(四种方式)小写字母p
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口
	-p 容器端口
	容器端口
-P 					随机指定端口(大写字母P)
# 测试:启动并进入容器
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -it centos /bin/bash
[root@526c31d2c298 /]# ls		# 查看容器内的centos(基础版本,很多命令都是不完善的)
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 从容器中退回到主机
[root@526c31d2c298 /]# exit
exit
[root@iZbp13qr3mm4ucsjumrlgqZ /]# ls
bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  www

列出所有运行的容器

docker ps	# 列出当前正在运行的容器
# 命令参数可选项
-a		# 列出当前正在运行的容器+历史运行过的容器
-n=?	# 显示最近创建的容器(可以指定显示几条,比如-n=1)
-q		# 只显示容器的编号

[root@iZbp13qr3mm4ucsjumrlgqZ /]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZbp13qr3mm4ucsjumrlgqZ /]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                     PORTS     NAMES
526c31d2c298   centos         "/bin/bash"   4 minutes ago   Exited (0) 2 minutes ago             optimistic_allen
ce0eb11fbf8a   feb5d9fea6a5   "/hello"      4 hours ago     Exited (0) 4 hours ago               keen_ellis
[root@iZbp13qr3mm4ucsjumrlgqZ /]# docker ps -a -n=1
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                     PORTS     NAMES
526c31d2c298   centos    "/bin/bash"   5 minutes ago   Exited (0) 3 minutes ago             optimistic_allen

退出容器

exit		# 容器直接停止,并退出
ctrl+P+Q	# 容器不停止,退出

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -it centos /bin/bash
[root@c5d61aa9d7df /]# [root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
c5d61aa9d7df   centos    "/bin/bash"   56 seconds ago   Up 55 seconds             kind_clarke
[root@iZbp13qr3mm4ucsjumrlgqZ ~]#

删除容器

docker rm 容器id					# 删除容器(不能删除正在运行的容器)如果要强制删除:docker rm -f 容器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 镜像名
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -d centos
# 问题:docker ps发现centos停止了

# 常见的坑:docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止。
# 比如:nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

查看日志

docker logs -tf --tail 容器id
# 自己编写一段shell脚本
docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done"


[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker logs -tf  容器id
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker logs -tf --tail 10  容器id

# 显示日志
-tf						# 显示日志
--tail number	# 要显示的日志条数	

查看容器中进程的信息

# 命令 docker top 容器id 
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker top 88d23bcbe1f2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                21212               21193               0                   16:23               ?                   00:00:00            
root                21600               21212               0                   16:29               ?                   00:00:00            

查看镜像的元数据

# 命令docker inspect 容器id
[
    {
        "Id": "88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe",
        "Created": "2022-07-29T08:23:56.862239223Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo kuangshen;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 21212,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-07-29T08:23:57.109766809Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe/hostname",
        "HostsPath": "/var/lib/docker/containers/88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe/hosts",
        "LogPath": "/var/lib/docker/containers/88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe/88d23bcbe1f28e1f8ae5d2b63fa8d57d2abcbdacf193db05852f4f74a95b9ffe-json.log",
        "Name": "/silly_lichterman",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/59b088d44f6e67f4ed336de44d19a5784c1a13fa856760bd2b166c4a4d421e2b-init/diff:/var/lib/docker/overlay2/7fc43e24b63e4656ab7e7718d3e4ef5297fe82509452be305a01605a7cdc3b97/diff",
                "MergedDir": "/var/lib/docker/overlay2/59b088d44f6e67f4ed336de44d19a5784c1a13fa856760bd2b166c4a4d421e2b/merged",
                "UpperDir": "/var/lib/docker/overlay2/59b088d44f6e67f4ed336de44d19a5784c1a13fa856760bd2b166c4a4d421e2b/diff",
                "WorkDir": "/var/lib/docker/overlay2/59b088d44f6e67f4ed336de44d19a5784c1a13fa856760bd2b166c4a4d421e2b/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "88d23bcbe1f2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true;do echo kuangshen;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "bfc28d2ba671adfe5c93325173b93c335d50d8b017eed4fdce2ab75410d6ac2e",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/bfc28d2ba671",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "ad0252d454e751e2c5ecef24e64c32b0884c53242925bd66e9e5dbf5542af179",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "7254ffccbdf53e0c72c1d19252980f04fa65153ea3c7ca72af55cfac504cbe3f",
                    "EndpointID": "ad0252d454e751e2c5ecef24e64c32b0884c53242925bd66e9e5dbf5542af179",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

进入当前正在运行的容器

# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id /bin/bash

# 测试
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
88d23bcbe1f2   centos    "/bin/sh -c 'while t…"   13 minutes ago   Up 13 minutes             silly_lichterman
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker exec -it 88d23bcbe1f2 /bin/bash
[root@88d23bcbe1f2 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:23 ?        00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done
root       841     0  0 08:37 pts/0    00:00:00 /bin/bash
root       858     1  0 08:37 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root       859   841  0 08:37 pts/0    00:00:00 ps -ef

# 方式二
docker attach 容器id
# 测试
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker attach 88d23bcbe1f2
正在执行当前的代码...

# docker exex		# 进入容器后开启一个新的终端,可以再里面操作(常用)
# docker attach		# 进入容器正在执行的终端,不会启动新的进程。

从容器内拷贝文件到主机上

docker cp 容器id:容器内路径 目的主机的路径

[root@iZbp13qr3mm4ucsjumrlgqZ home]# ll
total 0
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker run -it centos /bin/bash
[root@6eda31ad7987 /]# [root@iZbp13qr3mm4ucsjumrlgqZ home]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
6eda31ad7987   centos    "/bin/bash"   17 seconds ago   Up 16 seconds             stoic_kepler
# 进入到容器内部
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker attach 6eda31ad7987
[root@6eda31ad7987 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@6eda31ad7987 /]# cd /home/
[root@6eda31ad7987 home]# ls
# 在容器的/home路径下创建test.java文件
[root@6eda31ad7987 home]# touch test.java
[root@6eda31ad7987 home]# ls
test.java
[root@6eda31ad7987 home]# exit
exit
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                      PORTS     NAMES
6eda31ad7987   centos    "/bin/bash"   About a minute ago   Exited (0) 28 seconds ago             stoic_kepler
# 将文件拷贝出来到主机上(在主机上执行该命令)
[root@iZbp13qr3mm4ucsjumrlgqZ home]# docker cp 6eda31ad7987:/home/test.java /home
[root@iZbp13qr3mm4ucsjumrlgqZ home]# ls
test.java

# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现,自动同步(容器内的/home路径和主机上的/home路径打通)

5. 小结

《狂神说Java》docker教程通俗易懂_第9张图片

6. 作业练习

docker安装nginx

  1. 搜索镜像:docker search nginx (建议去dockerHub上去搜索)

  2. 下载镜像:docker pull nginx

  3. 启动nginx:

    # -d 后台运行
    # --name="nginx01"	给容器命名
    # -p 宿主机端口:容器内部端口
    [root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -d --name="nginx-1" -p 3344:80 nginx
    6e02190a50bc8d79653ffa88f6b5c143d79c5ac3257d5d5ed6a01247980fb48a
    [root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
    6e02190a50bc   nginx     "/docker-entrypoint.…"   18 seconds ago   Up 17 seconds   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx-1
    
    # 进入容器
    [root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker exec -it a1e130aa184d /bin/bash
    root@a1e130aa184d:/# whereis nginx
    nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
    root@a1e130aa184d:/# cd /etc/nginx/
    root@a1e130aa184d:/etc/nginx# ls
    conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params
    
  4. 本机测试

    [root@iZbp13qr3mm4ucsjumrlgqZ ~]# curl localhost:3344
    <!DOCTYPE html>
    
    
    Welcome to nginx!<<span class="token operator">/</span>title>
    <style>
    html <span class="token punctuation">{</span> color-scheme: light dark<span class="token punctuation">;</span> <span class="token punctuation">}</span>
    body <span class="token punctuation">{</span> width: 35em<span class="token punctuation">;</span> margin: 0 auto<span class="token punctuation">;</span>
    font-family: Tahoma<span class="token punctuation">,</span> Verdana<span class="token punctuation">,</span> Arial<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <<span class="token operator">/</span>style>
    <<span class="token operator">/</span>head>
    <body>
    <h1>Welcome to nginx!<<span class="token operator">/</span>h1>
    <p><span class="token keyword">If</span> you see this page<span class="token punctuation">,</span> the nginx web server is successfully installed and
    working<span class="token punctuation">.</span> Further configuration is required<span class="token punctuation">.</span><<span class="token operator">/</span>p>
    
    <p><span class="token keyword">For</span> online documentation and support please refer to
    <a href=<span class="token string">"http://nginx.org/"</span>>nginx<span class="token punctuation">.</span>org<<span class="token operator">/</span>a><span class="token punctuation">.</span><br/>
    Commercial support is available at
    <a href=<span class="token string">"http://nginx.com/"</span>>nginx<span class="token punctuation">.</span>com<<span class="token operator">/</span>a><span class="token punctuation">.</span><<span class="token operator">/</span>p>
    
    <p><em>Thank you <span class="token keyword">for</span> <span class="token keyword">using</span> nginx<span class="token punctuation">.</span><<span class="token operator">/</span>em><<span class="token operator">/</span>p>
    <<span class="token operator">/</span>body>
    <<span class="token operator">/</span>html>
    </code></pre> </li> 
      </ol> 
      <blockquote> 
       <p>端口暴露的概念</p> 
      </blockquote> 
      <p><a href="http://img.e-com-net.com/image/info8/a5825a5e9f5a470388fb1c51825fb1f4.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/a5825a5e9f5a470388fb1c51825fb1f4.jpg" alt="《狂神说Java》docker教程通俗易懂_第10张图片" width="650" height="501" style="border:1px solid black;"></a><br> <code>思考问题:我们每次改动nginx配置文件,都需要进入容器内部?十分的麻烦,我要是可以在容器外部提供一个映射路径,达到在容器外修改文件名,容器内部就可以自动修改?-v 数据卷</code></p> 
      <h3>docker安装tomcat</h3> 
      <pre><code class="prism language-powershell"><span class="token comment"># 官方的使用</span>
    docker run <span class="token operator">-</span>it <span class="token operator">--</span><span class="token function">rm</span> tomcat
    
    <span class="token comment"># 我们之前的启动都是后台,停止了容器之后,容器还是可以查到docker run -it --rm,一般用来测试,用完就删除。</span>
    
    <span class="token comment"># 下载</span>
    docker pull tomcat
    
    <span class="token comment"># 启动运行</span>
    docker run <span class="token operator">-</span>d <span class="token operator">--</span>name=<span class="token string">"tomcat01"</span> <span class="token operator">-</span>p 3355:8080 tomcat
    
    <span class="token comment"># 测试访问没有问题,但是找不到资源</span>
    <span class="token comment"># 进入容器,有一个webapps文件夹和webapps.dist文件夹</span>
    docker exec <span class="token operator">-</span>it tomcat01 <span class="token operator">/</span>bin/bash
    <span class="token comment"># webapps文件夹下没有资源,资源都在webapp.dist文件夹下</span>
    root@35eb825661e0:<span class="token operator">/</span>usr/local/tomcat<span class="token comment"># ls</span>
    BUILDING<span class="token punctuation">.</span>txt  CONTRIBUTING<span class="token punctuation">.</span>md  LICENSE  NOTICE  README<span class="token punctuation">.</span>md  RELEASE-NOTES  RUNNING<span class="token punctuation">.</span>txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps<span class="token punctuation">.</span>dist  work
    
    <span class="token comment"># 发现问题:(阿里云镜像的原因:默认是最小的镜像,所有不必要的都剔除掉)保证最小可运行的环境</span>
    <span class="token comment"># 1、Linux命令少了。</span>
    <span class="token comment"># 2、没有webapps文件夹。</span>
    
    <span class="token comment"># 没有webapps文件夹,发现有一个webapps.dist文件夹,资源在webapps.dist文件夹下;</span>
    <span class="token comment"># 把webapps.dist文件夹下的文件复制到webapps文件夹下,就可以访问成功。</span>
    root@35eb825661e0:<span class="token operator">/</span>usr/local/tomcat<span class="token comment"># cp -r webapps.dist/* webapps</span>
    </code></pre> 
      <p>思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径,webapps,我们在外部放置项目,就自动同步到内部就好了!</p> 
      <h3>部署ES+kibana</h3> 
      <pre><code class="prism language-powershell"><span class="token comment"># es暴露的端口很多!</span>
    <span class="token comment"># es十分的耗内存!</span>
    <span class="token comment"># es的数据一般需要放置到安全目录!挂载</span>
    
    <span class="token comment"># 下载启动elasticsearch</span>
    docker run <span class="token operator">-</span>d <span class="token operator">--</span>name elasticsearch <span class="token operator">-</span>p 9200:9200 <span class="token operator">-</span>p 9300:9300 <span class="token operator">-</span>e <span class="token string">"discovery.type=single-node"</span> elasticsearch:7<span class="token punctuation">.</span>6<span class="token punctuation">.</span>2
    
    <span class="token comment"># 启动了linux就卡住了,es是十分耗内存的(1核2G)</span>
    <span class="token comment"># 查看cpu的状态</span>
    docker stats 
    <span class="token comment"># 测试一下es是成功的</span>
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># curl localhost:9200</span>
    <span class="token punctuation">{</span>
      <span class="token string">"name"</span> : <span class="token string">"7ed338b2a87c"</span><span class="token punctuation">,</span>
      <span class="token string">"cluster_name"</span> : <span class="token string">"docker-cluster"</span><span class="token punctuation">,</span>
      <span class="token string">"cluster_uuid"</span> : <span class="token string">"enAVpI1oQoW4tLmafuWcnw"</span><span class="token punctuation">,</span>
      <span class="token string">"version"</span> : <span class="token punctuation">{</span>
        <span class="token string">"number"</span> : <span class="token string">"7.6.2"</span><span class="token punctuation">,</span>
        <span class="token string">"build_flavor"</span> : <span class="token string">"default"</span><span class="token punctuation">,</span>
        <span class="token string">"build_type"</span> : <span class="token string">"docker"</span><span class="token punctuation">,</span>
        <span class="token string">"build_hash"</span> : <span class="token string">"ef48eb35cf30adf4db14086e8aabd07ef6fb113f"</span><span class="token punctuation">,</span>
        <span class="token string">"build_date"</span> : <span class="token string">"2020-03-26T06:34:37.794943Z"</span><span class="token punctuation">,</span>
        <span class="token string">"build_snapshot"</span> : false<span class="token punctuation">,</span>
        <span class="token string">"lucene_version"</span> : <span class="token string">"8.4.0"</span><span class="token punctuation">,</span>
        <span class="token string">"minimum_wire_compatibility_version"</span> : <span class="token string">"6.8.0"</span><span class="token punctuation">,</span>
        <span class="token string">"minimum_index_compatibility_version"</span> : <span class="token string">"6.0.0-beta1"</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token string">"tagline"</span> : <span class="token string">"You Know, for Search"</span>
    <span class="token punctuation">}</span>
    <span class="token comment"># 赶紧关闭,增加内存的限制,修改配置文件-e环境配置修改</span>
    docker run <span class="token operator">-</span>d <span class="token operator">--</span>name elasticsearch <span class="token operator">-</span>p 9200:9200 <span class="token operator">-</span>p 9300:9300 <span class="token operator">-</span>e <span class="token string">"discovery.type=single-node"</span> ES_JAVA_OPTS=<span class="token string">"-Xms64m -Xmx512m"</span> elasticsearch:7<span class="token punctuation">.</span>6<span class="token punctuation">.</span>2
    <span class="token comment"># 可以访问成功;查看cpu状态</span>
    </code></pre> 
      <p>作业:使用kibana连接es?思考网络如何才能连接过去!<br> <img src="http://img.e-com-net.com/image/info8/8f37a18732ff41f896ccb919ab20c8e6.jpg" alt="在这里插入图片描述" width="0" height="0"></p> 
      <h2>7. 可视化</h2> 
      <ul> 
       <li>portainer(先用这个)</li> 
      </ul> 
      <pre><code class="prism language-powershell">docker run <span class="token operator">-</span>d <span class="token operator">-</span>p 8088:9000 <span class="token operator">--</span>restart=always <span class="token operator">-</span>v <span class="token operator">/</span><span class="token keyword">var</span><span class="token operator">/</span>run/docker<span class="token punctuation">.</span>sock:<span class="token operator">/</span><span class="token keyword">var</span><span class="token operator">/</span>run/docker<span class="token punctuation">.</span>sock <span class="token operator">--</span>privileged=true portainer/portainer
    </code></pre> 
      <ul> 
       <li>Rancher(CI/CD时再用这个)</li> 
      </ul> 
      <h3>什么是portainer ?</h3> 
      <p>Docker图形化界面管理工具!提供一个后台面板供我们操作!</p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 启动运行</span>
    docker run <span class="token operator">-</span>d <span class="token operator">-</span>p 8088:9000 <span class="token operator">--</span>restart=always <span class="token operator">-</span>v <span class="token operator">/</span><span class="token keyword">var</span><span class="token operator">/</span>run/docker<span class="token punctuation">.</span>sock:<span class="token operator">/</span><span class="token keyword">var</span><span class="token operator">/</span>run/docker<span class="token punctuation">.</span>sock <span class="token operator">--</span>privileged=true portainer/portainer
    </code></pre> 
      <p>访问测试:http://ip:8088<br> <a href="http://img.e-com-net.com/image/info8/0ea629e8fb844ad89af4b4d8fd8620dc.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/0ea629e8fb844ad89af4b4d8fd8620dc.jpg" alt="《狂神说Java》docker教程通俗易懂_第11张图片" width="650" height="406" style="border:1px solid black;"></a><br> 选择本地的:Local<br> <a href="http://img.e-com-net.com/image/info8/9916956a0ac8493bbd4275cd4ed541c5.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/9916956a0ac8493bbd4275cd4ed541c5.jpg" alt="《狂神说Java》docker教程通俗易懂_第12张图片" width="650" height="311" style="border:1px solid black;"></a><br> 进入之后的面板<br> <a href="http://img.e-com-net.com/image/info8/3004a4b29e4c41e7b05c2ed105aaccc3.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/3004a4b29e4c41e7b05c2ed105aaccc3.jpg" alt="《狂神说Java》docker教程通俗易懂_第13张图片" width="650" height="329" style="border:1px solid black;"></a></p> 
      <h1>四、Docker镜像讲解</h1> 
      <h2>1. 镜像是什么</h2> 
      <p>镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。<br> 所有的应用,直接打包docker镜像,就可以直接跑起来!<br> 如何得到镜像:</p> 
      <ul> 
       <li>从远程仓库下载</li> 
       <li>朋友拷贝给你</li> 
       <li>自己制作一个镜像DockerFile</li> 
      </ul> 
      <h2>2. Docker镜像加速原理</h2> 
      <h3>UnionFS(联合文件系统)</h3> 
      <p>我们下载的时候看到的一层层就是这个!<br> UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。</p> 
      <p>特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。</p> 
      <h3>Docker镜像加载原型</h3> 
      <p>docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。</p> 
      <p>bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。</p> 
      <p>rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。<br> rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。<br> <a href="http://img.e-com-net.com/image/info8/6b52e1fc506f487aa7fb8cfaf00d2bc6.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/6b52e1fc506f487aa7fb8cfaf00d2bc6.jpg" alt="《狂神说Java》docker教程通俗易懂_第14张图片" width="650" height="186" style="border:1px solid black;"></a><br> 平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?<br> <a href="http://img.e-com-net.com/image/info8/f305782d15c941d3a32eadf3f1e5ff72.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f305782d15c941d3a32eadf3f1e5ff72.jpg" alt="《狂神说Java》docker教程通俗易懂_第15张图片" width="639" height="130" style="border:1px solid black;"></a><br> 对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。<br> 由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。<br> (虚拟机是分钟级,容器是秒级!)</p> 
      <h2>3. 分层理解</h2> 
      <h3>分层的镜像</h3> 
      <p>我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!<br> <a href="http://img.e-com-net.com/image/info8/c25f064a77854367a35f3952c77217f1.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c25f064a77854367a35f3952c77217f1.jpg" alt="《狂神说Java》docker教程通俗易懂_第16张图片" width="650" height="188" style="border:1px solid black;"></a><br> 思考:为什么Docker镜像要采用这种分层的结构呢?<br> 最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。<br> 查看镜像分层的方式可以通过 docker image inspect命令!</p> 
      <pre><code class="prism language-powershell"><span class="token punctuation">[</span>
    		<span class="token operator">/</span><span class="token operator">/</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
            <span class="token string">"RootFS"</span>: <span class="token punctuation">{</span>
                <span class="token string">"Type"</span>: <span class="token string">"layers"</span><span class="token punctuation">,</span>
                <span class="token string">"Layers"</span>: <span class="token punctuation">[</span>
                    <span class="token string">"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f"</span><span class="token punctuation">,</span>
                    <span class="token string">"sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb"</span><span class="token punctuation">,</span>
                    <span class="token string">"sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1"</span><span class="token punctuation">,</span>
                    <span class="token string">"sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372"</span><span class="token punctuation">,</span>
                    <span class="token string">"sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed"</span><span class="token punctuation">,</span>
                    <span class="token string">"sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"</span>
                <span class="token punctuation">]</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token string">"Metadata"</span>: <span class="token punctuation">{</span>
                <span class="token string">"LastTagTime"</span>: <span class="token string">"0001-01-01T00:00:00Z"</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
    </code></pre> 
      <p><strong>理解:</strong><br> 所有的Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。<br> 举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。<br> 该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。<br> <a href="http://img.e-com-net.com/image/info8/666b15c6f0834a0d83d57ee12a9959c4.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/666b15c6f0834a0d83d57ee12a9959c4.jpg" alt="《狂神说Java》docker教程通俗易懂_第17张图片" width="621" height="383" style="border:1px solid black;"></a><br> 在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。<br> <a href="http://img.e-com-net.com/image/info8/d3801d545c6044d78b13ac0ac1051ceb.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d3801d545c6044d78b13ac0ac1051ceb.jpg" alt="《狂神说Java》docker教程通俗易懂_第18张图片" width="613" height="303" style="border:1px solid black;"></a><br> 上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。<br> 下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。<br> <a href="http://img.e-com-net.com/image/info8/ea1e4f575e8a485899eb0f8190fd2e02.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ea1e4f575e8a485899eb0f8190fd2e02.jpg" alt="《狂神说Java》docker教程通俗易懂_第19张图片" width="648" height="457" style="border:1px solid black;"></a><br> 这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。<br> Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。<br> Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。<br> Docker在Windows 上仅支持 windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。<br> 下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。<br> <a href="http://img.e-com-net.com/image/info8/e361ec357dd94fe587ea0c1c679cc0b8.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/e361ec357dd94fe587ea0c1c679cc0b8.jpg" alt="《狂神说Java》docker教程通俗易懂_第20张图片" width="650" height="191" style="border:1px solid black;"></a></p> 
      <h3>特点</h3> 
      <p>Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!<br> 这一层就是我们通常说的容器层,容器之下的都叫镜像层!<br> <a href="http://img.e-com-net.com/image/info8/f46b31da4d8e4b4295b4d75b2c3993d8.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f46b31da4d8e4b4295b4d75b2c3993d8.jpg" alt="《狂神说Java》docker教程通俗易懂_第21张图片" width="650" height="118" style="border:1px solid black;"></a></p> 
      <h2>4. commit镜像</h2> 
      <pre><code class="prism language-powershell"><span class="token comment"># 提交容器成为一个新的副本</span>
    docker commit 
    <span class="token comment"># 命令和git原理类似</span>
    docker commit <span class="token operator">-</span>m=<span class="token string">"提交的描述信息"</span> <span class="token operator">-</span>a=<span class="token string">"作者"</span> 容器id 目标镜像名:<span class="token namespace">[TAG]</span>
    </code></pre> 
      <h3>实战测试</h3> 
      <pre><code class="prism language-powershell"><span class="token comment"># 1.启动一个默认的tomcat。</span>
    <span class="token comment"># 2.发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的。</span>
    <span class="token comment"># 3.我自己拷贝进去了基本的文件。</span>
    <span class="token comment"># 4.将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像。</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/b0c6a137a2a14c409605fecb4bafda44.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/b0c6a137a2a14c409605fecb4bafda44.jpg" alt="《狂神说Java》docker教程通俗易懂_第22张图片" width="650" height="278" style="border:1px solid black;"></a></p> 
      <p>学习方式说明:理解概念,但是一定要实践,最后实践和理论相结合一次搞定这个知识如果你想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,就好比我们以前学习VM时候,快照!到了这里才算是入门Dokcer!</p> 
      <h1>五、容器数据卷</h1> 
      <h2>1. 什么是容器数据卷</h2> 
      <p><strong>docker的理念回顾</strong><br> 将应用和环境打包成一个镜像!<br> 数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!(需求:数据可以持久化)<br> MySQL,容器删了,删库跑路!(需求:MySQL数据可以存储在本地)<br> 容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!<br> 这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux主机上面!<br> <a href="http://img.e-com-net.com/image/info8/f077450cb9e64fce9d9730be7262c48c.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f077450cb9e64fce9d9730be7262c48c.jpg" alt="《狂神说Java》docker教程通俗易懂_第23张图片" width="622" height="415" style="border:1px solid black;"></a><br> <code>总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!</code></p> 
      <h2>2. 使用数据卷</h2> 
      <h3>直接使用命令来挂载:-v</h3> 
      <pre><code class="prism language-powershell">docker run <span class="token operator">-</span>it <span class="token operator">-</span>v 主机目录:容器内目录 镜像名 <span class="token operator">/</span>bin/bash
    <span class="token comment"># 测试,查看容器信息</span>
    docker inspect 容器id
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/f214a74857da4ba9886b1f8719ade238.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f214a74857da4ba9886b1f8719ade238.jpg" alt="《狂神说Java》docker教程通俗易懂_第24张图片" width="650" height="350" style="border:1px solid black;"></a><br> 测试文件的同步:<br> 在容器的/home文件夹下,新建test.java文件,会同步到主机的/home/ceshi文件夹下。<br> <code>删除操作也是同步的;双向绑定,保证两边文件夹下的数据始终是一直的。</code></p> 
      <p><a href="http://img.e-com-net.com/image/info8/28c7d09d0b5f4868b14010d369a0e49d.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/28c7d09d0b5f4868b14010d369a0e49d.jpg" alt="《狂神说Java》docker教程通俗易懂_第25张图片" width="650" height="110" style="border:1px solid black;"></a><br> 再来测试:<br> 停止容器后,在主机的/home/ceshi文件夹下,修改文件或新增文件,启动容器,查看容器的/home文件夹,发现容器内的数据依旧是同步的</p> 
      <ol> 
       <li>停止容器。</li> 
       <li>宿主机上修改文件。</li> 
       <li>启动容器。</li> 
       <li>容器内的数据依旧是同步的。<br> <a href="http://img.e-com-net.com/image/info8/99d7be9989d9458f99e582b8fc1c10ec.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/99d7be9989d9458f99e582b8fc1c10ec.jpg" alt="《狂神说Java》docker教程通俗易懂_第26张图片" width="650" height="164" style="border:1px solid black;"></a><br> 好处:我们以后修改只需要在本地修改即可,容器内会自动同步!|</li> 
      </ol> 
      <h2>3. 实战:安装mysql</h2> 
      <pre><code class="prism language-powershell"><span class="token comment"># 获取镜像</span>
    docker pull mysql:5<span class="token punctuation">.</span>7
    <span class="token comment"># 运行容器,需要做数据目录挂载。(安装启动mysql,注意:需要配置密码)</span>
    <span class="token comment"># 官方启动mysql</span>
    docker run <span class="token operator">--</span>name some-mysql <span class="token operator">-</span>e MYSQL_ROOT_PASSWORD=my-secret-pw <span class="token operator">-</span>d mysql:tag
    <span class="token comment"># 我们启动mysql(-e是环境配置)</span>
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker run -d -p 7777: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</span>
    
    <span class="token comment"># 启动成功之后,我们在本地使用navicat来接测试一下。</span>
    <span class="token comment"># navicat连接到服务器的7777端口和容器内的3306映射,这个时候我们就可以连接上了!</span>
    <span class="token comment"># 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!(OK的)</span>
    </code></pre> 
      <p>如果我们将容器删除:<br> <a href="http://img.e-com-net.com/image/info8/c5626e7451e0474baa3d7d155327b67f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c5626e7451e0474baa3d7d155327b67f.jpg" alt="《狂神说Java》docker教程通俗易懂_第27张图片" width="650" height="154" style="border:1px solid black;"></a></p> 
      <p>发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!</p> 
      <h2>4. 匿名和具名挂载</h2> 
      <pre><code class="prism language-powershell"><span class="token comment"># 匿名挂载</span>
    docker run <span class="token operator">-</span>d <span class="token operator">-</span>p <span class="token operator">--</span>name nginx01 <span class="token operator">-</span>v <span class="token operator">/</span>etc/nginx nginx
    <span class="token comment"># 查看所有的volume的情况</span>
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker volume ls</span>
    DRIVER    VOLUME NAME
    local     964b8e505f12f65fb23fd21f05cfa9ecd6c2c6b2ca89c0e44f168bb017dfabd6
    <span class="token comment"># 这种就是匿名挂载:我们在-v挂载目录时,只写了容器内的路径,没有写容器外的路径。</span>
    
    <span class="token comment"># 具名挂载</span>
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker run -d -p 3344:80 --name nginx02 -v juming-nginx:/etc/nginx nginx</span>
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker volume ls</span>
    DRIVER    VOLUME NAME
    local     964b8e505f12f65fb23fd21f05cfa9ecd6c2c6b2ca89c0e44f168bb017dfabd6
    local     juming-nginx
    <span class="token comment"># 通过 -v 卷名:容器内的路径(具名挂载)</span>
    <span class="token comment"># 查看一下这个卷</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/0f54ec1c14c44afa88abea8f6e4a95ca.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/0f54ec1c14c44afa88abea8f6e4a95ca.jpg" alt="《狂神说Java》docker教程通俗易懂_第28张图片" width="589" height="185" style="border:1px solid black;"></a><br> 所有的docker容器内的卷,没有指定目录的情况下都是在<code>/var/lib/docker/volumes/xxxx/_data"</code>(xxxx是卷名)<br> 我们通过具名挂载可以方便的找到我们的一个卷,<code>大多数情况在使用的具名挂载</code></p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 如何确定是具名挂载,还是匿名挂载,还是指定路径挂载</span>
    <span class="token operator">-</span>v 容器内的路径				<span class="token comment"># 匿名挂载</span>
    <span class="token operator">-</span>v 卷名:容器内的路径		<span class="token comment"># 具名挂载</span>
    <span class="token operator">-</span>v <span class="token operator">/</span>宿主机路径:容器内路径	<span class="token comment"># 指定路径挂载</span>
    </code></pre> 
      <p>拓展:</p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 通过 -v 容器内的路径:ro	rw	改变读写权限</span>
    ro	read only	<span class="token comment"># 只读</span>
    rw	read <span class="token function">write</span>	<span class="token comment"># 可读可写</span>
    
    <span class="token comment"># 一旦设置了容器权限,容器对我们挂载出来的内容就有了限定。</span>
    docker run <span class="token operator">-</span>d <span class="token operator">-</span>p 3344:80 <span class="token operator">--</span>name nginx02 <span class="token operator">-</span>v juming-nginx:<span class="token operator">/</span>etc/nginx:ro nginx
    docker run <span class="token operator">-</span>d <span class="token operator">-</span>p 3344:80 <span class="token operator">--</span>name nginx02 <span class="token operator">-</span>v juming-nginx:<span class="token operator">/</span>etc/nginx:rw nginx
    <span class="token comment"># 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!</span>
    </code></pre> 
      <h2>5. 初识Dockerfile</h2> 
      <p>Dockerfile就是用来构建 docker 镜像的构建命令!命令脚本!先体验一下!<br> 通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个一个的命令,每个命令都是一层!</p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 创建一个dockerfile文件,名字可以随机,建议dockerfile</span>
    <span class="token comment"># 文件中的内容:指令都是大写</span>
    <span class="token keyword">FROM</span> centos
    VOLUME <span class="token punctuation">[</span><span class="token string">"volume01"</span><span class="token punctuation">,</span><span class="token string">"volume02"</span><span class="token punctuation">]</span>
    CMD <span class="token function">echo</span> <span class="token string">"-----end-----"</span>
    CMD <span class="token operator">/</span>bin/bash
    <span class="token comment"># 这里的每个命令,就是镜像的一层。</span>
    
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/ccf56a4d18be42a48f288436a048370f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/ccf56a4d18be42a48f288436a048370f.jpg" alt="《狂神说Java》docker教程通俗易懂_第29张图片" width="650" height="381" style="border:1px solid black;"></a><br> 启动自己写的容器:<br> <a href="http://img.e-com-net.com/image/info8/2e4c08f0dc6a4ca4b028788b80985002.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/2e4c08f0dc6a4ca4b028788b80985002.jpg" alt="《狂神说Java》docker教程通俗易懂_第30张图片" width="650" height="309" style="border:1px solid black;"></a><br> 这个卷和外部一定有一个同步的目录!<br> <a href="http://img.e-com-net.com/image/info8/5ae70bbf9fc64765abd693bea180db8f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/5ae70bbf9fc64765abd693bea180db8f.jpg" alt="《狂神说Java》docker教程通俗易懂_第31张图片" width="650" height="201" style="border:1px solid black;"></a><br> 查看一下卷挂载的路径:docker inspect 容器id<br> <a href="http://img.e-com-net.com/image/info8/539d5b1aff1d4dea9013678c11836d2f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/539d5b1aff1d4dea9013678c11836d2f.jpg" alt="《狂神说Java》docker教程通俗易懂_第32张图片" width="650" height="234" style="border:1px solid black;"></a><br> 测试一下文件是否同步出去:在容器的volume01文件夹下创建文件,查看宿主机对应目录是否同步成功。<br> <code>这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!</code><br> 如果构建镜像时候没有挂载卷,就需要自己手动镜像挂载目录!</p> 
      <h2>6. 数据卷容器</h2> 
      <p>多个mysql同步数据<br> <a href="http://img.e-com-net.com/image/info8/3437b5ea1209467d9cf49bc7a06567f2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/3437b5ea1209467d9cf49bc7a06567f2.jpg" alt="《狂神说Java》docker教程通俗易懂_第33张图片" width="650" height="203" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 启动3个容器,通过我们刚才自己的写镜像启动。</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/07b0ea9a03ca48ed97776c94c967c786.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/07b0ea9a03ca48ed97776c94c967c786.jpg" alt="《狂神说Java》docker教程通俗易懂_第34张图片" width="650" height="359" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/2c46db2555c74637aef3a7c5e98f6e43.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/2c46db2555c74637aef3a7c5e98f6e43.jpg" alt="《狂神说Java》docker教程通俗易懂_第35张图片" width="650" height="322" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/558b31dc91b9436d8672d6c6c630be00.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/558b31dc91b9436d8672d6c6c630be00.jpg" alt="在这里插入图片描述" width="650" height="99"></a></p> 
      <pre><code class="prism language-powershell"><span class="token comment"># 测试:可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件</span>
    <span class="token comment"># 测试依旧可以访问</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/c82915b53ca84a56972fa44bf2efc197.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c82915b53ca84a56972fa44bf2efc197.jpg" alt="《狂神说Java》docker教程通俗易懂_第36张图片" width="650" height="131" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/251fcfb0b2eb4a9483d1087c65c512a7.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/251fcfb0b2eb4a9483d1087c65c512a7.jpg" alt="《狂神说Java》docker教程通俗易懂_第37张图片" width="650" height="251" style="border:1px solid black;"></a><br> 多个mysql实现数据共享:</p> 
      <pre><code class="prism language-powershell"><span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker run -d -p 7777: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</span>
    
    <span class="token namespace">[root@iZbp13qr3mm4ucsjumrlgqZ ~]</span><span class="token comment"># docker run -d -p 7777:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7</span>
    
    <span class="token comment"># 这个时候,可以实现两个容器数据同步!</span>
    </code></pre> 
      <p>结论:<br> 容器之间配置信息的传递,数据卷容器的生命同期一直持续到没有容器使用为止。<br> 但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!</p> 
      <h1>六、DockerFile</h1> 
      <h2>1. DockerFile介绍</h2> 
      <p>dockerfile是用来构建docker镜像的文件!命令参数脚本!<br> 构建步骤:<br> 1、编写一个dockerfile文件<br> 2、docker build 构建成为一个镜像<br> 3、docker run运行镜像<br> 4、docker push发布镜像(DockerHub、阿里云镜像仓库!)<br> 查看一下官方是怎么做的?<br> <a href="http://img.e-com-net.com/image/info8/7daee6fe17b94ded88d0569ccbdf8a6f.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/7daee6fe17b94ded88d0569ccbdf8a6f.jpg" alt="《狂神说Java》docker教程通俗易懂_第38张图片" width="650" height="328" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/34a72609c79b4401bb2f47a1a98ffa99.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/34a72609c79b4401bb2f47a1a98ffa99.jpg" alt="《狂神说Java》docker教程通俗易懂_第39张图片" width="650" height="252" style="border:1px solid black;"></a></p> 
      <h2>2. DockerFile的构建过程</h2> 
      <h3>基础知识</h3> 
      <p>1、每个保留关键字(指令)都是必须是大写字母<br> 2、执行从上到下顺序执行<br> 3、# 表示注释<br> 4、每一个指令都会创建提交一个新的镜像层,并提交!<br> <a href="http://img.e-com-net.com/image/info8/843308f0a75548589dad4a97a9be7eb9.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/843308f0a75548589dad4a97a9be7eb9.jpg" alt="《狂神说Java》docker教程通俗易懂_第40张图片" width="650" height="458" style="border:1px solid black;"></a><br> dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!<br> Docker镜像逐渐成为企业交付的标准,必须要掌握!<br> 步骤:开发,部署,运维。。。缺一不可!|<br> DockerFile:构建文件,定义了一切的步骤,源代码。<br> Dockerlmages:通过DockerFile构建生成的镜像,最终发布和运行的产品。<br> Docker容器:容器就是镜像运行起来提供服务的。</p> 
      <h2>3. DockerFile的命令</h2> 
      <p>以前的话我们就是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!</p> 
      <pre><code class="prism language-shell">FROM		<span class="token comment"># 基础镜像,一切从这里开始构建</span>
    MAINTAINER	<span class="token comment"># 镜像是谁写的:姓名+邮箱</span>
    RUN			<span class="token comment"># 镜像构建的时候需要运行的命令</span>
    ADD			<span class="token comment"># 步骤:tomcat镜像,这个tomcat压缩包!添加内容</span>
    WORKDIR		<span class="token comment"># 镜像的工作目录</span>
    VOLUME		<span class="token comment"># 挂载的目录</span>
    EXPOSE		<span class="token comment"># 暴露端口配置</span>
    CMD			<span class="token comment"># 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代</span>
    ENTRYPOINT	<span class="token comment"># 指定这个容器启动的时候要运行的命令,可以追加命令</span>
    ONBUILD		<span class="token comment"># 当构建一个被继承DockerFile这个时候就会运行ONBUILD的指令。触发指令。</span>
    COPY		<span class="token comment"># 类似ADD,将我们文件拷贝到镜像中</span>
    ENV			<span class="token comment"># 构建的时候设置环境变量!</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/4fa82478199c4022a5f6025ede8ca1e3.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/4fa82478199c4022a5f6025ede8ca1e3.jpg" alt="《狂神说Java》docker教程通俗易懂_第41张图片" width="650" height="368" style="border:1px solid black;"></a></p> 
      <h2>4. 实战测试</h2> 
      <p>Docker Hub中99%镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行的构建。</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 1. 编写dockerfile的文件</span>
    FROM centos:7
    MAINTAINER sywl<span class="token operator"><</span>xxx@qq.com<span class="token operator">></span>
    
    ENV MYPATH /usr/local
    WORKDIR <span class="token variable">$MYPATH</span>
    
    RUN yum -y <span class="token function">install</span> <span class="token function">vim</span>
    RUN yum -y <span class="token function">install</span> net-tools
    
    EXPOSE <span class="token number">80</span>
    
    CMD <span class="token builtin class-name">echo</span> <span class="token variable">$MYPATH</span>
    CMD <span class="token builtin class-name">echo</span> <span class="token string">"-----end-----"</span>
    CMD /bin/bash
    
    <span class="token comment"># 2. 通过这个文件构建镜像</span>
    <span class="token comment"># 命令:docker build -f dockerfile文件路径 -t 镜像名:[tag]</span>
    <span class="token function">docker</span> build -f mydockerfile-centos -t mycentos:0.1 <span class="token builtin class-name">.</span>
    
    Successfully built 285c2064af01
    Successfully tagged mycentos:0.1
    
    <span class="token comment"># 3. 测试运行</span>
    </code></pre> 
      <p>对比:<br> 之前的原生的centos7:<br> <a href="http://img.e-com-net.com/image/info8/cd6adc394d2f447486e71e886b576366.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/cd6adc394d2f447486e71e886b576366.jpg" alt="《狂神说Java》docker教程通俗易懂_第42张图片" width="648" height="149" style="border:1px solid black;"></a><br> 我们增加之后的镜像:<br> <a href="http://img.e-com-net.com/image/info8/3e64875269754f9fa187d662c5c59f21.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/3e64875269754f9fa187d662c5c59f21.png" alt="《狂神说Java》docker教程通俗易懂_第43张图片" width="694" height="321" style="border:1px solid black;"></a><br> 我们可以列出本地进行的变更历史:docker history 镜像id<br> <a href="http://img.e-com-net.com/image/info8/767d55389fc6445884b96f571235e9c8.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/767d55389fc6445884b96f571235e9c8.png" alt="《狂神说Java》docker教程通俗易懂_第44张图片" width="787" height="216" style="border:1px solid black;"></a></p> 
      <blockquote> 
       <p>CMD和ENTRYPOINT区别</p> 
      </blockquote> 
      <pre><code class="prism language-shell">CMD            <span class="token comment"># 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代</span>
    ENTRYPOINT     <span class="token comment"># 指定这个容器启动的时候要运行的命令,可以追加命令</span>
    </code></pre> 
      <p>测试CMD</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 1. 编写dockerfile文件</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># vim mydockerfile-cmd-test</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># cat mydockerfile-cmd-test</span>
    FROM centos:7
    CMD <span class="token punctuation">[</span><span class="token string">"ls"</span>,<span class="token string">"-a"</span><span class="token punctuation">]</span>
    <span class="token comment"># 2. 构建镜像</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># docker build -f mydockerfile-cmd-test -t cmdtest .</span>
    <span class="token comment"># 3. run运行,发现我们的"ls -a"命令生效、执行</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/bca830eca1ea46ce8e73f3980461283a.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/bca830eca1ea46ce8e73f3980461283a.png" alt="《狂神说Java》docker教程通俗易懂_第45张图片" width="563" height="351" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 4. 我们先追加一个命令"l",构成"ls -al"命令,发现报错</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># docker run ec0d2dd226b3 -l</span>
    docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: <span class="token string">"-l"</span><span class="token builtin class-name">:</span> executable <span class="token function">file</span> not found <span class="token keyword">in</span> <span class="token environment constant">$PATH</span><span class="token builtin class-name">:</span> unknown.
    ERRO<span class="token punctuation">[</span>0000<span class="token punctuation">]</span> error waiting <span class="token keyword">for</span> container: context canceled
    
    <span class="token comment"># 原因:CMD命令的情况下,"-l"替换了CMD["1s","-a"]命令,因为"-l"不是命令,所以报错!</span>
    </code></pre> 
      <p>测试ENTRYPOINT</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 1. 编写dockerfile文件</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># vim mydockerfile-entrypoint-test</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># cat mydockerfile-entrypoint-test</span>
    FROM centos:7
    ENTRYPOINT <span class="token punctuation">[</span><span class="token string">"ls"</span>,<span class="token string">"-a"</span><span class="token punctuation">]</span>
    <span class="token comment"># 2. 构建镜像</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ dockerfile<span class="token punctuation">]</span><span class="token comment"># docker build -f mydockerfile-entrypoint-test -t entrypointtest .</span>
    <span class="token comment"># 3. run运行,发现我们的"ls -a"命令生效、执行</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/fa27c3466f9b469aafeafc66ccfe5022.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/fa27c3466f9b469aafeafc66ccfe5022.png" alt="《狂神说Java》docker教程通俗易懂_第46张图片" width="592" height="351" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 4. 我们先追加一个命令"l",构成"ls -al"命令,发现命令生效、执行</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/fe637062605347afa3ecd229d35c8924.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/fe637062605347afa3ecd229d35c8924.png" alt="《狂神说Java》docker教程通俗易懂_第47张图片" width="612" height="365" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 原因:ENTRYPOINT命令的情况下,"-l"追加在ENTRYPOINT ["1s","-a"]命令后面,得到"ls -al"的命令,所以命令正常执行!</span>
    <span class="token comment"># (我们的追加命令,是直接拼接在我们的ENTRYPOINT命令的后面)</span>
    </code></pre> 
      <h2>5. 制作tomcat镜像</h2> 
      <ol> 
       <li> <p>准备镜像文件:tomcat压缩包,jdk的压缩包!<br> <a href="http://img.e-com-net.com/image/info8/a46b04390d2d47639dfa6e3e6676753c.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/a46b04390d2d47639dfa6e3e6676753c.png" alt="《狂神说Java》docker教程通俗易懂_第48张图片" width="722" height="127" style="border:1px solid black;"></a></p> </li> 
       <li> <p>编写dockerfile文件,官方命名<strong>Dockerfile</strong>,build会自动寻找这个文件,就不需要-f指定文件名了!</p> <pre><code class="prism language-shell">FROM centos:7
    MAINTAINER sywl<span class="token operator"><</span>xxxx@qq.com<span class="token operator">></span>
    
    COPY readme.txt /usr/local/readme.txt
    
    ADD jdk-8u271-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.5.tar.gz /usr/local/
    
    RUN yum -y <span class="token function">install</span> <span class="token function">vim</span>
    
    ENV MYPATH /usr/local
    WORKDIR <span class="token variable">$MYPATH</span>
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_271
    ENV CLASS_PATH <span class="token variable">$JAVA_HOME</span>/lib/dt.jar:<span class="token variable">$JAVA_HOME</span>/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.5
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.5
    ENV <span class="token environment constant">PATH</span> <span class="token environment constant">$PATH</span><span class="token builtin class-name">:</span><span class="token variable">$JAVA_HOME</span>/bin:<span class="token variable">$CATALINA_HOME</span>/lib:<span class="token variable">$CATALINA_HOME</span>/bin
    
    EXPOSE <span class="token number">8080</span>
    
    CMD /usr/local/apache-tomcat-9.0.5/bin/startup.sh <span class="token operator">&&</span> <span class="token function">tail</span> -F /usr/local/apache-tomcat-9.0.5/bin/logs/catalina.out
    </code></pre> </li> 
       <li> <p>构建镜像</p> </li> 
      </ol> 
      <pre><code class="prism language-shell"><span class="token function">docker</span> build --name diytomcat <span class="token builtin class-name">.</span>
    </code></pre> 
      <ol start="4"> 
       <li>启动镜像</li> 
      </ol> 
      <pre><code class="prism language-shell"><span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker run -d -p 3355:8080 --name sywltomcat -v /home/sywl/build/tomcat/test:/usr/local/apache-tomcat-9.0.5/webapps/test -v /home/sywl/build/tomcat/tomcatlog:/usr/local/apache-tomcat-9.0.5/logs diytomcat</span>
    </code></pre> 
      <ol start="5"> 
       <li>访问测试<br> <a href="http://img.e-com-net.com/image/info8/6ba42f4d66c942e4b26dc6c8ae8934cb.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/6ba42f4d66c942e4b26dc6c8ae8934cb.png" alt="《狂神说Java》docker教程通俗易懂_第49张图片" width="762" height="193" style="border:1px solid black;"></a></li> 
       <li>发布项目(由于做了卷挂载,我们直接在本地test文件夹下编写项目就可以发布了!)</li> 
      </ol> 
      <pre><code class="prism language-shell"><span class="token comment"># /home/sywl/build/tomcat/test/WEB-INF/web.xml文件</span>
    <span class="token operator"><</span>?xml <span class="token assign-left variable">version</span><span class="token operator">=</span><span class="token string">"1.0"</span> <span class="token assign-left variable">encoding</span><span class="token operator">=</span><span class="token string">"UTF-8"</span>?<span class="token operator">></span>
    <span class="token operator"><</span>web-app <span class="token assign-left variable">xmlns</span><span class="token operator">=</span><span class="token string">"http://java.sun.com/xml/ns/javaee"</span>
    		xmlns:xsi<span class="token operator">=</span><span class="token string">"http://www.w3.org/2001/XMLSchema-instance"</span>
    		xsi:schemaLocation<span class="token operator">=</span><span class="token string">"http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"</span>
    		<span class="token assign-left variable">version</span><span class="token operator">=</span><span class="token string">"2.5"</span><span class="token operator">></span>
    <span class="token operator"><</span>/web-app<span class="token operator">></span>
    </code></pre> 
      <pre><code class="prism language-shell"><span class="token comment"># /home/sywl/build/tomcat/test/index.jsp文件</span>
    <span class="token operator"><</span>%@ page <span class="token assign-left variable">language</span><span class="token operator">=</span><span class="token string">"java"</span> <span class="token assign-left variable">contentType</span><span class="token operator">=</span><span class="token string">"text/html; charset=UTF-8"</span>
        <span class="token assign-left variable">pageEncoding</span><span class="token operator">=</span><span class="token string">"UTF-8"</span>%<span class="token operator">></span>
    <span class="token operator"><</span><span class="token operator">!</span>DOCTYPE html<span class="token operator">></span>
    <span class="token operator"><</span>html<span class="token operator">></span>
    <span class="token operator"><</span>head<span class="token operator">></span>
    <span class="token operator"><</span>meta <span class="token assign-left variable">charset</span><span class="token operator">=</span><span class="token string">"utf-8"</span><span class="token operator">></span>
    <span class="token operator"><</span>title<span class="token operator">></span>hello,sywl<span class="token operator"><</span>/title<span class="token operator">></span>
    <span class="token operator"><</span>/head<span class="token operator">></span>
    <span class="token operator"><</span>body<span class="token operator">></span>
    Hello World<span class="token operator">!</span><span class="token operator"><</span>br/<span class="token operator">></span>
    <span class="token operator"><</span>%
    System.out.println<span class="token punctuation">(</span><span class="token string">"----my web test----"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    %<span class="token operator">></span>
    <span class="token operator"><</span>/body<span class="token operator">></span>
    <span class="token operator"><</span>/html<span class="token operator">></span>
    </code></pre> 
      <p>发现:项目部署成功,可以直接访问ok!(ip地址:3355/test)<br> 我们以后开发的步骤:需要掌握Dokcerfile的编写!我们之后的一切都是使用docker镜像来发布运行!</p> 
      <h2>6. 发布自己的镜像</h2> 
      <h3>1. 发布到dockerhub上</h3> 
      <ol> 
       <li>https://hub.docker.com/ 注册自己的账号</li> 
       <li>确定这个账号可以登录</li> 
       <li>在我们服务器上提交自己的镜像<pre><code class="prism language-shell"><span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker login --help</span>
    
    Usage:  <span class="token function">docker</span> login <span class="token punctuation">[</span>OPTIONS<span class="token punctuation">]</span> <span class="token punctuation">[</span>SERVER<span class="token punctuation">]</span>
    
    Log <span class="token keyword">in</span> to a Docker registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
      -p, --password string   Password
    	  --password-stdin    Take the password from stdin
      -u, --username string   Username
    
    </code></pre> </li> 
       <li>登录完毕后就可以提交镜像了,就是一步: docker push<pre><code class="prism language-shell"><span class="token comment"># 登录命令</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker login -u xxxx</span>
    Password:
    WARNING<span class="token operator">!</span> Your password will be stored unencrypted <span class="token keyword">in</span> /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/<span class="token comment">#credentials-store</span>
    
    Login Succeeded
    
    <span class="token comment"># push镜像出现的问题?</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker push sunyiwenlong/diytomcat</span>
    The push refers to repository <span class="token punctuation">[</span>docker.io/sunyiwenlong/diytomcat<span class="token punctuation">]</span>
    An image does not exist locally with the tag: sunyiwenlong/diytomcat
    
    <span class="token comment"># 解决,增加一个tag</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker tag 6a5eb12e1252 账号id/tomcat:1.0</span>
    
    <span class="token comment"># docker push即可;自己发布的镜像尽量带上版本号</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ tomcat<span class="token punctuation">]</span><span class="token comment"># docker push 账号id/tomcat:1.0</span>
    </code></pre> </li> 
      </ol> 
      <h3>2. 发布到阿里云镜像服务上</h3> 
      <ol> 
       <li>登录阿里云账号</li> 
       <li>找到镜像容器服务</li> 
       <li>创建命名空间(一个账号只能创建3个命名空间)</li> 
       <li>创建镜像仓库</li> 
       <li>浏览相关操作命令</li> 
      </ol> 
      <h2>7. 小结</h2> 
      <p><a href="http://img.e-com-net.com/image/info8/b34d58e9e30a42d2b4d4c01a0d6552af.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/b34d58e9e30a42d2b4d4c01a0d6552af.jpg" alt="《狂神说Java》docker教程通俗易懂_第50张图片" width="650" height="536" style="border:1px solid black;"></a></p> 
      <h1>七、Docker网络</h1> 
      <h2>1. 理解docker0</h2> 
      <h3>测试</h3> 
      <p><a href="http://img.e-com-net.com/image/info8/8746f35195bd4e9ebb2775a2de2b3587.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/8746f35195bd4e9ebb2775a2de2b3587.png" alt="《狂神说Java》docker教程通俗易懂_第51张图片" width="814" height="292" style="border:1px solid black;"></a><br> 有三个网络</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 问题:docker是如何处理容器网络访问的?</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/2babf44c8207438388310aa4d4d0328d.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/2babf44c8207438388310aa4d4d0328d.jpg" alt="《狂神说Java》docker教程通俗易懂_第52张图片" width="650" height="146" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker run -d -P --name tomcat01 tomcat</span>
    
    <span class="token comment"># 查看容器的内部网络地址ip addr,发现容器启动的时候会得到一个eth0@if119的ip地址(docker分配的)</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat01 ip addr</span>
    <span class="token number">1</span>: lo: <span class="token operator"><</span>LOOPBACK,UP,LOWER_UP<span class="token operator">></span> mtu <span class="token number">65536</span> qdisc noqueue state UNKNOWN group default qlen <span class="token number">1000</span>
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet <span class="token number">127.0</span>.0.1/8 scope <span class="token function">host</span> lo
           valid_lft forever preferred_lft forever
    <span class="token number">118</span>: eth0@if119: <span class="token operator"><</span>BROADCAST,MULTICAST,UP,LOWER_UP<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid <span class="token number">0</span>
        inet <span class="token number">172.17</span>.0.2/16 brd <span class="token number">172.17</span>.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    
    <span class="token comment"># 思考:liunx能不能ping通容器内部?(linux可以ping通容器内部)</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># ping 172.17.0.2</span>
    PING <span class="token number">172.17</span>.0.2 <span class="token punctuation">(</span><span class="token number">172.17</span>.0.2<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.059</span> ms
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.046</span> ms
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">3</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.057</span> ms
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">4</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.045</span> ms
    </code></pre> 
      <h3>原理</h3> 
      <ol> 
       <li>我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了ddcker,就会有一个网卡docker0<br> (桥接模式,使用的技术是veth-pair技术)<br> 再次测试:<br> <a href="http://img.e-com-net.com/image/info8/55645017017a43cca9f207ba9dc775b3.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/55645017017a43cca9f207ba9dc775b3.png" alt="《狂神说Java》docker教程通俗易懂_第53张图片" width="949" height="352" style="border:1px solid black;"></a></li> 
       <li>在启动一个容器测试,发现又多了一对网卡。<br> <a href="http://img.e-com-net.com/image/info8/416d9549c1804ad0820353ca15088d6a.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/416d9549c1804ad0820353ca15088d6a.png" alt="《狂神说Java》docker教程通俗易懂_第54张图片" width="775" height="143" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/fe74249ccfa4431d8ed0a32f6af560ee.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/fe74249ccfa4431d8ed0a32f6af560ee.jpg" alt="《狂神说Java》docker教程通俗易懂_第55张图片" width="650" height="277" style="border:1px solid black;"></a></li> 
      </ol> 
      <pre><code class="prism language-shell"><span class="token comment"># 我们发现这个容器带来网卡,都是一对对的。</span>
    <span class="token comment"># veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连。</span>
    <span class="token comment"># 正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的。</span>
    <span class="token comment"># openstack,Docker容器之间的连接,OVS的连接,都是使用veth-pair技术。</span>
    </code></pre> 
      <ol start="3"> 
       <li>我们来测试下tomcat01和tomcat02是否可以ping通!(可以ping通)<pre><code class="prism language-shell"><span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat02 ping 172.17.0.2</span>
    PING <span class="token number">172.17</span>.0.2 <span class="token punctuation">(</span><span class="token number">172.17</span>.0.2<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.094</span> ms
    <span class="token number">64</span> bytes from <span class="token number">172.17</span>.0.2: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.055</span> ms
    
    <span class="token comment"># 结论:容器和容器之间是可以互相ping通的!</span>
    </code></pre> 绘制一个网络模型图<br> <a href="http://img.e-com-net.com/image/info8/4bc046a085ae49b49347a8be1b410d84.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/4bc046a085ae49b49347a8be1b410d84.jpg" alt="《狂神说Java》docker教程通俗易懂_第56张图片" width="650" height="419" style="border:1px solid black;"></a><br> 结论:tomcat01和tomcat02是公用的一个路由器,dockero。<br> 所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP</li> 
      </ol> 
      <p><a href="http://img.e-com-net.com/image/info8/14b963cc7ff64dc391072c9bdbee179e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/14b963cc7ff64dc391072c9bdbee179e.jpg" alt="《狂神说Java》docker教程通俗易懂_第57张图片" width="650" height="482" style="border:1px solid black;"></a><br> Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件!)<br> 只要容器删除,对应网桥一对就没了!<br> <a href="http://img.e-com-net.com/image/info8/60c810916717434ca9a07b939bcd7160.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/60c810916717434ca9a07b939bcd7160.png" alt="《狂神说Java》docker教程通俗易懂_第58张图片" width="664" height="348" style="border:1px solid black;"></a></p> 
      <h2>2. --link</h2> 
      <h3>思考一个场景(高可用)</h3> 
      <p>我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 通过服务名ping不通;如何解决?</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat02 ping tomcat01</span>
    ping: tomcat01: Name or <span class="token function">service</span> not known
    
    <span class="token comment"># 通过--link可以解决网络连接问题。</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker run -d -P --name tomcat03 --link tomcat02 tomcat:7.0</span>
    2393eecb870e5755068ea8b7d8bdcdd0f1ff110534c3359384413677c651bec4
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat03 ping tomcat02</span>
    PING tomcat02 <span class="token punctuation">(</span><span class="token number">172.17</span>.0.3<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from tomcat02 <span class="token punctuation">(</span><span class="token number">172.17</span>.0.3<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.085</span> ms
    <span class="token number">64</span> bytes from tomcat02 <span class="token punctuation">(</span><span class="token number">172.17</span>.0.3<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.055</span> ms
    
    <span class="token comment"># 反向可以ping通吗?(不可以)</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat02 ping tomcat03</span>
    ping: tomcat03: Name or <span class="token function">service</span> not known
    </code></pre> 
      <p>探究:docker network inspect networkID (docker network ls可以查看networkID)<br> <a href="http://img.e-com-net.com/image/info8/960da69377414bc5adb1c086ce162e5b.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/960da69377414bc5adb1c086ce162e5b.png" alt="《狂神说Java》docker教程通俗易懂_第59张图片" width="762" height="360" style="border:1px solid black;"></a><br> 其实这个tomcat03就是在本地配置了tomcat02的配置?</p> 
      <pre><code class="prism language-shell"><span class="token comment"># 查看</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat03 cat /etc/hosts</span>
    <span class="token number">127.0</span>.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
    <span class="token number">172.17</span>.0.3      tomcat02 20398a94efa7
    <span class="token number">172.17</span>.0.4      2393eecb870e
    </code></pre> 
      <p>本质探究:–link 就是我们在hosts配置中增加了一个"172.17.0.3 tomcat02 20398a94efa7"<br> 我们现在玩Docker已经不建议使用–link了!<br> 自定义网络!不适用docker0!<br> docker0问题:他不支持容器名连接访问!</p> 
      <h2>3. 自定义网络</h2> 
      <h3>查看所有的docker网络</h3> 
      <p><a href="http://img.e-com-net.com/image/info8/704a97b1c9044ef691ff71df0d56b0e0.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/704a97b1c9044ef691ff71df0d56b0e0.png" alt="" width="443" height="82"></a></p> 
      <h3>网络模式</h3> 
      <p>bridge:桥接 docker(默认,自己创建也使用bridge桥接模式)<br> none:不配置网络<br> host:和主机共享网络<br> container:容器网络连通!(用的少!局限很大)</p> 
      <h3>测试</h3> 
      <pre><code class="prism language-shell"><span class="token comment"># 我们直接启动的命令--net bridge(这个就是我们的docker0);默认带上这个参数的,以下两种启动方式效果一致。</span>
    <span class="token function">docker</span> run -d -P --name tomcat01 tomcat
    <span class="token function">docker</span> run -d -P --name tomcato1 --het bridge tomcat
    
    <span class="token comment"># docker0特点:默认,域名不能访问,--1ink可以打通连接!</span>
    <span class="token comment"># 我们可以自定义一个网络!</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker network ls</span>
    NETWORK ID     NAME      DRIVER    SCOPE
    7254ffccbdf5   bridge    bridge    <span class="token builtin class-name">local</span>
    45610891738f   <span class="token function">host</span>      <span class="token function">host</span>      <span class="token builtin class-name">local</span>
    266acd66473c   mynet     bridge    <span class="token builtin class-name">local</span>
    7795cbc2686c   none      null      <span class="token builtin class-name">local</span>
    </code></pre> 
      <p>我们自己的网络就创建好了<br> <a href="http://img.e-com-net.com/image/info8/001000c11ae64378ae5e635f480ac2bc.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/001000c11ae64378ae5e635f480ac2bc.png" alt="《狂神说Java》docker教程通俗易懂_第60张图片" width="652" height="472" style="border:1px solid black;"></a><br> 启动两个容器测试:</p> 
      <pre><code class="prism language-shell"><span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker run -d -P --name tomcat-net-01 --net mynet tomcat:7.0</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker run -d -P --name tomcat-net-02 --net mynet tomcat:7.0</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/094abbb9eec345d1abc87bf415c08cf1.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/094abbb9eec345d1abc87bf415c08cf1.png" alt="《狂神说Java》docker教程通俗易懂_第61张图片" width="805" height="693" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 不使用--link,ping名字也可以ping通。tomcat-net-01 ping tomcat-net-02可以ping通</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat-net-01 ping tomcat-net-02</span>
    PING tomcat-net-02 <span class="token punctuation">(</span><span class="token number">192.168</span>.0.3<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from tomcat-net-02.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.3<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.067</span> ms
    <span class="token number">64</span> bytes from tomcat-net-02.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.3<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.056</span> ms
    <span class="token comment"># 不使用--link,ping名字也可以ping通。tomcat-net-02 ping tomcat-net-01可以ping通</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat-net-02 ping tomcat-net-01</span>
    PING tomcat-net-01 <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from tomcat-net-01.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.050</span> ms
    <span class="token number">64</span> bytes from tomcat-net-01.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.056</span> ms
    </code></pre> 
      <p>我们自定义的网络docker都已经帮我们维护好了对应的关系,<strong>推荐我们平时这样使用网络</strong>!<br> redis -不同的集群使用不同的网络,保证集群是安全和健康的<br> mysql -不同的集群使用不同的网络,保证集群是安全和健康的</p> 
      <h2>4. 网络连通</h2> 
      <pre><code class="prism language-shell"><span class="token comment"># tomcat01在docker0网络下,tomcat-net-01在mynet网络下;</span>
    <span class="token comment"># tomcat01 ping tomcat-net-01是ping不通的</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat01 ping tomcat-net-01</span>
    ping: tomcat-net-01: Name or <span class="token function">service</span> not known
    </code></pre> 
      <p>容器和mynet网络需要打通<br> <a href="http://img.e-com-net.com/image/info8/501ff82a37f645c381c4c02d3b86917b.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/501ff82a37f645c381c4c02d3b86917b.jpg" alt="《狂神说Java》docker教程通俗易懂_第62张图片" width="650" height="398" style="border:1px solid black;"></a><br> 打通命令<br> <a href="http://img.e-com-net.com/image/info8/2eaac3349ad44d3b863d38cc48326558.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/2eaac3349ad44d3b863d38cc48326558.png" alt="《狂神说Java》docker教程通俗易懂_第63张图片" width="598" height="246" style="border:1px solid black;"></a><br> <a href="http://img.e-com-net.com/image/info8/31c04e6dc2c842eea07186e512965557.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/31c04e6dc2c842eea07186e512965557.png" alt="《狂神说Java》docker教程通俗易懂_第64张图片" width="639" height="195" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 测试:打通tomcat01连接mynet</span>
    <span class="token function">docker</span> network connect mynet tomcat01
    
    <span class="token comment"># 连通之后就是将tomcat01放到了mynet网络下</span>
    <span class="token comment"># 一个容器两个ip地址!I</span>
    <span class="token comment"># 阿里云服务:公网ip和私网ip</span>
    </code></pre> 
      <p><a href="http://img.e-com-net.com/image/info8/6871ca9677f142f7a0266a603b6d0ee2.png" target="_blank"><img src="http://img.e-com-net.com/image/info8/6871ca9677f142f7a0266a603b6d0ee2.png" alt="《狂神说Java》docker教程通俗易懂_第65张图片" width="801" height="795" style="border:1px solid black;"></a></p> 
      <pre><code class="prism language-shell"><span class="token comment"># 连接ok</span>
    <span class="token punctuation">[</span>root@iZbp13qr3mm4ucsjumrlgqZ ~<span class="token punctuation">]</span><span class="token comment"># docker exec -it tomcat01 ping tomcat-net-01</span>
    PING tomcat-net-01 <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span> <span class="token number">56</span><span class="token punctuation">(</span><span class="token number">84</span><span class="token punctuation">)</span> bytes of data.
    <span class="token number">64</span> bytes from tomcat-net-01.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">1</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.065</span> ms
    <span class="token number">64</span> bytes from tomcat-net-01.mynet <span class="token punctuation">(</span><span class="token number">192.168</span>.0.2<span class="token punctuation">)</span>: <span class="token assign-left variable">icmp_seq</span><span class="token operator">=</span><span class="token number">2</span> <span class="token assign-left variable">ttl</span><span class="token operator">=</span><span class="token number">64</span> <span class="token assign-left variable">time</span><span class="token operator">=</span><span class="token number">0.052</span> ms
    </code></pre> 
      <p>结论:假设要跨网络操作别人,就需要使用docker network connect连通!。。。。</p> 
      <h2>5. 实战:部署redis集群</h2> 
      <h1>八、SpringBoot微服务打包docker镜像</h1> 
     </div> 
    </div>
                                </div>
                            </div>
                        </div>
                        <!--PC和WAP自适应版-->
                        <div id="SOHUCS" sid="1587700000220000256"></div>
                        <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                        <!-- 文章页-底部 动态广告位 -->
                        <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                    </div>
                    <div class="col-md-3">
                        <div class="row" id="ad">
                            <!-- 文章页-右侧1 动态广告位 -->
                            <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                            </div>
                            <!-- 文章页-右侧2 动态广告位 -->
                            <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                            </div>
                            <!-- 文章页-右侧3 动态广告位 -->
                            <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="container">
            <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(狂神课程笔记,docker,java,容器)</h4>
            <div id="paradigm-article-related">
                <div class="recommend-post mb30">
                    <ul class="widget-links">
                        <li><a href="/article/1773586592385007616.htm"
                               title="天猫超市优惠获取渠道,天猫超市内部优惠劵领取方法使用教程" target="_blank">天猫超市优惠获取渠道,天猫超市内部优惠劵领取方法使用教程</a>
                            <span class="text-muted">氧惠全网优惠</span>
    
                            <div>天猫超市是一个不错的购物平台,满足用户所需,基本次日达,很方便的购物平台,那么有人问我,天猫超市优惠获取渠道在哪?怎么能够优惠的购买,今天分享给大家;1、天猫超市优惠券抢好券:天猫超市首页每天可以领取满199减30、满235减35、满299减50、满399减60、满166减30等优惠券,领劵方法复制下条口令打开淘宝进入领劵会场;隐藏神券、实时爆款、天天更新!戳>(CZ9185ZatcdhNADlJ</div>
                        </li>
                        <li><a href="/article/1773582305621770240.htm"
                               title="华为OD机试 - 单向链表中间节点(Java & JS & Python & C & C++)" target="_blank">华为OD机试 - 单向链表中间节点(Java & JS & Python & C & C++)</a>
                            <span class="text-muted">华为OD题库</span>
    <a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/%E9%93%BE%E8%A1%A8/1.htm">链表</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                            <div>须知哈喽,本题库完全免费,收费是为了防止被爬,大家订阅专栏后可以私信联系退款。感谢支持文章目录须知题目描述输出描述解析代码题目描述给定一个单链表L,请编写程序输出L中间结点保存的数据。如果有两个中间结点,则输出第二个中间结点保存的数据。例如:给定L为1→7→5,则输出应该为7;给定L为1→2→3→4,则输出应该为3;输入描述每个输入包含1个测试用例。每个测试用例:第一行给出链表首结点的地址、结点总</div>
                        </li>
                        <li><a href="/article/1773578026081124352.htm"
                               title="学习JavaEE的日子 Day32 线程池" target="_blank">学习JavaEE的日子 Day32 线程池</a>
                            <span class="text-muted">A 北枝</span>
    <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0JavaEE/1.htm">学习JavaEE</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/java-ee/1.htm">java-ee</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B%E6%B1%A0/1.htm">线程池</a>
                            <div>Day32线程池1.引入一个线程完成一项任务所需时间为:创建线程时间-Time1线程中执行任务的时间-Time2销毁线程时间-Time32.为什么需要线程池(重要)线程池技术正是关注如何缩短或调整Time1和Time3的时间,从而提高程序的性能。项目中可以把Time1,T3分别安排在项目的启动和结束的时间段或者一些空闲的时间段线程池不仅调整Time1,Time3产生的时间段,而且它还显著减少了创建</div>
                        </li>
                        <li><a href="/article/1773572474143834112.htm"
                               title="❤️ 美娟 感恩福记 32/365" target="_blank">❤️ 美娟 感恩福记 32/365</a>
                            <span class="text-muted">让一切都成为你的助力</span>
    
                            <div>感恩信守承诺完成✅的一天感恩连睡梦中都惦记着“感恩”,夜晚睡的香甜,好感恩,谢谢感恩好手艺,营养早餐,开启了美好的一天感恩感恩健身,让自己的身体肌肉变得结实,painisweaknessleavingthebody!痛苦会让软弱离开身体!好棒的,渐渐爱上燃烧脂肪的感觉,喜欢精气神饱满的自己感恩感恩奶奶的夸赞,把堉哥哥买给奶奶的蚕丝被邮寄回去了,奶奶很高兴,有人惦记着她,也是因为奶奶智慧的规劝,才遇</div>
                        </li>
                        <li><a href="/article/1773559735694458880.htm"
                               title="有一种失去叫做得不到" target="_blank">有一种失去叫做得不到</a>
                            <span class="text-muted">野风狂生</span>
    
                            <div>图片发自App有一种失去叫做得不到野风狂生(20190130)有一种失去叫做得不到失去的是希望是前进的方向是奋斗的动力是奇迹的召唤纵然有一天将其释怀遗憾的残迹却永留心底得不到有时也会心痛仿佛沙漠里远望着的一泓甘泉十米处被他人喝干涸仿佛黑洞里疲惫追逐的火焰在握住前一秒耗尽光明仿佛风雪彻骨的冬天被人剥剩至赤裸而夜行山莽埋葬未曾示面的野心有谁还会去祭奠不用问我问我也无可奉告不用问你问你也缄默不言去拥抱那</div>
                        </li>
                        <li><a href="/article/1773520124586819584.htm"
                               title="helm 部署 Kube-Prometheus + Grafana + 钉钉告警部署 Kube-Prometheus" target="_blank">helm 部署 Kube-Prometheus + Grafana + 钉钉告警部署 Kube-Prometheus</a>
                            <span class="text-muted">zxj19880502</span>
    <a class="tag" taget="_blank" href="/search/grafana/1.htm">grafana</a><a class="tag" taget="_blank" href="/search/prometheus/1.htm">prometheus</a>
                            <div>背景角色IPK8S版本容器运行时k8s-master-1172.16.16.108v1.24.1containerd://1.6.8k8s-node-1172.16.16.109v1.24.1containerd://1.6.8k8s-node-2172.16.16.110v1.24.1containerd://1.6.8安装kube-prometheusmkdir-p/data/yaml/kub</div>
                        </li>
                        <li><a href="/article/1773510684068347904.htm"
                               title="请简单介绍一下Shiro框架是什么?Shiro在Java安全领域的主要作用是什么?Shiro主要提供了哪些安全功能?" target="_blank">请简单介绍一下Shiro框架是什么?Shiro在Java安全领域的主要作用是什么?Shiro主要提供了哪些安全功能?</a>
                            <span class="text-muted">AaronWang94</span>
    <a class="tag" taget="_blank" href="/search/shiro/1.htm">shiro</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                            <div>请简单介绍一下Shiro框架是什么?Shiro框架是一个强大且灵活的开源安全框架,为Java应用程序提供了全面的安全解决方案。它主要用于身份验证、授权、加密和会话管理等功能,可以轻松地集成到任何JavaWeb应用程序中,并提供了易于理解和使用的API,使开发人员能够快速实现安全特性。Shiro的核心组件包括Subject、SecurityManager和Realms。Subject代表了当前与应用</div>
                        </li>
                        <li><a href="/article/1773510078264049664.htm"
                               title="我到人间走一趟" target="_blank">我到人间走一趟</a>
                            <span class="text-muted">常清净</span>
    
                            <div>我到人间走一趟爱恨情仇尝一尝看着你多情的目光无情的我心头也有些迷茫看着你如此惆怅不屑一顾的我不忍再让你忧伤既然已经来到了凡尘之上又怎能一尘不染地度春光扯一段霓虹遮挡住那道灵光撒一把红尘模糊那个真相我是人,不是神是人就会恋红尘都说人生就是一场戏转身我拿起了一个面具准备和你好好地演上一场戏哪怕最终没有了记忆阿赖耶识里却都会留下印记只要还在轮回里我们就会三生三世十里桃花再相遇桃花开时来相聚</div>
                        </li>
                        <li><a href="/article/1773504260386914304.htm"
                               title="通俗易懂:什么是Java虚拟机(JVM)?它的主要作用是什么?" target="_blank">通俗易懂:什么是Java虚拟机(JVM)?它的主要作用是什么?</a>
                            <span class="text-muted">大龄下岗程序员</span>
    <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a>
                            <div>Java虚拟机(JavaVirtualMachine,JVM)是一种软件实现的抽象计算机,它负责执行Java字节码(Bytecode)。Java程序并不是直接在物理计算机上运行,而是先由Java编译器将源代码编译成与平台无关的字节码,然后由JVM负责读取字节码并在实际硬件架构上运行。JVM的主要作用包括以下几个方面:1.跨平台性-JVM是Java语言“一次编写,到处运行”(WriteOnce,Ru</div>
                        </li>
                        <li><a href="/article/1773495574226599936.htm"
                               title="3、JavaWeb-Ajax/Axios-前端工程化-Element" target="_blank">3、JavaWeb-Ajax/Axios-前端工程化-Element</a>
                            <span class="text-muted">所谓远行Misnearch</span>
    <a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/JavaWeb/1.htm">JavaWeb</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/elementui/1.htm">elementui</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
                            <div>P34Ajax介绍Ajax:AsynchroousJavaScriptAndXML,异步的JS和XMLJS网页动作,XML一种标记语言,存储数据,作用:数据交换:通过Ajax给服务器发送请求,并获取服务器响应的数据异步交互:在不重新加载整个页面的情况下,与服务器交换数据并实现更新部分网页的技术,例如:搜索联想、用户名是否可用的校验等等。同步与异步:同步:服务器在处理中客户端要处于等待状态,输入域名</div>
                        </li>
                        <li><a href="/article/1773495447948689408.htm"
                               title="docker怎么端口映射" target="_blank">docker怎么端口映射</a>
                            <span class="text-muted">Lance_mu</span>
    <a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a>
                            <div>1、默认固定的端口#Web服务器:WebApache或Nginx通常使用80端口HTTP:80HTTPS:443#数据库服务器MySQL:3306PostgreSQL:5432MongoDB:27017Redis:6379#邮件服务器SMTP:25POP3:110IMAP:143#其他服务SSH:22FTP:21DNS(域名解析):53代理服务器Squid:3128版本控制系统Git:9418(S</div>
                        </li>
                        <li><a href="/article/1773489909345091584.htm"
                               title="docker基础(一)" target="_blank">docker基础(一)</a>
                            <span class="text-muted">运维搬运工</span>
    <a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8-docker/1.htm">容器-docker</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a>
                            <div>相关概念介绍Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖到一个可移植的容器中,然后发布到任何流行的linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,互相之间不会有任何接口。Docker有几个重要概念:dockerfile,配置文件,用来生成dockerimagedockerimage,交付部署的最小单元docker命令与API,定义命令与接口,支持第三方系统集</div>
                        </li>
                        <li><a href="/article/1773489024493748224.htm"
                               title="傲娇||这几年我追过五月天的那几场演唱会" target="_blank">傲娇||这几年我追过五月天的那几场演唱会</a>
                            <span class="text-muted">进击的嘉欣大小姐</span>
    
                            <div>一直想要认真的去思考这件事情,码字说一下这几年我追过的那几场五月天演唱会,作为入坑手帐的我,做过美食手帐、旅行手帐、电影手帐、日常手帐,唯独一直没有写过我的追星手帐,票根就一直存留着,周边不断买买买,但是依旧没有狠下心去写自己的一路追演唱会的感觉。2012.5.26–南宁自出娘胎的二十多年来第一场演唱会就是五月天诺亚方舟巡回南宁场,最惊心动魄的一场,从此进入五月天的神坑无法自拔,那是毕业出来的工作</div>
                        </li>
                        <li><a href="/article/1773436409693143040.htm"
                               title="枚举使用笔记" target="_blank">枚举使用笔记</a>
                            <span class="text-muted">万变不离其宗_8</span>
    <a class="tag" taget="_blank" href="/search/%E9%A1%B9%E7%9B%AE%E7%AC%94%E8%AE%B0/1.htm">项目笔记</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                            <div>1.java枚举怎么放在方法上面的注释里面/***保存*@paramuserId用户id*@paramtype见枚举{@linkcom.common.enums.TypeEnum}*@return*/voidsave(LonguserId,Stringtype);</div>
                        </li>
                        <li><a href="/article/1773413750980804608.htm"
                               title="linux安装docker及docker-compose 部署spring boot项目" target="_blank">linux安装docker及docker-compose 部署spring boot项目</a>
                            <span class="text-muted">时而有事儿</span>
    <a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a>
                            <div>linux系统环境:centos5.14本篇描述的是在centos系统版本下安装docker,如果是ubuntu版本,请看这篇文章:linuxubuntu20安装docker和docker-compose-CSDN博客正文:安装docker和docker-compose安装docker---------运行命名等待安装完成遇到选择直接输入yyuminstall-yyum-utilsdevice-m</div>
                        </li>
                        <li><a href="/article/1773403175781466112.htm"
                               title="Python dict字符串转json对象,小数精度丢失问题" target="_blank">Python dict字符串转json对象,小数精度丢失问题</a>
                            <span class="text-muted">朝如青丝 暮成雪</span>
    <a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                            <div>一前言JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,dict是Python的一种数据格式。本篇介绍一个float数据转换时精度丢失的案例。二问题描述importjsontest_str1='{"π":3.1415926535897932384626433832795028841971}'test_str2='{"value":10.00000}'print</div>
                        </li>
                        <li><a href="/article/1773382031552610304.htm"
                               title="java实体中返回前端的double类型四舍五入(格式化)" target="_blank">java实体中返回前端的double类型四舍五入(格式化)</a>
                            <span class="text-muted">婲落ヽ紅顏誶</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                            <div>根据业务,需要通过后端给前端返回部分double类型的数值,一般需要保留两位小数,使用jackson转换对象packagecom.ruoyi.common.core.config;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.f</div>
                        </li>
                        <li><a href="/article/1773366674838323200.htm"
                               title="k8s入门到实战(十)—— CronJob详细介绍及使用示例" target="_blank">k8s入门到实战(十)—— CronJob详细介绍及使用示例</a>
                            <span class="text-muted">一弓虽</span>
    <a class="tag" taget="_blank" href="/search/k8s%E5%AD%A6%E4%B9%A0/1.htm">k8s学习</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/%E4%BA%91%E5%8E%9F%E7%94%9F/1.htm">云原生</a>
                            <div>CronJob什么是CronJob在k8s中,CronJob是一种用于定期执行任务的资源对象。它基于Cron表达式,允许您在指定的时间间隔内自动运行容器化的任务。CronJob可以定义以下属性:schedule:指定任务执行的时间表,使用标准的Cron表达式语法。例如,“0****”表示每小时执行一次任务。jobTemplate:定义要执行的任务的模板,通常是一个Pod模板。这个模板包含了任务所需</div>
                        </li>
                        <li><a href="/article/1773365103316500480.htm"
                               title="泡面" target="_blank">泡面</a>
                            <span class="text-muted">陆一飞</span>
    
                            <div>今天,阳光明媚,晴空万里。妈妈让我给她泡面,我欣然应允。妈妈说了泡面的几个步骤,千叮万嘱之后,便去洗衣服了。我拿起一包老坛酸菜面,拆开放进碗中,放好调料后,便喜滋滋地端进了微波炉。按了“五分钟”后,我欣喜若狂地守在微波炉旁。可是料想不到的事发生了,一分钟、二分钟、三分钟时,微波炉里竟然飘出了一股焦臭味。我急了,可又不敢打开微波炉的门。漫长的五分钟终于过去了,微波炉“叮”的一声,我心惊胆战地打开炉门</div>
                        </li>
                        <li><a href="/article/1773359500359696384.htm"
                               title="Java中HashMap底层数据结构及主要参数?" target="_blank">Java中HashMap底层数据结构及主要参数?</a>
                            <span class="text-muted">山间漫步人生路</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                            <div>在Java中,HashMap的底层数据结构主要基于数组和链表,同时在Java8及以后的版本中,当链表长度超过一定阈值时,链表会转换为红黑树来优化性能。这种结构结合了数组和链表的优点,既提供了快速的随机访问,又允许动态地扩展存储桶的大小。HashMap的主要参数包括:初始容量(InitialCapacity):这是HashMap在创建时设定的桶数组的大小。默认值为16。这个值可以根据预计存储的键值对</div>
                        </li>
                        <li><a href="/article/1773351821931249664.htm"
                               title="Java学习笔记01" target="_blank">Java学习笔记01</a>
                            <span class="text-muted">.wsy.</span>
    <a class="tag" taget="_blank" href="/search/%E6%97%A5%E5%B8%B8/1.htm">日常</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                            <div>1.1Java简介Java的前身是Oak,詹姆斯·高斯林是java之父。1.2Java体系Java是一种与平台无关的语言,其源代码可以被编译成一种结构中立的中间文件(.class,字节码文件)于Java虚拟机上运行。1.2.3专有名词JDK提供编译、运行Java程序所需要的种种工具及资源。JRE是运行Java所依赖的环境的集合。JVM是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功</div>
                        </li>
                        <li><a href="/article/1773340995031728128.htm"
                               title="Java回溯知识点(含面试大厂题和源码)" target="_blank">Java回溯知识点(含面试大厂题和源码)</a>
                            <span class="text-muted">一成码农</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                            <div>回溯算法是一种通过遍历所有可能的候选解来寻找所有解的算法,如果候选解被确认不是一个解(或至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃这个解,即“回溯”并尝试另一个候选解。回溯法通常用递归方法来实现,在解决排列、组合、选择问题时非常有效。回溯算法的核心要点:路径:也就是已经做出的选择。选择列表:也就是你当前可以做的选择。结束条件:也就是到达决策树底层,无法再做出选择的条件。回溯算法</div>
                        </li>
                        <li><a href="/article/1773337745800888320.htm"
                               title="Azkaban各种类型的Job编写" target="_blank">Azkaban各种类型的Job编写</a>
                            <span class="text-muted">__元昊__</span>
    
                            <div>一、概述原生的Azkaban支持的plugin类型有以下这些:command:Linuxshell命令行任务gobblin:通用数据采集工具hadoopJava:运行hadoopMR任务java:原生java任务hive:支持执行hiveSQLpig:pig脚本任务spark:spark任务hdfsToTeradata:把数据从hdfs导入TeradatateradataToHdfs:把数据从Te</div>
                        </li>
                        <li><a href="/article/1773326395645165568.htm"
                               title="java基础相关面试题详细总结" target="_blank">java基础相关面试题详细总结</a>
                            <span class="text-muted">。。。。。96</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                            <div>1.Java中的数据类型有哪些?答:Java中的数据类型包括基本数据类型(如整数、浮点数、字符等)和引用数据类型(如类、接口、数组等)。2.什么是面向对象编程(OOP)?答:面向对象编程是一种编程范式,它将数据和对数据的操作封装在一起,形成对象。通过对象之间的交互来实现程序的功能。3.解释类和对象的关系。答:类是对象的抽象描述,而对象是类的具体实例。一个类可以创建多个对象,每个对象都具有类中定义的</div>
                        </li>
                        <li><a href="/article/1773306382401994752.htm"
                               title="Qlib-Server部署" target="_blank">Qlib-Server部署</a>
                            <span class="text-muted">宋志辉</span>
    <a class="tag" taget="_blank" href="/search/flask/1.htm">flask</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/qlib/1.htm">qlib</a><a class="tag" taget="_blank" href="/search/%E9%87%8F%E5%8C%96/1.htm">量化</a>
                            <div>Qlib-Server部署介绍构建Qlib服务器,用户可以选择:一键部署Qlib服务器逐步部署Qlib服务器一键部署Qlib服务器支持一键部署,用户可以选择以下两种方法之一进行一键部署:使用docker-compose部署在Azure中部署使用docker-compose进行一键部署按照以下步骤使用docker-compose部署Qlib服务器:安装docker,请参考Docker安装。安装doc</div>
                        </li>
                        <li><a href="/article/1773256158274977792.htm"
                               title="javascript 日期转换为时间戳,时间戳转换为日期的函数" target="_blank">javascript 日期转换为时间戳,时间戳转换为日期的函数</a>
                            <span class="text-muted">cdcdhj</span>
    <a class="tag" taget="_blank" href="/search/javascript%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0/1.htm">javascript学习日记</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                            <div>日期转化为时间戳,主要用valueOf()来进行转化为毫秒时间戳,getTime()IOS系统无法解析转换,所以都有valueOf()letgetTimestampOrDate=function(timestamp){lettimeStamp='';constregex=/^\d{4}(-|\/)\d{2}(-|\/)\d{2}$/;constregex2=/^\d{4}(-|\/)\d{2}(-</div>
                        </li>
                        <li><a href="/article/1773255151038038016.htm"
                               title="Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法" target="_blank">Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法</a>
                            <span class="text-muted">杰哥在此</span>
    <a class="tag" taget="_blank" href="/search/Java%E7%B3%BB%E5%88%97/1.htm">Java系列</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
                            <div>Java内存模型与多线程的深入探讨在Java的世界里,内存模型和多线程是开发者必须掌握的核心知识点。它们不仅关系到程序的性能和稳定性,还直接影响到系统的可扩展性和可靠性。下面,我将通过三个面试题,带领大家深入理解Java内存模型、多线程以及并发编程的相关原理和实践。面试题一:请解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用。关注点:JVM内存结构的基本组成堆、栈、方法区的功能和</div>
                        </li>
                        <li><a href="/article/1773198631940194304.htm"
                               title="COMP315 JavaScript Cloud Computing for E Commerce" target="_blank">COMP315 JavaScript Cloud Computing for E Commerce</a>
                            <span class="text-muted">zhuyu0206girl</span>
    <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                            <div>Assignment1:Javascript1IntroductionAcommontaskincloudcomputingisdatacleaning,whichistheprocessoftakinganinitialdatasetthatmaycontainerroneousorincompletedata,andremovingorfixingthoseelementsbeforeform</div>
                        </li>
                        <li><a href="/article/1773191331473063936.htm"
                               title="JSON与AJAX:网页交互的利器" target="_blank">JSON与AJAX:网页交互的利器</a>
                            <span class="text-muted">入冉心</span>
    <a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                            <div>在现代Web开发中,JSON(JavaScriptObjectNotation)和AJAX(AsynchronousJavaScriptandXML)是两项不可或缺的技术。它们共同为网页提供了动态、实时的数据交互能力,为用户带来了更加流畅和丰富的体验。本文将详细介绍JSON和AJAX的概念、原理,并通过代码示例展示它们在实际开发中的应用。一、JSON:轻量级的数据交换格式JSON是一种轻量级的数据</div>
                        </li>
                        <li><a href="/article/1772795036136701952.htm"
                               title="程序员开发技术整理" target="_blank">程序员开发技术整理</a>
                            <span class="text-muted">laizhixue</span>
    <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
                            <div>前端技术:vue-前端框架element-前端框架bootstrap-前端框架echarts-图标组件C#后端技术:webservice:soap架构:简单的通信协议,用于服务通信ORM框架:对象关系映射,如EF:对象实体模型,是ado.net中的应用技术soap服务通讯:xml通讯ado.net:OAuth2:登录授权认证:Token认证:JWT:jsonwebtokenJava后端技术:便捷工</div>
                        </li>
                                    <li><a href="/article/99.htm"
                                           title="ios内付费" target="_blank">ios内付费</a>
                                        <span class="text-muted">374016526</span>
    <a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/%E5%86%85%E4%BB%98%E8%B4%B9/1.htm">内付费</a>
                                        <div>近年来写了很多IOS的程序,内付费也用到不少,使用IOS的内付费实现起来比较麻烦,这里我写了一个简单的内付费包,希望对大家有帮助。 
      
    具体使用如下: 
    这里的sender其实就是调用者,这里主要是为了回调使用。 
    [KuroStoreApi kuroStoreProductId:@"产品ID" storeSender:self storeFinishCallBa</div>
                                    </li>
                                    <li><a href="/article/226.htm"
                                           title="20 款优秀的 Linux 终端仿真器" target="_blank">20 款优秀的 Linux 终端仿真器</a>
                                        <span class="text-muted">brotherlamp</span>
    <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/linux%E8%A7%86%E9%A2%91/1.htm">linux视频</a><a class="tag" taget="_blank" href="/search/linux%E8%B5%84%E6%96%99/1.htm">linux资料</a><a class="tag" taget="_blank" href="/search/linux%E8%87%AA%E5%AD%A6/1.htm">linux自学</a><a class="tag" taget="_blank" href="/search/linux%E6%95%99%E7%A8%8B/1.htm">linux教程</a>
                                        <div>  
    终端仿真器是一款用其它显示架构重现可视终端的计算机程序。换句话说就是终端仿真器能使哑终端看似像一台连接上了服务器的客户机。终端仿真器允许最终用户用文本用户界面和命令行来访问控制台和应用程序。(LCTT 译注:终端仿真器原意指对大型机-哑终端方式的模拟,不过在当今的 Linux 环境中,常指通过远程或本地方式连接的伪终端,俗称“终端”。) 
    你能从开源世界中找到大量的终端仿真器,它们</div>
                                    </li>
                                    <li><a href="/article/353.htm"
                                           title="Solr Deep Paging(solr 深分页)" target="_blank">Solr Deep Paging(solr 深分页)</a>
                                        <span class="text-muted">eksliang</span>
    <a class="tag" taget="_blank" href="/search/solr%E6%B7%B1%E5%88%86%E9%A1%B5/1.htm">solr深分页</a><a class="tag" taget="_blank" href="/search/solr%E5%88%86%E9%A1%B5%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/1.htm">solr分页性能问题</a>
                                        <div>转载请出自出处:http://eksliang.iteye.com/blog/2148370 
    作者:eksliang(ickes) blg:http://eksliang.iteye.com/ 概述 
    长期以来,我们一直有一个深分页问题。如果直接跳到很靠后的页数,查询速度会比较慢。这是因为Solr的需要为查询从开始遍历所有数据。直到Solr的4.7这个问题一直没有一个很好的解决方案。直到solr</div>
                                    </li>
                                    <li><a href="/article/480.htm"
                                           title="数据库面试题" target="_blank">数据库面试题</a>
                                        <span class="text-muted">18289753290</span>
    <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98+%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">面试题 数据库</a>
                                        <div>1.union ,union all 
    网络搜索出的最佳答案: 
    union和union all的区别是,union会自动压缩多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复。 
    Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序; 
    Union All:对两个结果集进行并集操作,包括重复行,不进行排序; 
    2.索引有哪些分类?作用是</div>
                                    </li>
                                    <li><a href="/article/607.htm"
                                           title="Android TV屏幕适配" target="_blank">Android TV屏幕适配</a>
                                        <span class="text-muted">酷的飞上天空</span>
    <a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                        <div>先说下现在市面上TV分辨率的大概情况 
    两种分辨率为主 
    1.720标清,分辨率为1280x720. 
    屏幕尺寸以32寸为主,部分电视为42寸 
    2.1080p全高清,分辨率为1920x1080 
    屏幕尺寸以42寸为主,此分辨率电视屏幕从32寸到50寸都有 
      
    适配遇到问题,已1080p尺寸为例: 
    分辨率固定不变,屏幕尺寸变化较大。 
    如:效果图尺寸为1920x1080,如果使用d</div>
                                    </li>
                                    <li><a href="/article/734.htm"
                                           title="Timer定时器与ActionListener联合应用" target="_blank">Timer定时器与ActionListener联合应用</a>
                                        <span class="text-muted">永夜-极光</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                        <div>功能:在控制台每秒输出一次 
      
    代码: 
    package Main;
    import javax.swing.Timer;
     import java.awt.event.*;
    
     public class T {
        private static int count = 0; 
    
        public static void main(String[] args){
    </div>
                                    </li>
                                    <li><a href="/article/861.htm"
                                           title="Ubuntu14.04系统Tab键不能自动补全问题解决" target="_blank">Ubuntu14.04系统Tab键不能自动补全问题解决</a>
                                        <span class="text-muted">随便小屋</span>
    <a class="tag" taget="_blank" href="/search/Ubuntu+14.04/1.htm">Ubuntu 14.04</a>
                                        <div>Unbuntu 14.4安装之后就在终端中使用Tab键不能自动补全,解决办法如下: 
      
    1、利用vi编辑器打开/etc/bash.bashrc文件(需要root权限) 
    sudo vi /etc/bash.bashrc 
     接下来会提示输入密码 
    2、找到文件中的下列代码 
    #enable bash completion in interactive shells
    #if</div>
                                    </li>
                                    <li><a href="/article/988.htm"
                                           title="学会人际关系三招 轻松走职场" target="_blank">学会人际关系三招 轻松走职场</a>
                                        <span class="text-muted">aijuans</span>
    <a class="tag" taget="_blank" href="/search/%E8%81%8C%E5%9C%BA/1.htm">职场</a>
                                        <div>要想成功,仅有专业能力是不够的,处理好与老板、同事及下属的人际关系也是门大学问。如何才能在职场如鱼得水、游刃有余呢?在此,教您简单实用的三个窍门。 
      第一,多汇报 
     最近,管理学又提出了一个新名词“追随力”。它告诉我们,做下属最关键的就是要多请示汇报,让上司随时了解你的工作进度,有了新想法也要及时建议。不知不觉,你就有了“追随力”,上司会越来越了解和信任你。 
      第二,勤沟通 
     团队的力</div>
                                    </li>
                                    <li><a href="/article/1115.htm"
                                           title="《O2O:移动互联网时代的商业革命》读书笔记" target="_blank">《O2O:移动互联网时代的商业革命》读书笔记</a>
                                        <span class="text-muted">aoyouzi</span>
    <a class="tag" taget="_blank" href="/search/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/1.htm">读书笔记</a>
                                        <div>移动互联网的未来:碎片化内容+碎片化渠道=各式精准、互动的新型社会化营销。 
      
    O2O:Online to OffLine 线上线下活动 
    O2O就是在移动互联网时代,生活消费领域通过线上和线下互动的一种新型商业模式。 
      
    手机二维码本质:O2O商务行为从线下现实世界到线上虚拟世界的入口。 
      
    线上虚拟世界创造的本意是打破信息鸿沟,让不同地域、不同需求的人</div>
                                    </li>
                                    <li><a href="/article/1242.htm"
                                           title="js实现图片随鼠标滚动的效果" target="_blank">js实现图片随鼠标滚动的效果</a>
                                        <span class="text-muted">百合不是茶</span>
    <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E6%BB%9A%E5%8A%A8%E5%B1%9E%E6%80%A7%E7%9A%84%E8%8E%B7%E5%8F%96/1.htm">滚动属性的获取</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E7%89%87%E6%BB%9A%E5%8A%A8/1.htm">图片滚动</a><a class="tag" taget="_blank" href="/search/%E5%B1%9E%E6%80%A7%E8%8E%B7%E5%8F%96/1.htm">属性获取</a><a class="tag" taget="_blank" href="/search/%E9%A1%B5%E9%9D%A2%E5%8A%A0%E8%BD%BD/1.htm">页面加载</a>
                                        <div>1,获取样式属性值 
    top  与顶部的距离
    left  与左边的距离
    right 与右边的距离
    bottom 与下边的距离
    zIndex 层叠层次 
      
      例子:获取左边的宽度,当css写在body标签中时 
    <div id="adver" style="position:absolute;top:50px;left:1000p</div>
                                    </li>
                                    <li><a href="/article/1369.htm"
                                           title="ajax同步异步参数async" target="_blank">ajax同步异步参数async</a>
                                        <span class="text-muted">bijian1013</span>
    <a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/Ajax/1.htm">Ajax</a><a class="tag" taget="_blank" href="/search/async/1.htm">async</a>
                                        <div>        开发项目开发过程中,需要将ajax的返回值赋到全局变量中,然后在该页面其他地方引用,因为ajax异步的原因一直无法成功,需将async:false,使其变成同步的。 
            格式: 
    $.ajax({ type: 'POST', ur</div>
                                    </li>
                                    <li><a href="/article/1496.htm"
                                           title="Webx3框架(1)" target="_blank">Webx3框架(1)</a>
                                        <span class="text-muted">Bill_chen</span>
    <a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/ibatis/1.htm">ibatis</a>
                                        <div>Webx是淘宝开发的一套Web开发框架,Webx3是其第三个升级版本;采用Eclipse的开发环境,现在支持java开发; 
    采用turbine原型的MVC框架,扩展了Spring容器,利用Maven进行项目的构建管理,灵活的ibatis持久层支持,总的来说,还是一套很不错的Web框架。 
    Webx3遵循turbine风格,velocity的模板被分为layout/screen/control三部</div>
                                    </li>
                                    <li><a href="/article/1623.htm"
                                           title="【MongoDB学习笔记五】MongoDB概述" target="_blank">【MongoDB学习笔记五】MongoDB概述</a>
                                        <span class="text-muted">bit1129</span>
    <a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a>
                                        <div>MongoDB是面向文档的NoSQL数据库,尽量业界还对MongoDB存在一些质疑的声音,比如性能尤其是查询性能、数据一致性的支持没有想象的那么好,但是MongoDB用户群确实已经够多。MongoDB的亮点不在于它的性能,而是它处理非结构化数据的能力以及内置对分布式的支持(复制、分片达到的高可用、高可伸缩),同时它提供的近似于SQL的查询能力,也是在做NoSQL技术选型时,考虑的一个重要因素。Mo</div>
                                    </li>
                                    <li><a href="/article/1750.htm"
                                           title="spring/hibernate/struts2常见异常总结" target="_blank">spring/hibernate/struts2常见异常总结</a>
                                        <span class="text-muted">白糖_</span>
    <a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a>
                                        <div> 
     Spring 
     
    ①ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException 
    缺少aspectjweaver.jar,该jar包常用于spring aop中 
      
    ②java.lang.ClassNotFoundException: org.sprin</div>
                                    </li>
                                    <li><a href="/article/1877.htm"
                                           title="jquery easyui表单重置(reset)扩展思路" target="_blank">jquery easyui表单重置(reset)扩展思路</a>
                                        <span class="text-muted">bozch</span>
    <a class="tag" taget="_blank" href="/search/form/1.htm">form</a><a class="tag" taget="_blank" href="/search/jquery+easyui/1.htm">jquery easyui</a><a class="tag" taget="_blank" href="/search/reset/1.htm">reset</a>
                                        <div>在jquery easyui表单中 尚未提供表单重置的功能,这就需要自己对其进行扩展。 
    扩展的时候要考虑的控件有: 
     combo,combobox,combogrid,combotree,datebox,datetimebox 
    需要对其添加reset方法,reset方法就是把初始化的值赋值给当前的组件,这就需要在组件的初始化时将值保存下来。 
    在所有的reset方法添加完毕之后,就需要对fo</div>
                                    </li>
                                    <li><a href="/article/2004.htm"
                                           title="编程之美-烙饼排序" target="_blank">编程之美-烙饼排序</a>
                                        <span class="text-muted">bylijinnan</span>
    <a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BE%8E/1.htm">编程之美</a>
                                        <div>
    package beautyOfCoding;
    
    import java.util.Arrays;
    
    /*
     *《编程之美》的思路是:搜索+剪枝。有点像是写下棋程序:当前情况下,把所有可能的下一步都做一遍;在这每一遍操作里面,计算出如果按这一步走的话,能不能赢(得出最优结果)。
     *《编程之美》上代码有很多错误,且每个变量的含义令人费解。因此我按我的理解写了以下代码:
     */
    </div>
                                    </li>
                                    <li><a href="/article/2131.htm"
                                           title="Struts1.X 源码分析之ActionForm赋值原理" target="_blank">Struts1.X 源码分析之ActionForm赋值原理</a>
                                        <span class="text-muted">chenbowen00</span>
    <a class="tag" taget="_blank" href="/search/struts/1.htm">struts</a>
                                        <div>struts1在处理请求参数之前,首先会根据配置文件action节点的name属性创建对应的ActionForm。如果配置了name属性,却找不到对应的ActionForm类也不会报错,只是不会处理本次请求的请求参数。 
     
    如果找到了对应的ActionForm类,则先判断是否已经存在ActionForm的实例,如果不存在则创建实例,并将其存放在对应的作用域中。作用域由配置文件action节点的s</div>
                                    </li>
                                    <li><a href="/article/2258.htm"
                                           title="[空天防御与经济]在获得充足的外部资源之前,太空投资需有限度" target="_blank">[空天防御与经济]在获得充足的外部资源之前,太空投资需有限度</a>
                                        <span class="text-muted">comsci</span>
    <a class="tag" taget="_blank" href="/search/%E8%B5%84%E6%BA%90/1.htm">资源</a>
                                        <div> 
          这里有一个常识性的问题: 
     
          地球的资源,人类的资金是有限的,而太空是无限的..... 
     
          就算全人类联合起来,要在太空中修建大型空间站,也不一定能够成功,因为资源和资金,技术有客观的限制.... 
     
    &</div>
                                    </li>
                                    <li><a href="/article/2385.htm"
                                           title="ORACLE临时表—ON COMMIT PRESERVE ROWS" target="_blank">ORACLE临时表—ON COMMIT PRESERVE ROWS</a>
                                        <span class="text-muted">daizj</span>
    <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E4%B8%B4%E6%97%B6%E8%A1%A8/1.htm">临时表</a>
                                        <div>ORACLE临时表 转 
    临时表:像普通表一样,有结构,但是对数据的管理上不一样,临时表存储事务或会话的中间结果集,临时表中保存的数据只对当前 
    会话可见,所有会话都看不到其他会话的数据,即使其他会话提交了,也看不到。临时表不存在并发行为,因为他们对于当前会话都是独立的。 
    创建临时表时,ORACLE只创建了表的结构(在数据字典中定义),并没有初始化内存空间,当某一会话使用临时表时,ORALCE会</div>
                                    </li>
                                    <li><a href="/article/2512.htm"
                                           title="基于Nginx XSendfile+SpringMVC进行文件下载" target="_blank">基于Nginx XSendfile+SpringMVC进行文件下载</a>
                                        <span class="text-muted">denger</span>
    <a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8/1.htm">网络应用</a><a class="tag" taget="_blank" href="/search/lighttpd/1.htm">lighttpd</a>
                                        <div>    在平常我们实现文件下载通常是通过普通 read-write方式,如下代码所示。 
     
       @RequestMapping("/courseware/{id}") 
       public void download(@PathVariable("id") String courseID, HttpServletResp</div>
                                    </li>
                                    <li><a href="/article/2639.htm"
                                           title="scanf接受char类型的字符" target="_blank">scanf接受char类型的字符</a>
                                        <span class="text-muted">dcj3sjt126com</span>
    <a class="tag" taget="_blank" href="/search/c/1.htm">c</a>
                                        <div>/*
    	2013年3月11日22:35:54
    	目的:学习char只接受一个字符
    */
    # include <stdio.h>
    
    int main(void)
    {
    	int i;
    	char ch;
    
    	scanf("%d", &i);
    	printf("i = %d\n", i);
    	scanf("%</div>
                                    </li>
                                    <li><a href="/article/2766.htm"
                                           title="学编程的价值" target="_blank">学编程的价值</a>
                                        <span class="text-muted">dcj3sjt126com</span>
    <a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a>
                                        <div>发一个人会编程, 想想以后可以教儿女, 是多么美好的事啊, 不管儿女将来从事什么样的职业, 教一教, 对他思维的开拓大有帮助 
      
    像这位朋友学习:   
    http://blog.sina.com.cn/s/articlelist_2584320772_0_1.html 
      
     
      VirtualGS教程 (By @林泰前): 几十年的老程序员,资深的</div>
                                    </li>
                                    <li><a href="/article/2893.htm"
                                           title="二维数组(矩阵)对角线输出" target="_blank">二维数组(矩阵)对角线输出</a>
                                        <span class="text-muted">飞天奔月</span>
    <a class="tag" taget="_blank" href="/search/%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84/1.htm">二维数组</a>
                                        <div>今天在BBS里面看到这样的面试题目, 
      
    1,二维数组(N*N),沿对角线方向,从右上角打印到左下角如N=4: 4*4二维数组  
    { 1 2 3 4 }
    { 5 6 7 8 }
    { 9 10 11 12 }
    {13 14 15 16 } 
    打印顺序  
    4
    3 8
    2 7 12
    1 6 11 16
    5 10 15
    9 14
    13 
    要</div>
                                    </li>
                                    <li><a href="/article/3020.htm"
                                           title="Ehcache(08)——可阻塞的Cache——BlockingCache" target="_blank">Ehcache(08)——可阻塞的Cache——BlockingCache</a>
                                        <span class="text-muted">234390216</span>
    <a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91/1.htm">并发</a><a class="tag" taget="_blank" href="/search/ehcache/1.htm">ehcache</a><a class="tag" taget="_blank" href="/search/BlockingCache/1.htm">BlockingCache</a><a class="tag" taget="_blank" href="/search/%E9%98%BB%E5%A1%9E/1.htm">阻塞</a>
                                        <div>可阻塞的Cache—BlockingCache 
      
           在上一节我们提到了显示使用Ehcache锁的问题,其实我们还可以隐式的来使用Ehcache的锁,那就是通过BlockingCache。BlockingCache是Ehcache的一个封装类,可以让我们对Ehcache进行并发操作。其内部的锁机制是使用的net.</div>
                                    </li>
                                    <li><a href="/article/3147.htm"
                                           title="mysqldiff对数据库间进行差异比较" target="_blank">mysqldiff对数据库间进行差异比较</a>
                                        <span class="text-muted">jackyrong</span>
    <a class="tag" taget="_blank" href="/search/mysqld/1.htm">mysqld</a>
                                        <div>  mysqldiff该工具是官方mysql-utilities工具集的一个脚本,可以用来对比不同数据库之间的表结构,或者同个数据库间的表结构 
       如果在windows下,直接下载mysql-utilities安装就可以了,然后运行后,会跑到命令行下: 
     
    1) 基本用法 
       mysqldiff --server1=admin:12345</div>
                                    </li>
                                    <li><a href="/article/3274.htm"
                                           title="spring data jpa 方法中可用的关键字" target="_blank">spring data jpa 方法中可用的关键字</a>
                                        <span class="text-muted">lawrence.li</span>
    <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a>
                                        <div>spring data jpa 支持以方法名进行查询/删除/统计。 
    查询的关键字为find 
    删除的关键字为delete/remove (>=1.7.x) 
    统计的关键字为count (>=1.7.x) 
      
    修改需要使用@Modifying注解 
    @Modifying
    @Query("update User u set u.firstna</div>
                                    </li>
                                    <li><a href="/article/3401.htm"
                                           title="Spring的ModelAndView类" target="_blank">Spring的ModelAndView类</a>
                                        <span class="text-muted">nicegege</span>
    <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a>
                                        <div>项目中controller的方法跳转的到ModelAndView类,一直很好奇spring怎么实现的? 
    /*
     * Copyright 2002-2010 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * yo</div>
                                    </li>
                                    <li><a href="/article/3528.htm"
                                           title="搭建 CentOS 6 服务器(13) - rsync、Amanda" target="_blank">搭建 CentOS 6 服务器(13) - rsync、Amanda</a>
                                        <span class="text-muted">rensanning</span>
    <a class="tag" taget="_blank" href="/search/centos/1.htm">centos</a>
                                        <div>(一)rsync 
     
    Server端 
     
    # yum install rsync
    # vi /etc/xinetd.d/rsync
        service rsync
        {
            disable = no
            flags           = IPv6
            socket_type     = stream
            wait    </div>
                                    </li>
                                    <li><a href="/article/3655.htm"
                                           title="Learn Nodejs 02" target="_blank">Learn Nodejs 02</a>
                                        <span class="text-muted">toknowme</span>
    <a class="tag" taget="_blank" href="/search/nodejs/1.htm">nodejs</a>
                                        <div>(1)npm是什么   
    npm is the package manager for node 
    官方网站:https://www.npmjs.com/ 
    npm上有很多优秀的nodejs包,来解决常见的一些问题,比如用node-mysql,就可以方便通过nodejs链接到mysql,进行数据库的操作 
    在开发过程往往会需要用到其他的包,使用npm就可以下载这些包来供程序调用 
    &nb</div>
                                    </li>
                                    <li><a href="/article/3782.htm"
                                           title="Spring MVC 拦截器" target="_blank">Spring MVC 拦截器</a>
                                        <span class="text-muted">xp9802</span>
    <a class="tag" taget="_blank" href="/search/spring+mvc/1.htm">spring mvc</a>
                                        <div>Controller层的拦截器继承于HandlerInterceptorAdapter 
     
     HandlerInterceptorAdapter.java   1  public   abstract   class  HandlerInterceptorAdapter  implements  HandlerIntercep</div>
                                    </li>
                    </ul>
                </div>
            </div>
        </div>
    
    <div>
        <div class="container">
            <div class="indexes">
                <strong>按字母分类:</strong>
                <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                    href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                    href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                    href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                    href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                    href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                    href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                    href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                    href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
            </div>
        </div>
    </div>
    <footer id="footer" class="mb30 mt30">
        <div class="container">
            <div class="footBglm">
                <a target="_blank" href="/">首页</a> -
                <a target="_blank" href="/custom/about.htm">关于我们</a> -
                <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
                <a target="_blank" href="/sitemap.txt">Sitemap</a> -
                <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
            </div>
            <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
    <!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
            </div>
        </div>
    </footer>
    <!-- 代码高亮 -->
    <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
    <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
    <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
    <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
    <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>
    
    
    
    
    
    </body>
    
    </html>