文章目录
- 一、云原生
- 二、 Docker 介绍
- 2.1 什么是docker
- 2.2 为什么要使用docker
- 三、Docker 核心架构
- 3.1 Docker镜像
- 3.2 容器
- 3.3 仓库
- 3.4 Docker安装
- 四、Docker常用命令
- 4.1 Docker引擎及镜像的相关操作命令
- 列出本地镜像
- 搜索镜像
- 下载镜像
- 删除镜像
- 4.2 容器相关操作命令
- 将已存在的tar镜像,导入自己的本地镜像仓库
- 将新的镜像导出:
- 运行容器
- 列出正在运行的容器
- 删除容器
- 启动和停止容器
- 查看容器日志
- 查看容器内进程
- 与容器内部进行交互
- 退出容器
- 拷贝文件
- 查看容器元数据
- 将容器打包成镜像
- 五、数据卷
- 六、Docker 网络
- 七、应用部署
- 7.1部署mysql+wordpress
- 7.2 部署tomcat
- 7.3 部署 ES+Kibana
- 7.4 部署mysql 将配置文件与数据路径挂载出来
一、云原生
云中的资源在使用者看来是可以无限扩展的,并且可以随时获取,按需使用,随时扩展,按使用付费。这种特性经常被称为像水电一样使用IT基础设施

2018年,CNCF在关于云原生定义v1.0版本中这样描述云原生技术体系
- 云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用
- 云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API
- 云原生计算基金会(CNCF)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术

二、 Docker 介绍
2.1 什么是docker
Docker是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。是容器运行时。在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
英文文档
中文文档

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便,
借助于称之为“容器运行时”的软件技术,在同一个内核之上生成多个彼此隔离的用户空间,各用户空间可独立管理运行其内部进程,每个用户空间“自以为”独占该内核及硬件资源
2.2 为什么要使用docker
-
更高效的利用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。 -
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。 -
一致的运行环境
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。 -
持续交付和部署
对开发和运维人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment)
而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
-
更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。 -
更轻松的维护和扩展
Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像 ,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
总结:

三、Docker 核心架构

3.1 Docker镜像
操作系统分为内核空间和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:20.04 就包含了完整的一套 Ubuntu 20.04 最小系统的 root 文件系统。
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
分层存储:
因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
docker镜像的实质是由一层层文件系统组成
-
boots (boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载boots文件系统。在docke镜像的最底层就是bootfs。这一层与Linux(Univx系统是一样的,包含boot加载器(bootoader)和内核(kermnel)。当boot加载完,后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时会卸载bootfs。
-
rootfs (root file system),在bootfs之上,包含的就是典型的linux系统中的/dev/proc,/bin,/etc等标准的目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu/Centos等等。
-
我们平时安装进虚拟机的centos都有1到几个GB,为什么docer这里才20OMB?对于一个精简的OS,roots可以很小,只需要包括最基本的命令,工具,和程序库就可以了,因为底层直接使用Host的Kernal,自己只需要提供rootfs就行了。由此可见不同的linux发行版,他们的bootfs是一致的,rootfs会有差别。因此不同的发行版可以共用bootfs。

为什么docker会采取这种分层结构?
资源共享。采用分层机制实现基础层共享,从而减小docker仓库整体体积
比如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像。同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为容器层,容器层之下都叫镜像层。
3.2 容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间 。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。
容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。
3.3 仓库
一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
以 Ubuntu 镜像为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04,20.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。
仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。
Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像,最常使用的 Registry 公开服务是官方的Docker Hub。
由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为 加速器。常见的有 阿里云加速器 DaoCloud 加速器等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从 Docker Hub 下载速度会提高很多。
国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 网易云镜像服务、 DaoCloud 镜像市场、阿里云镜像库等
3.4 Docker安装
1.安装
官方安装参考
也可以不依赖平台,用脚本安装,只需要执行如下命令
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
2.开机自启
# 开机启动 docker
sudo systemctl enable docker
# 启动 docker
sudo systemctl start docker
3.配置阿里云镜像加速

四、Docker常用命令
docker镜像启动流程如下:

4.1 Docker引擎及镜像的相关操作命令
官方文档请参考
1.操作引擎的相关命令
docker info # 查看docker相关信息
docker version 或 --version # 查看docker版本信息
docker --help # 查看具体命令的帮助信息
2.操作镜像的相关命令
列出本地镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3.15 c059bfaa849c 13 days ago 5.59MB
nginx 1.20-alpine 373f8d4d4c60 3 weeks ago 23.2MB
hello-world latest feb5d9fea6a5 2 months ago 13.3kB
# 可选参数
-a/--all 列出所有镜像
-q/--quiet 只显示镜像的id
列表包含了仓库名、标签、镜像 ID、创建时间 以及 所占用的空间,一个镜像可以有多个TAG标签,但是只能有唯一一个ID
搜索镜像
docker search nginx
ocker search nginx -f=STARS=3000 #搜索收藏超过3000的镜像
下载镜像
docker pull 镜像名[:tag]
[root@localhost ~]# docker pull mysql
Using default tag: latest #如果不写tag默认就是latest
latest: Pulling from library/mysql
ffbb094f4f9e: Pull complete # 分层下载
df186527fc46: Pull complete
fa362a6aa7bd: Pull complete
5af7cb1a200e: Pull complete
949da226cc6d: Pull complete
bce007079ee9: Pull complete
eab9f076e5a3: Pull complete
8a57a7529e8d: Pull complete
b1ccc6ed6fc7: Pull complete
b4af75e64169: Pull complete
3aed6a9cd681: Pull complete
23390142f76f: Pull complete
Digest: sha256:ff9a288d1ecf4397967989b5d1ec269f7d9042a46fc8bc2c3ae35458c1a26727
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #docker pull mysql等价于docker pull docker.io/library/mysql:latest
指定版本下载 docker pull mysql:5.7
删除镜像
docker rmi 镜像名:TAG /镜像ID
或者 docker image rm 镜像名:TAG
# 指定镜像id删除 ,也可以同时指定多个id
docker rmi 镜像id
#指定镜像名删除
docker rmi mysql:5.7
# 删除全部镜像
docker rmi $(docker images -qa)
# 删除已经运行成容器的镜像,默认情况下当一个镜像启动为容器,是不能直接删除,可以加-f参数
docker rmi -f mysql
4.2 容器相关操作命令
容器是依据镜像启动的,独立运行的一个或一组应用,以及它们的运行态环境。
将已存在的tar镜像,导入自己的本地镜像仓库
docker load -i 镜像包名

将新的镜像导出:
docker save 镜像名:tag -o 文件名
例如
docker save test-tomcat:1.0 -o test-tomcat-1.0.tar
后期可以将tar包load成镜像
运行容器
docker run --name tomcat1(容器名) -d(后台运行) -p 80:8080(宿主机与容器端口映射) tomcat:9.0(运行容器的镜像名)
docker run [可选参数] image
#参数
--name "名字" 指定容器别名
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口
-p 主机端口:容器端口 (一般经常用到此格式,如果需要暴露多个容器内端口,可以写多个-p)
-p ip:主机端口:容器端口 配置主机端口映射到容器端口(绑定宿主机特定ip,上面是开放宿主机任意ip的指定端口)
-p 容器端口
-P 随机指定端口(大写的P)
[root@localhost ~]# docker run tomact
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
容器id 启动容器的镜像名 容器内运行命令 容器启动时间 容器状态UP/Down 容器内监听端口 容器名称
db6b1b1272be tomcat "catalina.sh run" 36 seconds ago Up 35 seconds 8080/tcp adoring_dewdney
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从 registry 下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
列出正在运行的容器
docker ps # 列出当前正在运行的容器
-a # 列出所有容器的运行记录
-n=? # 显示最近创建的n个容器
-q # 只显示容器的编号
删除容器
docker rm 容器id 或容器名 #删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
docker rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs -I {} docker rm {} #删除所有的容器
启动和停止容器
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前运行的容器
docker kill 容器id #强制停止当前容器
# id都可以换成容器名
查看容器日志
docker logs 容器id |容器名称
docker logs -f 容器id|容器名称===>实时展示日志
docker logs -tf 容器id |容器名称===>加入时间戳实时展示日志
docker logs --tail number 容器id|容器名称===>查看容器日志最后number行
查看容器内进程
docker top 容器id或者容器名
与容器内部进行交互
方式1:
docker exec -it 容器id或者容器名 bash(命令行) =-==>进入容器,并与容器内命令终端进行交互
方式2:
docker attach 容器id或者容器名
docker exec 进入容器后开启一个新的终端,可以在里面操作
docker attach 进入容器正在执行的终端,不会启动新的进程
退出容器
exit # 停止并退出容器(后台方式运行则仅退出)
Ctrl+P+Q # 不停止容器退出
拷贝文件
#拷贝容器的文件到主机中
docker cp 容器id:容器内路径 目的主机路径
#拷贝宿主机的文件到容器中
docker cp 目的主机路径 容器id:容器内路径
查看容器元数据
docker inspect 容器名或id
将容器打包成镜像
docker commit -m "描述" -a "bertwu <sss@qq.com>" 容器名/id 新镜像名:tag
[root@localhost ~]# docker commit -a "bertwu <dd@qq.com>" -m "tomcat-test:1.0" tomcat02 tomcat-test:1.0
sha256:886cfe66736280955b1560f14ae1b87214919c5f9558aa7bc2aa17b3d89c548d
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat-test 1.0 886cfe667362 12 seconds ago 680MB
注:源容器有-v挂载数据卷,打包成新镜像后,新镜像并不会继承源容器的数据卷
五、数据卷
Docker将运用与运行的环境打包形成容器运行, Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了。 为了能保存数据,在Docker中我们使用卷。
卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性。
数据卷的特性:
- 数据卷可以在容器之间或容器与宿主机之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 数据卷会一直存在,即使容器被删除
1.自定义数据卷目录
docker run -it -v 主机目录(绝对路径):容器目录
例如
docker run --name tomcat02 -d -p 8082:8080 -v /soft/wabapps:/usr/local/tomcat/webapps tomcat:latest
2.自动数据卷目录
docker run --name tomcat03 -d -p 8082:8080 -v aaa:/usr/local/tomcat/webapps tomcat:latest
注意:
1.aa代表一个数据卷名字,名称可以随便写, docker在不存在时自动创建这个数据卷同时自动映射宿主机中某个目录
2.同时在启动容器时会将aa对应容器目录中全部内容复制到aa映射目录中
[root@localhost ~]# docker inspect tomcat03
"Mounts": [
{
"Type": "volume",
"Name": "aa",
"Source": "/var/lib/docker/volumes/aa/_data", #本地映射的目录,如果镜像中目录有数据,会同步过来
"Destination": "/usr/local/tomcat/webapps",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
默认情况下,只要挂载了数据卷,宿主机和容器对应的目录是相互影响的,有时候只需要让宿主机对应的目录更改影响容器,而容器内不要影响宿主机,只需要把宿主机目录设置为只读
docker run -d -p 8990∶8080 -name tomcat90 -v /root/apps:/usr/local/tomcat/webapps:ro tomcat:8.0-jre8
列出所有数据卷
docker volume ls
查看具体的数据卷信息
docker volume inspect 卷名
创建数据卷
docker volume create bb
启动容器时候,可以直接 -v bb:/var/lib/tomcat/webapps
删除
docker volume rm bb
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local aa
[root@localhost ~]# docker volume inspect aa
[
{
"CreatedAt": "2021-12-09T18:51:48+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/aa/_data",
"Name": "aa",
"Options": null,
"Scope": "local"
}
]
六、Docker 网络
当 Docker 启动时,会自动在宿主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。
同时,Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0 接口。比如典型的 172.17.0.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。
当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。

例如,启动两个容器时,查看网络部分信息如下:
[root@localhost ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:82ff:fe1e:3835 prefixlen 64 scopeid 0x20<link>
ether 02:42:82:1e:38:35 txqueuelen 0 (Ethernet)
RX packets 256 bytes 450855 (440.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 295 bytes 31116 (30.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth99d5ecd: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::6c4d:5cff:feb5:936 prefixlen 64 scopeid 0x20<link>
ether 6e:4d:5c:b5:09:36 txqueuelen 0 (Ethernet)
RX packets 47 bytes 145211 (141.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 57 bytes 6776 (6.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
vethce62afb: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::d04b:b6ff:fe4e:3674 prefixlen 64 scopeid 0x20<link>
ether d2:4b:b6:4e:36:74 txqueuelen 0 (Ethernet)
RX packets 53 bytes 22436 (21.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 63 bytes 4814 (4.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
一般情况下,在使用docker网桥(bridge)实现容器与容器通信时,如果站在企业实战的角度上,应该为每个项目创建不同的网桥。因为如果多个项目同时使用默认网桥,当一个项目要与它所依赖的容器频繁交换数据时,势必会影响到其他项目。
查看默认网络
docker network ls
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
9ca9b78f1c71 bridge bridge local
4e399f07fed6 host host local
c9ab8f104ab7 none null local
自定义网桥
docker network create -d bridge --subnet 192.168.1.2/24 my_network
docker run -d -p 80:8080 --name tomcat01 --network my_network
#其中 --subnet 可以不指定
查看网桥信息及网桥下活跃的容器
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "9ca9b78f1c71e5f518b2d90a22724abfed391d503287724b4feb8b42a364a254",
"Created": "2021-12-08T13:21:02.999144213+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3450360ca77657170ae9be68258ee355dbe6a532938cfce3f0fde24a3846815b": {
"Name": "tomcat01",
"EndpointID": "01039d663f2caea10e961b65033dd4bf26b6faacb6477b77f85c96a2a70dc51b",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"46b45c8100738423422b969800d036c995bf38a793f8f11604683ec03f2bea42": {
"Name": "tomcat02",
"EndpointID": "4667cdb4e63faae35ccd0622ce1b1df314f14b5eb0515227535861b1b9265b1c",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Labels": {}
}
]
删除网桥
docker network rm 网桥名称
注意:
一旦在启动容器时指定了自建网桥之后,日后可以在任何这个网桥关联的容器中使用容器名字进行与其他容器通信
七、应用部署
7.1部署mysql+wordpress
1.mysql以及wordpress需要的环境变量
[root@localhost ~]# cat wordpress.env
MYSQL_RANDOM_ROOT_PASSWORD=1 #设置随机root密码
MYSQL_DATABASE=wordpress
MYSQL_USER=bertwu
MYSQL_PASSWORD=123456
WORDPRESS_DB_HOST=word_db # 可以写ip,也可以指定mysql的容器名,前提是两者同一个网络
WORDPRESS_DB_USER=bertwu
WORDPRESS_DB_PASSWORD=123456
WORDPRESS_DB_NAME=wordpress
WORDPRESS_TABLE_PREFIX=wp # 表前缀
2.创建自建bridge网络,所有加入该网络的容器间可以用容器名通讯
docker network create -d bridge --subnet 172.20.1.100/24 wdnet
3.启动mysql容器
docker container run --name word_db \
-v /word/container/mysql:/var/lib/mysql \
--env-file wordpress.env \
-d --network wdnet mysql:8.0
4.启动wordpress容器
docker container run --name wordpress \
-v /word/container/word_picture:/usr/src/wordpress/wp-content/uploads \
--env-file wordpress.env -d --network wdnet -p 80:80 \
--link word_db wordpress:php8.0-apache
7.2 部署tomcat
#官方的使用
docker run -it --rm tomcat:9.0
#我们之前的启动都是后台,停止了容器之后,容器还是可以查到
docker run -it --rm, 一般用来测试,用完就删除
#下载在启动
docker pu11 tomcat
#启动运行
docker run -d -p 8080:8080 --name tomcat01 tomcat
#测试访问没有问题
#进入容器
root@ubuntu:~# docker exec -it tomcat1 /bin/bash
#发现问题: 1、linux命令少了,2。没有webapps。阿里云镜像的原因。默认是最小的镜像,所有不必要的都剔除掉。
#2.保证最小运行环境
#默认webapps下面是空的,执行如下就可以访问了
root@8418f6c7533f:/usr/local/tomcat# cp -r webapps.dist/* webapps

思考问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径, webapps ,我们在外部放置项目,就自动同步到内部就好了!
7.3 部署 ES+Kibana
# es暴露的端口很多!
# es十分的耗内存
# es的数据一般需要放置到安全目录!挂载
# --net somenetwork ?网络配置
#启动elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
docker stats 查看cpu的状态,默认情况下占用内存比较大
添加 ’-e ES_JAVA_OPTS="-Xms128m -Xmx512m" ‘ 配置ElasticSearch的虚拟机占用的内存大小。
root@ubuntu:~# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2

7.4 部署mysql 将配置文件与数据路径挂载出来
root@ubuntu:~# docker run --name mysql01 -d -p 3316:3306 -v /home/mysql/conf:/etc/mysql -v /home/mysql1/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
docker link 可以连接两个容器,以容器名访问而不基于ip, 但是需要用户手动创建 桥接网络
root@ubuntu:~# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
创建网络
root@ubuntu:~# docker network create -d bridge --subnet 192.168.100.0/24 mynet
df22e28f489a8ea95ff05eb675cb174adf83b3b4dd2733b51fc423625d29d374
以自己的网络创建mysql容器,并实现卷挂载
root@ubuntu:~# docker container run --name mydb1 -v /data/containers/mysql/:/var/lib/mysql --env-file mysql.env -d --net mynet mysql:8.0
34bf185e2b5066639a6745742931a940d1da96bd5aee16b7615822d65ccdda1b
查看mysql运行地址
root@ubuntu:~# docker container inspect mydb1 | grep -i ip
"IpcMode": "private",
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"IPAMConfig": null,
"IPAddress": "192.168.100.2",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
运行redis
root@ubuntu:~# docker container run --name redis -p 6379:6379 -d redis:alpine
root@ubuntu:~# docker port redis
6379/tcp -> 0.0.0.0:6379
6379/tcp -> :::6379
root@ubuntu:~# iptables -t nat -Lnv
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 to:172.17.0.2:6379
进入redis测试
root@ubuntu:~# docker container exec -it redis /bin/sh
/data # redis-cli
127.0.0.1:6379> keys *
添加主机名解析 --add-host
root@ubuntu:~# docker container run --name alpine --add-host xxx:172.17.0.3 --rm -it alpine
/ # cat /etc/hosts
127.0.0.1 localhost
172.17.0.3 xxx
创建网络 docker network create
需要网络驱动程序,默认驱动如下:
root@ubuntu:~# docker info | grep -i network
WARNING: No swap limit support
Network: bridge host ipvlan macvlan null overlay
创建网络
root@ubuntu:~# docker network create appnet --subnet 10.224.0.0/16
99b42eb4888601773a1b5e50f1566a91b168aeee4933be736bdcd3d3e05de803
root@ubuntu:~# docker network list
NETWORK ID NAME DRIVER SCOPE
99b42eb48886 appnet bridge local
root@ubuntu:~# apt install bridge-utils
root@ubuntu:~# brctl show
bridge name bridge id STP enabled interfaces
br-99b42eb48886 8000.02423489ae23 no
br-df22e28f489a 8000.02426a6073b3 no veth9cf771d
vethf7a8899
docker0 8000.0242c9d6cfe4 no vethe5f7764
启动容器,加入自己的网络
root@ubuntu:~# docker run --name alpine2 --rm --net appnet alpine:3.15 ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:0A:E0:00:02
inet addr:10.224.0.2 Bcast:10.224.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:290 (290.0 B) TX bytes:0 (0.0 B)
删除自定义网络
root@ubuntu:~# docker network rm appnet
appnet
