Docker 教程


一、Docker 与虚拟机的区别?

传统虚拟机:

  1. 资源占用多、冗余步骤多、启动慢。
  2. 虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件

Docker:

  1. 容器化技术,项目代码带上环境配置打包成镜像,上传到镜像仓库,下载镜像即可运行,不再需要复杂环境配置;
  2. Docker 容器内的应用直接运行在宿主机上,容器是没有内核的,也没有虚拟硬件;
  3. 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

二、Docker 术语

  1. 镜像(image)
    镜像是一些软件和配置环境的整体打包。
  2. 容器(container)
    容器是一个精简的 Linux 系统,是通过镜像运行起来的实例,镜像运行起来就是容器。
  3. 仓库(repository)
    仓库类似于 Github,我们写好的代码会提交到 Github 上面进行保存和管理,方便在其他人也能下载代码。镜像仓库也是类似的,制作好的镜像,就把它放到镜像仓库,方便其他人直接用镜像部署。

总结:
镜像是存在硬盘上的东西,镜像运行起来,就形成一个容器,容器才是真正跑起来的程序。只不过在 Docker 中,我们可以进入容器,做一些操作,然后再把容器中的改动提交形成一个新的镜像。

三、Docker 安装与卸载

1. 安装

  1. 环境要求:Linux 内核3.0以上,查看命令如下:
## uname 显示系统信息 -r (kernel-release) 显示操作系统发行编号:
uname -r
## cat(concatenate)命令用于连接文件并打印到标准输出设备上,(查看文件)。
cat /etc/os-release
  1. 卸载旧版本(无,则忽略)
yum remove docker \
	docker-client \
	docker-client-latest \
	docker-common \
	docker-latest \
	docker-latest-logrotate \
	docker-logrotate \
	docker-engine
  1. 需要的安装包
yum install -y yum-utils
  1. 设置镜像仓库(使用国内)
yum-config-manager \
	--add-repo \
	https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 更新软件包索引
yum makecache fast
  1. 安装 docker (docker-ce 为社区版,docker-ee 为企业版)
yum install docker-ce docker-ce-cli containerd.io
注意:版本为 centos 8 时执行上述命令时会报错,说的是 containerd.io >= 1.2.2-3,
解决方法:
(1).降低 docker 版本(不推荐)
(2).更新 containerd.io 版本(不降低 docker 版本)
## 更新 containerd.io 版本
wget https://download.docker.com/linux/centos/7/x86_64/edge/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm	#下载安装包
yum install -y  containerd.io-1.2.6-3.3.el7.x86_64.rpm #yum安装
yum install docker-ce docker-ce-cli containerd.io #重新安装 docker
  1. 启动docker
systemctl start docker #启动docker
docker version #查看版本,是否安装成功

2. 卸载

yum remove docker-ce docker-ce-cli containerd.io #卸载依赖
rm -rf /var/lib/docker/ #删除资源 /var/lib/docker docker的默认工作路径

3. 镜像加速(阿里云)

在这里插入图片描述

四、Docker 的run流程 和 Docker原理

1. run 流程

yes
no
yes
no
开始 run
Docker在本
机选找镜像
判断本机是否有这个镜像
使用这个镜像运行
去Docker Hub 下载
Docker Hub 是
否有这个镜像
下载镜像到本地
返回错误

2. docker 原理

docker 是一个Client-Server 结构的系统,Docker 的守护进程运行在主机上,通过Socket从客户端访问。DockerServer接收到 Docker-Client 的指令,就会执行命令。
在这里插入图片描述

六、Docker 的常用命令

Docker 命令官方文档:https://docs.docker.com/reference/,这里整理一下常用的命令。

1. 帮助命令

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

2. 镜像命令

## 获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/] 仓库名[:标签]     #下载镜像,
## 案例讲解
[root@localhost ~]# docker pull mysql
Using default tag: latest	#如果不写tag,默认就是latest(最新版本)
latest: Pulling from library/mysql
a076a628af6f: Pull complete 	#分层下载,docker image的核心 联合文件系统
f6c208f3f991: Pull complete 
88a9455a9165: Pull complete 
406c9b8427c6: Pull complete 
7c88599c0b25: Pull complete 
25b5c6debdaf: Pull complete 
43a5816f1617: Pull complete 
1a8c919e89bf: Pull complete 
9f3cf4bd1a07: Pull complete 
80539cea118d: Pull complete 
201b3cad54ce: Pull complete 
944ba37e1c06: Pull complete 
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest	#真实地址
## 这两个等价
docker pull mysql
docker pull docker.io/library/mysql:latest

## 列出镜像
docker images  #查看所有顶层镜像 
#解释: REPOSITORY 镜像仓库源 TAG 镜像标签 IMAGE ID 镜像的ID CREATED 镜像创建时间 SIZE 镜像大小
#可选项 -a, --all 列出所有选项 -q, --quiet 只显示镜像的ID 
docker images ls -a #查看中间层在内的所有镜象
docker images ls --digests #查看镜象摘要
docker images ls ubuntu:18.04 #查看指定仓库名和标签的镜像
docker images ls -f since=ubuntu:18.04 #查看某个位置之后的镜像
docker images ls -f before=ubuntu:18.04 #查看某个位置之前的镜像
docker iamges ls -q #查询ID
docker system df #查看镜像、容器、数据卷

## 删除镜像
docker image rm [选项] <镜像1>[<镜像2>......] #镜像 可以是短ID 镜像长ID 镜象名 镜象摘要
docker rmi -f #rm:删除,i:image
docker rmi -f $(docker images -q)	#删除所有镜像
## 保存现场,慎用
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] #保存为镜象,选项:--author "作者名" --message "信息"

docker search   #搜索镜像
#可选项 通过搜索来过滤
--filter=STARS=3000  搜索出来的镜像是STARS > 3000

## 提交镜像
docker commit -m="提交的描述信息" -a="作者“ 容器ID 目标镜像名:[TAG]

3. 容器命令

## 新建容器并启动
docker run [可选参数] 镜像        # 新建容器并启动,此时会新键容器
	#参数说明
	--name="Name" 	#容器名字 tomcat01 tomcat02 用来区分容器
	--d 			#后台方式运行
	-it    			#使用交互方式运行,进入容器查看内容
	-p            	#指定容器的端口 -p 8080(宿主机):8080(容器)
	-P(大写)      	#随机指定端口
## 实战启动centos
docker run -it centos /bin/bash		# /bin/bash centos 中bin目录中bash 命令
exit          #容器停止并退出
ctrl + P + Q  #容器不停止退出
## 列出所有的运行容器
docker ps              #列出所有当前正在运行的容器
	#参数说明
	-a           #列出所有当前正运行的容器+历史运行的容器
	-n=[数字]	#显示最近创建的容器,数字代表显示多少数量
	-q			#只显示容器的编号
## 删除容器
docker rm 容器id        #删除指定id的容器,注意和 rmi 的区别,不能删除正在运行的容器,如果要强制删除 rm -rf
	-f 容器id 或 $(docker ps -aq) # 删除指定的容器或全部删除(包括历史信息)
docker ps -a -q|xargs docker rm         # 删除所有的容器
##启动和停止容器的操作
docker start 容器id     # 启动容器,根据容器 id 来运行,此时不会新键容器
docker restart 容器id   # 重启容器
docker stop 容器id      # 停止当前正在运行的容器
docker kill 容器id      # 强制停止当前容器

4. 常用其他命令

## 后台启动容器
docker run -d 镜像名
#注意:docker 容器会使用后台运行,必须要有一个前台进程,docker 发现没有应用,就会自动停止
##查看日志
docker logs #查看日志
	-tf #显示全部日志 ,f带上时间
	--tail n #显示n条日志
##查看容器中进程信息
docker top 容器id  
##查看镜像的元数据
docker inspect 容器id
[
    {
        "Id": "402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834",
        "Created": "2021-04-07T04:59:00.2247648Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 11098,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-04-07T04:59:00.8697568Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
        "ResolvConfPath": "/var/lib/docker/containers/402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834/hostname",
        "HostsPath": "/var/lib/docker/containers/402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834/hosts",
        "LogPath": "/var/lib/docker/containers/402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834/402b59baed1a6d2c7ef0b5122be2ea0f8f061313ceb4ad960504b02ac3208834-json.log",
        "Name": "/great_hofstadter",
        "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/d4dbf6618ebafc6950487efd5458fd784e3a8423c3b12aca514759861d1daae5-init/diff:/var/lib/docker/overlay2/ae81f222a7e5772d14c3d07719ab760b93d2d6c30288dba30ecd9fd0d4f0ccda/diff",
                "MergedDir": "/var/lib/docker/overlay2/d4dbf6618ebafc6950487efd5458fd784e3a8423c3b12aca514759861d1daae5/merged",
                "UpperDir": "/var/lib/docker/overlay2/d4dbf6618ebafc6950487efd5458fd784e3a8423c3b12aca514759861d1daae5/diff",
                "WorkDir": "/var/lib/docker/overlay2/d4dbf6618ebafc6950487efd5458fd784e3a8423c3b12aca514759861d1daae5/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "402b59baed1a",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20201204",
                "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": "75c18c71ec50f8665e307be8b8fa172828e721771ea3eed3d36282799c6f8301",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/75c18c71ec50",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "775b1bc8cc03ce57512a1fa8707dbca1117bc5c27803da6af523090e29d9de9c",
            "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": "677eb02c7aba4fafca56a7980ccffaa0d47bdd3049c5a1942afc78c75abb690b",
                    "EndpointID": "775b1bc8cc03ce57512a1fa8707dbca1117bc5c27803da6af523090e29d9de9c",
                    "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 bashshell #进入当前容器后开启一个新的终端,可以在里面操作(常用)
docker attach 容器id #进入容器正在执行的终端
## 拷贝容器内文件到宿主机
docker cp 容器id:容器内路径  宿主机目的路径 

在这里插入图片描述

5. 可视化(平时不用)

  1. portainer(先用这个)
docker run -d -p 8088:9000 \
--restart=always -V /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

七、Docker 镜像细解

1. 镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有的内容,包括代码、运行库、环境变量和配置文件。
镜像来源:1.从远程仓库下载;2.朋友拷贝给你;3.自己制作一个镜像 DockerFile

2. Docker 镜像加载原理

UnionFs(联合文件系统)

UniosFS(联合文件系统):Union 文件系统(UniionFS)是一层分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
特性:一次同时加载多个文件系统,但从外面看起来,只能看一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker 镜像加载原理

docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS。
bootfs(boot file system) 主要包含 bootloader 和 kernel , bootloader 主要是引导加载 kernel ,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 bootfs 。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot加载器 和 内核。当boot加载完成之后整个内核都在内存中了,此时内存的使用权已由 bootfs 转交给 内核,此时系统也会卸载 bootfs。
rootfs(root file system) ,在bootfs 之上。包含的就是典型 Linux 系统中的 /dev/,/proc/,/bin/,/etc/ 等标准目录和文件,rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos 等等

分层理解

优势:资源共享
查看镜你分层的方式可以通过 docker image inspect 。
理解:所有 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层上,创建新的镜像层。

八、容器数据卷

1. 什么是容器数据卷

容器的持久化和同步操作,容器间也是可以数据共享。

2.容器数据卷命令

docker volume
	create #创建一个volume
	inspect [卷名] #查看卷名的详细信息
	ls #列表所有卷
	prune #移除未使用的数据卷
	rm #移除一个或多个数据卷,不能移除被容器使用的数据卷。

3. 使用容器数据卷

## 直接使用命令来挂载 -v
docker run -it -v 主机目录:容器目录

4. 实战:安装MySQL

## 获取镜像
docker pull msyql:5.7
## 官方安装: docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_PASSWORD=123456 --home mysql01 mysql
## 数据持久化

5. 具名挂载 各 匿名挂载

## 匿名挂载 -v只写容器路径
docker run -d -P --name 容器命名 -v 容器内路径
## 具名挂载
docker run -d -P --name 容器命名 -v 卷名:容器内路径
## 如何确定是具名挂载还匿名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径::容器内路径 #指定路径挂载
## 拓展
# 通过 -v 容器内路径:[ro/rw] 改变读写权限
ro readonly #只读,说明这个路径只能通过宿主机来操作,容器内部无法操作
rw readwrite #读写
# 设置了容器权限,容器对我们的挂载出来的内容就有限定了
docker run -d -P nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P nginx02 -v juming-nignx:/etc/nginx:rw nginx

九、Dockerfile

概念:dockerfile 是用来构建 docker 镜像的构建文件,命令脚本
实战:通过脚本生成镜像,镜象是一层一层的,脚本一个个的命令,每个命令都是一层的

## 1.编写一个dockerfile文件
vi dockerfile01
#dockerfile01文件内容
	FORM centos
	VOLUME ["volume01","volume02"]
	CMD echo "---end---"
	CMD /bin/bash
## 2.构建一个镜像
docker build -f dokcerfile02 -t centos2:2.3 .
## 3.docker fun 运行镜像
## 4.docker push 发布镜像(DockerHub 、阿里云镜像他库)

1. Dockerfile 构建过程

基础知识

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

dockerfile 是面向开发的,我们以后要发布项目,做镜像,就要编写dockfile 文件,这个文件十分简单!
Docker 镜像逐渐成为企业交付的标准,必须掌握!

步骤:开发,部署,运维。。。 缺一不可
DockFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile 构建生成的镜像,最终发布程和运行的产品
Docker:容器就是镜像运行起来提供服务器

2. Dockerfile 指令

FROM	#指定基础镜像
MAINTAINER	#镜像维护者:姓名+邮箱
RUN		#镜像构建的时候需要运行的命令
ADD		#COPY文件,会自动解压。步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR		#镜像的工作目录
VOLUME		#挂载的目录
EXPOST		#保留端口配置
CMD		#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT		#指定这个容器启动的时候要运行命令,可以追加命令
ONBUILD		#当构建一个被继承 DockerFile 这个时候就会运行 ONBUTLD 的指令,触发指令
COPY		#类似ADD,将我们文件拷贝到镜像中
ENV		#构建的时候设置环镜变量!

3. 实战测试

目标:创建一个自己的centos

##1. 编写Dockerfile的文件
FROM centos
MAINTAINER wang<1558924235@qq.com>

ENV MYPATH /usr/local
WORKDIR	$MYPATH

RUN yum -y install vim
RUM yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end-----"
CMD /bin/bash
##2. 通过这个文件构建镜像
docker build -f dockerfile文件路径 -t 镜像名:tag .

4. CMD 和 ENTRYPOINT 区别

CMD		#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT		#指定这个容器启动的时候要运行命令,可以追加命令

容器与容器之间的共之前共享存储

docker run -it --name 容器名 --volumes-from 容器名 镜像名:tag

实战:mysql 实现数据库共享

 docker run -d -p 3312:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql
 docker run -d -p 3313:3306 -e MYSQL_ROOT_PASSWORD=1234567 --name mysql03 --volumes-from mysql02 mysql

实战:Tomcat 镜像

  1. 准备镜像文件 tomcat 压缩包,jdk压缩包!
    在这里插入图片描述
  2. 编写 dockerfile 文件,官方命名 Dockerfile ,build 会自动寻找这个文件,就不需要 -f 指定了
FROM centos
MAINTAINER wang<1558924235@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-16_linux-aarch64_bin.tar.gz /usr/local/
ADD apache-tomcat-9.0.33.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/lib:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.22/bin/logs/catalina.out
  1. 构建镜像
docker build -t diytomcat .
  1. 启动镜像
  2. 访问测试
  3. 发布项目

发布自己的镜像

1.地址 https://hub.docker.com/ 注册自己的帐号!
2.在我们服务器上提交自己的镜像

docker login
-u #用户名
-p #密码
  1. 提交自己的镜像
    docker push

阿里云镜像发布

  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间
  4. 建容器镜像
  5. 参考阿里云镜像说明

小结

在这里插入图片描述

十、Docker 网络

1. 理解 Docker0

[root@localhost build]# ip addr
##	lo 本机回环地址
##	eth0 内网地址
##	docker0 docker生成的地址
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_U P> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:08:e5:69 brd ff:ff:ff:ff:ff:ff
    inet 43.226.145.126/21 brd 43.226.151.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe08:e569/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:d0:10:f6:fd brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d0ff:fe10:f6fd/64 scope link 
       valid_lft forever preferred_lft forever

三个问题

  1. docker 是如何处理容器网络访问的
docker run -d -P --name tomcat01 tomcat
#查看容器的内部网络地址 ip addr ,容器会有一个 eth0@if105 ip地址 docker分配的
[root@localhost /]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
104: eth0@if105: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# linux 可以 ping 通 docker 容器内部
[root@localhost /]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.190 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.131 ms

原理:

  1. 我们每启动一个 docker容器 ,docker 就会给 docker容器 分配一个IP,我们只要安装了 docker,就会有一个网卡 docker0 桥接模式,使用的技术是 evth-pair技术!
#再次测试 ip addr
[root@localhost /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:08:e5:69 brd ff:ff:ff:ff:ff:ff
    inet 43.226.145.126/21 brd 43.226.151.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe08:e569/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:d0:10:f6:fd brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d0ff:fe10:f6fd/64 scope link 
       valid_lft forever preferred_lft forever
105: vethcdd5754@if104: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether f2:5b:6d:12:3f:c1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f05b:6dff:fe12:3fc1/64 scope link 
       valid_lft forever preferred_lft forever

我们发现这个容器还来网卡,都是一对对的
evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
正因为这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
openstac,Docker 容器之间的连接,OVS 的连接,都是使用 evth-pair 技术
所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用IP

2. --link

场景:我们编写一个微服务,database url = ip;,项目不重启,数据库IP换掉了,我们希望可以处理这个问,可以名字来进行访问客户端。

docker exec -it tomcat02 ping tomcat01
>ping: tomcat01: Name or service not know

#如何解决,通过 --link 可以解决网络连通问题
dokcer run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 ping tomcat02
>可以ping通
##本质上是hosts配置中增加

3. 自定义网络

  1. 容器互联
##查看所有 Docker 网络
docker network ls

网络模式
bridge:桥接 docker(默认)
none: 不配置网络
host:和宿主机共享网络
containner:容器网络连通(用的少,局限很大)

  1. 测试
##我们真接启动命令 --net bridge,而这个就是我们的docker0
docker run -d -P --name tomcat01 --net bridge tomcat

#docker0特点,默认,域名不能访问,--link 可以打通连接!

# 我们可以自定义一个自己的网络 
# --driver bridge
# --subnet 192.168.0.0/16
# --getway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --getway 192.168.0.1 mynet
## 查看所有网络
docker network ls
## 查看自己创建的网络
docker network inspect mynet
## 创建容器,连接自己的网络
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
##  查看自己的网络
docker network inpect mynet
## ping
docker exec -it tomcat-net-01 ping 192.168.0.3
== docker exec -it tomcat-net-01 ping tomcat-net-02 ##现在不使用 --link 也可以 ping 名字

我们自定义的网络,docker 都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络。
好处:
redis - 不同的集群使用不同的网络,保证集群是安全和健康的
mysql - 不同的集群使用不同的网络,保证集群是安全和健康的

4. 网络连通


docker network conncet [OPTIONS] NETWORK CONTAINER
测试打通 tomcat01  mynet
docker network connect mynet tomcat01
连能之后就是将 tomcat01 放到了 mynet 网络下
一个容器两个ip地址
阿里云服务: 公网ip 私网ip

实站:部署Redis集群

# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个 redis 配置
for port in $(seq 1 6);\
do \
mkdir -p /mydata/redis/node-$(port)/conf
cat <<EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

##通过脚本起动6个redis
docker run -p 637${port}:6379 -p1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1{port} redis:5.0.9 -alipine3.11 redis-server /etc/redis/redis.conf; \

## 创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

## docker 搭建redis 集群完成

我们使用了docker 之后,所有的技术都会慢慢的变提简单起来!

SpringBoot 微服务打包 Docker 镜像

  1. 构建 springboot 项目
  2. 打包应用
  3. 编写dockerfile
  4. 构建镜像
  5. 发布运行

待续
Docker Compose
Docker Swarm
CI/CD 之 Jenkins

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值