docker 概述
Docker 为什么会出现?
开发--上线 应用环境 , 应用配置!
开发--运维 问题:我在我的电脑上可以运行! 版本更新,导致服务不可用!对于运维来说,考验就十分大!
开发即运维
环境配置十分麻烦,每个机器都要部署环境,每个机器都要部署环境(集群Redis,ES,hadoop) 费时费力
发项目 jar,war + (Redis,MySQL,JDK,ES),项目是否可以带上环境打包!
之前在服务器配置应用环境Redis,MySQL,JDK,ES,hadoop, 配置麻烦,不能跨平台
Windows,最后发不到Linux
传统:jar -- > 运维,运维做部署!
现在:开发、打包、部署上线,一套流程做完!
java --> apk -->发布 (应用商店)---> 下载apk -->安装即可用
java --> jar(环境) --> 打包项目带上环境(镜像) ---> (Docker仓库:商店) ---> 下载我们发布的镜像---> 直接运行
Docker 给以上问题提出了解决方案!
Docker的思想来自于集装箱!
jre --> 多个应用(端口冲突) ---> 原来都是交叉的 !
隔离:Docker核心思想!打包装箱!每个箱子是相互隔离的
水果 | 生化武器
Docker通过隔离机制,将服务器利用到极致
所有的技术都是因为出现了问题,所以才出现!
docker 的历史
2010年,几个搞IT年轻人,在美国创建一家公司dotCloud,做PASS云计算服务,Linux 有关的虚拟机技术,他们将容器化技术,统一简化命名是Docker
Docker诞生没有引起行业注意!dot活不下去!开源了
2013年,Docker开源!越老越多人发现docker的优点!火了!Docker每个月更新版本!到了2014年4月9日,Docker1.0发布
Docker为什么这么火?相对于虚拟机技术十分轻巧
容器技术之前,使用的是虚拟机技术!
虚拟机:在windows中装一个Vmare,通过软件可以虚拟出一条和多台电脑,太笨重!
虚拟机也是属性虚拟化技术,docker是容器技术也是一种虚拟化技术!
容器技术:
vm : Linux centos镜像, 隔离,开启多个虚拟机
docker : 隔离, 镜像(最核心的环境 4m 装什么安什么)十分小巧,使用只要运行镜像就行了
现在所有开发人员必须要会docker
Docker 基于go 语言开发,开源项目:
官网地址:Docker: Accelerated Container Application Development
文档地址:Docker Docs
docker文档超级详细
仓库地址:
docker能干嘛
虚拟机技术:
虚拟机技术的缺点:
(1)资源占用十分多
(2)冗余步骤多
(3)启动很慢
容器化技术:
比较docker 和虚拟机技术的不同
(1)传统虚拟机,虚拟出一个硬件,运行一个完整的操作系统,然后在这个系统上安装和运行环境
(2)容器内的应用直接运行在宿主机的内容,容器是没有内核的,也没有虚拟硬件,所以就轻便了
(3)每个容器间相互隔离,每个容器都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
更快速的交付和部署
传统:一堆帮助文件,安装程序
Docker:一键运行打包镜像并发布测试
更编辑的升级和扩容
使用了docker之后,部署应用和搭积木一样(数据卷的概念)
(SpringBoot 1.5 Redis 5 tomcat 8)
项目打包为一个镜像,扩展 服务器A ! 直接在服务器B上一键运行即可
更简单的系统运维
在容器化之后,我们的开发和测试环境高度一致
更高效的计算资源利用
1核2G 的服务器 可以运行好多东西,因为docker是内核级别的虚拟化,可以在物理机上运行很多的容器实例,服务器的应能可以被压榨到极致
只要学不死,就往死里学
docker 安装
docker基本组成
镜像(image):
docker 镜像好比是一个模板,可以通过模板来创建一个容器服务,tomcat 镜像 ---> run ---> tomcat1容器(提供服务)
通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中)
容器(container):
Docker 利用容器技术,独立运行一个或者一组应用,通过镜像来创建
启动,停止,删除等基本命令!也可以把docker理解为一个简易的linux系统
仓库(repository):
仓库就是存放镜像的地方,
仓库分为共有仓库和私有仓库
官网的Docker Hub(默认国外的)
阿里云 ... 都有容器服务(配置镜像加速!)
安装docker
环境准备
1、需要会一点点的Linux基础
2、centos 7
3、使用xshell 连接远程服务器进行操作
我的腾讯云服务器:
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"
安装:
- 卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
- 需要安装包
yum install -y yum-utils
- 设置镜像仓库(阿里云、腾讯云都行,我买的是腾讯云)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 更新软件包索引
yum makecache fast
- 安装docker相关的
yum install docker-ce docker-ce-cli containerd.io
- 启动docker
systemctl start docker
docker version // 判断是否安装成功
- 测试hello world
docker run hello-world
- 查看helloword镜像
[root@VM-0-12-centos etc]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
了解:卸载docker
# 移除镜像
yum remove docker-ce docker-ce-cli containerd.io
# 删除包中的内容
rm -rf /var/lib/docker // docker 默认工作空间
镜像加速:
腾讯云的docker镜像加速和阿里的不一样,稍微有点麻烦
执行步骤
- 找到docker安装地址,创建或者修改/etc/docker/daemon.json,写入下面东西
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
]
}
- 依次执行下面命令
systemctl daemon-reload
service docker restart
- 检查是否生效
docker info
看到下面地址
Registry Mirrors:
https://mirror.ccs.tencentyun.com/
hello world的运行流程
底层原理
docker 是一个Client-server结构系统,docker的守护进程运行在主机上,通过Socket从客户端访问!
DockerServer接收DockerClient的指令,就会执行这个命令
Docker 为什么比虚拟机快?
1、Docker 有着比虚拟机少的抽象层。
2、Docker 利用的是宿主机的内核,VM需要gestOS
因此,新建容器,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机加载gust OS,分钟级别,而Docker利用的是宿主机的系统,省略这个过程
学完命令,回头看理论很清晰
docker 命令
帮助命令
docker version # docker 版本信息
docker info # docker 信息显示更加详细
docker 命令 --help # 帮助命令
docker 命令文档:Reference documentation | Docker Docs
镜像命令
docker images 查看本机镜像
[root@VM-0-12-centos docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像id
CREATED 创建时间
SIZE 镜像大小
-a, --all Show all images (default hides intermediate images)
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
-q, --quiet Only show image IDs
docker 搜索镜像地址:https://registry.hub.docker.com
docker search
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10247 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3785 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 749
Options:
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results (default 25)
--no-trunc Don't truncate outpu
--filter=STARS=3000 搜索出来的镜像就是stars大于3000
[root@VM-0-12-centos docker]# docker search mysql --filter=STARS=3785
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10247 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3785 [OK]
docker pull
# 下载镜像 docker pull 镜像[:tag]
[root@VM-0-12-centos docker]# docker pull redis
Using default tag: latest // 如果不写tat,默认最新的
latest: Pulling from library/redis
6ec7b7d162b2: Pull complete // 分层下载
1f81a70aa4c8: Pull complete
968aa38ff012: Pull complete
884c313d5b0b: Pull complete
6e858785fea5: Pull complete
78bcc34f027b: Pull complete
Digest: sha256:0f724af268d0d3f5fb1d6b33fc22127ba5cbca2d58523b286ed3122db0dc5381
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest // 真实地址
等价于
docker pull docker.io/library/redis:latest
docker pull mysql:5.7
[root@VM-0-12-centos docker]# docker pull mysql:5.7
5.7: Pulling from library/mysql
6ec7b7d162b2: Already exists
fedd960d3481: Pull complete
7ab947313861: Pull complete
64f92f19e638: Pull complete
3e80b17bff96: Pull complete
014e976799f9: Pull complete
59ae84fee1b3: Pull complete
7d1da2a18e2e: Pull complete
301a28b700b9: Pull complete
979b389fc71f: Pull complete
403f729b1bad: Pull complete
Digest: sha256:d4ca82cee68dce98aa72a1c48b5ef5ce9f1538265831132187871b78e768aed1
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rm
[root@VM-0-12-centos docker]# docker rmi -f 697daaecf703
Untagged: mysql:5.7
Untagged: mysql@sha256:d4ca82cee68dce98aa72a1c48b5ef5ce9f1538265831132187871b78e768aed1
Deleted: sha256:697daaecf703e82e8755034e816282fc3e912151b7818c85af8647fdcdcee517
Deleted: sha256:5214ea7c0bfb5429533d91b143604067a50042ae7b371dddb6ae53baadd3f7ef
Deleted: sha256:e9082a53da66fba9c49f51580500919310a36722cc4d3eb0c78e7000ad058655
Deleted: sha256:8615ae1ee613441540ee54a2c517eb0600a6c83667a79f7ca74acc9ffec4c9a4
Deleted: sha256:252efab3ecb7891820c5a340645044850d6edc7815c6588450d74b0a743424f4
Deleted: sha256:43b82d704a10e6d022fa3f31a5f827a00e339ee21dd2849a9b120ab82be9af71
Deleted: sha256:a4994702421d2b9a74c4f3810aa7ac09990e849905f23a1d8f358c826d58501f
Deleted: sha256:36c598c7a6f90abf6d67cde4a58b0747bfbcc7441d3b782bdeea7cda8c9ad7b6
Deleted: sha256:86f598b4f8200bdd4ae752f916154e4e29d5b4c211bb124eb150b9957a3e0141
Deleted: sha256:9e979d97f92bf78a225c77c6b4ba74eb2e03efb95b19b69206cd17cee15a4b26
Deleted: sha256:aff48ce4678f78d83d7e9bfb9e88cd951c3da52da08779e99b6082edd1cc66f3
[root@VM-0-12-centos docker]# docker rmi -f $(docker images -aq) #递归删除容器的所有
docker rmi -f 容器id 容器id 容器id
容器命令
说明:有了镜像才可以创建容器,Linux ,下载一个centos 镜像
docker pull centos
docker run 【可选项】image
--name="NAME" 容器名字 tomcat tomcat2, 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (使用最多)
-p 容器端口
容器端口
-P 随机指定端口号
# 测试 启动并进入容器
[root@VM-0-12-centos docker]# docker run -it centos /bin/bash
[root@630eb097aa1a /]#
[root@630eb097aa1a /]# ls // 查看内部的centos 基础版本,很多命令不完善
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
#退出主机命令
exit
列出所有的正在运行的程序
docker ps 命令
-a 列出当前和历史运行过的容器
-n=? 显示最近的几个
-q 只显示容器的编号
[root@VM-0-12-centos /]# docker ps // 正在运行的
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@VM-0-12-centos /]# docker ps -a //
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
630eb097aa1a centos "/bin/bash" 2 minutes ago Exited (0) 59 seconds ago musing_chatelet
b1669e5c4401 bf756fb1ae65 "/hello" 5 hours ago Exited (0) 5 hours ago sharp_albattani
退出容器
exit # 容器直接停止并退出
ctrl+p+q # 退出容器不停止
删除容器
docker rm 容器id 删除指定容器,不能删除正在运行的程序
docker rm -f $(docker ps -aq) #递归删除,删除所有的
docker ps -a -q | xargs docker rm #删除所有容器
启动和停止容器操作
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill #强制停止当前容器
常用的其他命令
后台启动容器
# 命令 docker run -d 镜像名!
[root@VM-0-12-centos /]# docker run -d centos
f28f8cc3dc8c332195f7fa37277480c4afd014ecf25411b36b52463561df1d5b
[root@VM-0-12-centos /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 问题docker ps ,发现centos停止了
# docker 容器使用后台进行,必须要有一个前台进程,docker 发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,没有程序了
查看日志命令
docker logs -f -t --tail 容器id
# 自己编写shell 脚本
[root@VM-0-12-centos /]# docker run -d centos /bin/sh -c "while true;do echo wwzhaohahaha; sleep 1; done"
e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812
[root@VM-0-12-centos /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e66f9e4a11c6 centos "/bin/sh -c 'while t…" 2 seconds ago Up 1 second infallible_turing
# 显示日志
-tf
--tail -number #显示的日志条数
[root@VM-0-12-centos /]# docker logs -f -t --tail 10 e66f9e4a11c6
查看容器中的进程信息
# 名称docker top 容器id
[root@VM-0-12-centos /]# docker top e66f9e4a11c6
UID PID PPID C STIME TTY TIME CMD
root 22956 22936 0 16:25 ? 00:00:00 /bin/sh -c while true;do echo wwzhaohahaha; sleep 1; done
root 23905 22956 0 16:30 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像元数据
[root@VM-0-12-centos /]# docker inspect e66f9e4a11c6
[
{
"Id": "e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812",
"Created": "2020-12-13T08:25:37.068574908Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo wwzhaohahaha; sleep 1; done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 22956,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-12-13T08:25:37.417799971Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812/hostname",
"HostsPath": "/var/lib/docker/containers/e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812/hosts",
"LogPath": "/var/lib/docker/containers/e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812/e66f9e4a11c6af140bb62da88cbdbcaafdf370a7ebd26d05bb3e3050347fe812-json.log",
"Name": "/infallible_turing",
"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/615f453441bcd945af111a0e1a6c67b9a7c7c3f45dde060cb5e3d805b209f0fa-init/diff:/var/lib/docker/overlay2/b0520a19b47b0a8a7898931d53ba99afe03ff261854c6a3af854d6c0f6dbfa12/diff",
"MergedDir": "/var/lib/docker/overlay2/615f453441bcd945af111a0e1a6c67b9a7c7c3f45dde060cb5e3d805b209f0fa/merged",
"UpperDir": "/var/lib/docker/overlay2/615f453441bcd945af111a0e1a6c67b9a7c7c3f45dde060cb5e3d805b209f0fa/diff",
"WorkDir": "/var/lib/docker/overlay2/615f453441bcd945af111a0e1a6c67b9a7c7c3f45dde060cb5e3d805b209f0fa/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "e66f9e4a11c6",
"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 wwzhaohahaha; sleep 1; done"
],
"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": "ea7d2412682d01ad3c689c6330456b715fda0eb2a88d6a9289a01cf0ca323358",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/ea7d2412682d",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "529eec257e87d143185e2accac705b804b06501480c56b547a76f73bf97f7a2c",
"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": "2191960cf43eef7cf1d5a24bfeecf83098ecf8a1608d8ed329c93c00b025bcbf",
"EndpointID": "529eec257e87d143185e2accac705b804b06501480c56b547a76f73bf97f7a2c",
"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
# 测试
root@VM-0-12-centos /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e66f9e4a11c6 centos "/bin/sh -c 'while t…" 5 hours ago Up 5 hours infallible_turing
[root@VM-0-12-centos /]# docker exec -it e66f9e4a11c6 /bin/bash
[root@e66f9e4a11c6 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:25 ? 00:00:05 /bin/sh -c while true;do echo wwzhaohahaha; sleep 1; done
root 19678 0 0 13:54 pts/0 00:00:00 /bin/bash
root 19700 1 0 13:54 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 19701 19678 0 13:54 pts/0 00:00:00 ps -ef
# 方式二
docker attach 容器id
[root@VM-0-12-centos ~]# docker attach e66f9e4a11c6
正在执行当前代码
#docker exec 进入容器开启一个新的连接,可以在里面操作(常用)
#docker attach 进入容器正在执行的连接,不会启动新进程
从容器内容拷贝到主机上
docker cp 容器id:路径 主机路径
#运行docker 镜像
[root@VM-0-12-centos ~]# docker run -it centos /bin/bash
# 退出docker
[root@90bdc67804ac /]# [root@VM-0-12-centos ~]#
[root@VM-0-12-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90bdc67804ac centos "/bin/bash" 11 seconds ago Up 10 seconds distracted_hugle
# 进入docker 镜像
[root@VM-0-12-centos ~]# docker attach 90bdc67804ac
[root@90bdc67804ac /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@90bdc67804ac /]# cd home/
# 查询并建立文件
[root@90bdc67804ac home]# ls
[root@90bdc67804ac home]# touch test.java
[root@90bdc67804ac home]# vi test.java
[root@90bdc67804ac home]# read escape sequence
[root@VM-0-12-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90bdc67804ac centos "/bin/bash" About a minute ago Up About a minute distracted_hugle
# docker 内文件拷贝到主机文件
[root@VM-0-12-centos ~]# docker cp 90bdc67804ac:/home/test.java /home/
[root@VM-0-12-centos ~]# cd /home/
[root@VM-0-12-centos home]# ls
test.java
# 拷贝是一个手动命令, 未来使用-v 卷的技术,可以实现,自动同步
将所有命令敲一遍,自己记录笔记
作业:Docker 安装Ngnix
- 搜索镜像 search 建议网站上下
docker search nginx
- 下载镜像 pull
docker pull nginx
- 启动(docker run -d --name nginx -p 外部端口:内部端口 nginx)
# docker 开启配置
# -d 后台运行
# --name 容器名称
# -p 宿主机端口:容器端口
[root@VM-0-12-centos ~]# docker run -d --name nginx02 -p 9203:80 nginx
cc6cd97977d76c10728f2b2626dc6c17b3dae4f0fac719251ee7e2d555a88328
# 本地测试
[root@VM-0-12-centos ~]# curl localhost:9203
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 测试通过,进入容器
root@VM-0-12-centos ~]# docker exec -it nginx02 /bin/bash
root@cc6cd97977d7:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@cc6cd97977d7:/# cd /etc/nginx/
root@cc6cd97977d7:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
端口暴露的概念
思考问题,每次改动nginx 配置文件,都需要进入容器?十分麻烦,如果可以在容器外部提供一个映射路径,达到在容器中修改,容器中相应的文件就会自动修改
作业:部署tomcat
# 官方使用
docker run -it --rm tomcat:9.0
# 之前使用都是后台,停止了容器之后,容器还是可以看得到docker run -it --rm tomcat:9.0用完就删除
# 启动运行
[root@VM-0-12-centos ~]# docker run -d --name tomat01 -p 9204:8080 tomcat
a1795b859c5e2bca33a089cab88cee82d4668facd6f3e98b667d32357c974e5a
# 测试访问
#进入容器
[root@VM-0-12-centos ~]# docker exec -it tomat01 /bin/bash
root@a1795b859c5e:/usr/local/tomcat# ll
bash: ll: command not found
root@a1795b859c5e:/usr/local/tomcat# ls -al
total 172
drwxr-xr-x 1 root root 4096 Dec 12 17:40 .
drwxr-xr-x 1 root root 4096 Dec 12 17:37 ..
-rw-r--r-- 1 root root 18982 Dec 3 11:48 BUILDING.txt
-rw-r--r-- 1 root root 5409 Dec 3 11:48 CONTRIBUTING.md
-rw-r--r-- 1 root root 57092 Dec 3 11:48 LICENSE
-rw-r--r-- 1 root root 2333 Dec 3 11:48 NOTICE
-rw-r--r-- 1 root root 3257 Dec 3 11:48 README.md
-rw-r--r-- 1 root root 6898 Dec 3 11:48 RELEASE-NOTES
-rw-r--r-- 1 root root 16507 Dec 3 11:48 RUNNING.txt
drwxr-xr-x 2 root root 4096 Dec 12 17:41 bin
drwxr-xr-x 1 root root 4096 Dec 14 00:25 conf
drwxr-xr-x 2 root root 4096 Dec 12 17:40 lib
drwxrwxrwx 1 root root 4096 Dec 14 00:25 logs
drwxr-xr-x 2 root root 4096 Dec 12 17:40 native-jni-lib
drwxrwxrwx 2 root root 4096 Dec 12 17:40 temp
drwxr-xr-x 2 root root 4096 Dec 12 17:40 webapps
drwxr-xr-x 7 root root 4096 Dec 3 11:45 webapps.dist
drwxrwxrwx 2 root root 4096 Dec 3 11:43 work
root@a1795b859c5e:/usr/local/tomcat#
# 发现问题 1. Linux 少了, 2. 没有webapps ,阿里云镜像的原因,默认是最小的进项,默认吧不必要的都剔除了
# 保证最小的可使用性
作业:部署es + kibana
es 暴露的端口多! 十分耗内存! 数据一般需要放置安全目录
# 启动 elasticsearch
# --net somenetwork 最新版本
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.10.1
# 太卡了,卡死了 docker stats 查看CPU状态
# es 十分消耗内存 1核2G ,穷
# 查看状态
docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
443207c50d9a elasticsearch 92.41% 1.271GiB / 1.795GiB 70.84% 656B / 0B 190MB / 778kB 47
fd1861b81adc nginx01 0.00% 1.422MiB / 1.795GiB 0.08% 1.91kB / 1.35kB 5.84MB / 8.19kB 2
90bdc67804ac distracted_hugle 0.00% 540KiB / 1.795GiB 0.03% 914B / 0B 0B / 0B 1
# 测试es 是否成功了
[root@VM-0-12-centos ~]# curl http://localhost:9200
{
"name" : "443207c50d9a",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "4ibpNW99TFag2QnHJXPwxg",
"version" : {
"number" : "7.10.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
"build_date" : "2020-12-05T01:00:33.671820Z",
"build_snapshot" : false,
"lucene_version" : "8.7.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
# 赶紧关闭,增加内存限制,修改配置文件 -e 环境变量
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.10.1
# 查看配置
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
3812e3971475 elasticsearch02 96.48% 354.5MiB / 1.795GiB 19.29% 656B / 0B 71.6MB / 344kB 31
fd1861b81adc nginx01 0.00% 1.422MiB / 1.795GiB 0.08% 2.03kB / 1.35kB 5.84MB / 8.19kB 2
90bdc67804ac distracted_hugle 0.00% 540KiB / 1.795GiB 0.03% 1.03kB / 0B 0B / 0B
# 验证:
[root@VM-0-12-centos ~]# curl http://localhost:9200
{
"name" : "3812e3971475",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "-5LpWYAIR6qM5fzRuXnj9g",
"version" : {
"number" : "7.10.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
"build_date" : "2020-12-05T01:00:33.671820Z",
"build_snapshot" : false,
"lucene_version" : "8.7.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
可视化
portainer(先用这个)
Rancher(CI/CD)
什么是Portainer?
Docker 图形化界面管理工具! 提供一个后台面板供我们操作!
docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
# 访问测试
设置密码
可视化面板
平常不会用
docker 镜像
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的内容,包括代码、运行时、库和配置文件。
所有的应用,直接打包呈docker镜像,就可以直接跑起来
如何得到镜像:
(1)从远程仓库下载
(2)朋友拷贝给你
(3)自己制作一个镜像
Docker 镜像加载原理
联合文件系统
UnionFS(联合文件系统),联合文件系统是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,联合文件系统是docker镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的镜像。
特性:一次可以同时加载多个文件系统,但是从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有的文件和目录。
docker 镜像加载原理
docker的镜像实际上是由一层层文件系统组成的,这种文件系统交UnionFs
bootfs(boot file system)主要包括bootloader和kernel,bootleader主要用于引导加载kernel,Linux刚启动的时候会加载bootfs文件系统,在docker镜像的最底层时bootfs,这一层与我们经典的LInux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成后整个内核就在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs.
rootfs(root file system),在bootfs之上,包含的就是单行的Linux系统中的/dev、/proc、/bin等标准目录和文件,rootfs就是各种不同操作系统的发行版,比如ubuntu、centos等。
而对于一个精简的OS,rootfs可以很小,只需要包含基本的命令、工具和程序库就可以了,因此底层直接用Host的Kernel,自己只需要提供rootfs就可以了,由此可见对于不同Linux发行版,bootfs基本相同,rootfs有所差别,因此不同发行版本可以公用bootfs
所以虚拟机启动时分钟级别的,而容器启动时秒级的
分层理解
下载一个mysql,观察日志输出,可以看到时一层一层下载的了
[root@VM-0-12-centos ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
6ec7b7d162b2: Already exists
fedd960d3481: Pull complete
7ab947313861: Pull complete
64f92f19e638: Pull complete
3e80b17bff96: Pull complete
014e976799f9: Pull complete
59ae84fee1b3: Pull complete
ffe10de703ea: Pull complete
657af6d90c83: Pull complete
98bfb480322c: Pull complete
9f2c4202ac29: Pull complete
a369b92bfc99: Pull complete
Digest: sha256:365e891b22abd3336d65baefc475b4a9a1e29a01a7b6b5be04367fcc9f373bb7
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
思考:为什么Docker镜像采用这种分层结构的呢?
查看镜像的下载情况:
[root@VM-0-12-centos ~]# docker inspect mysql
......
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:87c8a1d8f54f3aa4e05569e8919397b65056aa71cdf48b7f061432c98475eee9",
"sha256:8d77519601a52080d6e1e48d455df3b2646ec839a41f4566116c4058d1612eac",
"sha256:cb1c4d92429ddcbcbe3c43d2f4b8cea706cb47485f833c22aeb78725b593c8be",
"sha256:614fbc08d1b2e529d6a4b6975b7d193a232efc49f3359923d7efb2cfa6d73e3e",
"sha256:d4a3e8c51d197f372f9e1bba89eefe1c20e51ccb349211f9efbecc22ca64c95d",
"sha256:d0425b5c07f61692b1720f23afd5cd9b07f0bbf2e8cb2e52dcb971c81524436f",
"sha256:7d338559a103f8537c06b60bbda893b519f1d5f6ea7d79f2bd83a0cdee3c6120",
"sha256:d6710b52cd595cbfd4e2c75f5407dca20468b97c3deb860ac74cefd132b3c78c",
"sha256:3e98ba8dcb0acb5e725813a80810099fc5e50b1433e2689429fb93cdf3b96343",
"sha256:88000c6ddb1575d77413d07781df2d251fef4ce0a42f2688980cb21f3e79aaac",
"sha256:42c448223a4f8f1a3dc8608890efad088c026359efe58cbfa7251653379c718f",
"sha256:dc4da9ea5239cbba1fe183b690743956c9ef1e348089004148be941450a02c8e"
]
},
......
]
最大的好处就是,资源可以共享了,比如有多个镜像都是从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一根base镜像,同时内存中也只需要加载一份base镜像,就可以为所有容器服务了,因此这个镜像的每一层层都可以被共享
理解:
所有的docker镜像都是起始于一个基础镜像层,当进行修改或者增加新内容时,就会在当前镜像层之上创建新的镜像层
举个例子,假如在centos上面创建了一个新的镜像层,这个就是镜像的第一层;如果该镜像中添加python包,就会在基础层之上创建第二个镜像层,如果继续添加一个安全补丁就会创建第三个层。
在添加额外的镜像层的同时,镜像始终保持当前所有的镜像的组合,理解这一点非常重要,下图举个简短的例子,每个镜像层包含3个文件,而镜像时来自于六个文件。
上图中的镜像曾根之前途中的略有区别,主要目的时为了展示文件
下图展示了一个稍微复杂的三层镜像,在外部看来时6个文件,这是因为最上层中的文件7时文件5的一个更新版。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中文件是的文件的更新作为一个新的镜像层加载镜像中
Docker通过存储引擎(新版本采用快照机制)的方式实现镜像层堆栈,保证多个镜像层对外展示为统一的文件系统
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrf以及ZFS等,每种存储引擎都是基于Linux对应的文件系统或者块设备技术,并且这种存储引擎都是有其独有的特性。
Docker在Window上仅仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层
下图展示了与系统展示相同的三层镜像,所有镜像层堆叠并合并对外提供统一的试图。
特点:
Docker镜像都是只读的,当容器启动时,一个新的可写层被加到镜像顶部
这一层就是我们通常说的容器曾,容器曾之下的叫做镜像层。
commit 镜像
docker commit 提交容器成为一个新的副本
docker commit -m="提交信息" -a="作者" 容器id 目标名:[tag]
实战测试:
# 启动默认的tomcat
[root@VM-0-12-centos ~]# docker run -it -p 8080:8080 tomcat /bin/bash
# 官方默认webapps下面没有文件
# 自己拷贝基本文件
root@4afd716bf5a7:/usr/local/tomcat# cp -r webapps.dist/* webapps/
[root@VM-0-12-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4afd716bf5a7 tomcat "catalina.sh run" 2 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp vigilant_robinson
b78fae42345b redis "docker-entrypoint.s…" 6 hours ago Up 6 hours 0.0.0.0:6379->6379/tcp redis-test
bc601095c377 portainer/portainer "/portainer" 13 hours ago Up 13 hours 0.0.0.0:8088->9000/tcp nervous_chaplygin
fd1861b81adc nginx "/docker-entrypoint.…" 14 hours ago Up 14 hours 0.0.0.0:9203->80/tcp nginx01
90bdc67804ac centos "/bin/bash" 24 hours ago Up 24 hours distracted_hugle
# 提交版本 commit
[root@VM-0-12-centos ~]# docker commit -m="add personal info" -a="wwzhao" 4afd716bf5a7 vigilant_robinson:01
[root@VM-0-12-centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
vigilant_robinson 01 806121f8a322 11 seconds ago 653MB
tomcat latest 6d15a1d68603 45 hours ago 649MB
mysql latest ab2f358b8612 2 days ago 545MB
redis latest ef47f3b6dc11 2 days ago 104MB
nginx latest 7baf28ea91eb 3 days ago 133MB
centos latest 300e315adb2f 6 days ago 209MB
elasticsearch 7.10.1 558380375f1a 9 days ago 774MB
portainer/portainer latest 62771b0b9b09 4 months ago 79.1MB
方式:理解概念,但是一定要实践,最后实践和理论相结合一次搞定
保存当前的状态,可以通过commit体骄傲,获得一个镜像,就好比以前学习虚拟机,快照!
容器数据卷
什么是容器数据卷
docker 理念
将应用和环境打包成一个镜像
数据?如果数据都在容器中,那么我们将容器删除,数据会丢失!需求:数据可以持久化
MySQL,容器删除了,删库跑路了!需求:MySQL数据可以存储到本地!
容器之间可以有一个数据共享技术,Docker容器中产生的数据,同步到本地!这就是卷技术!目录的挂在,将我们容器内的目录挂在到虚拟机或者Linux中
总结一句话:容器的持久化同步操作!容器间也是可以共享的
使用数据卷
方式1:直接使用命令挂在 -v
docker run -it -v 主机目录:容器内目录
[root@VM-0-12-centos /]# docker run -it -v /home/ceshi:/home centos /bin/bash
[root@a65ec1edb720 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@a65ec1edb720 /]# cd /home/
[root@a65ec1edb720 home]# ls
[root@a65ec1edb720 home]# touch test.txt
[root@a65ec1edb720 home]# vi test.txt
主机
[root@VM-0-12-centos home]# cd ceshi/
[root@VM-0-12-centos ceshi]# ls
test.txt
[root@VM-0-12-centos ceshi]# cat test.txt
dfsggsgsdgxfgsfgs
[root@VM-0-12-centos ceshi]# docker inspect a65ec1edb720
数据同步
同步容器!
1、停止容器
2、宿主机上修改文件
3、启动容器
4、容器内的数据依旧是同步的
好处:以后修改后可以方便的把宿主机上的数据同步到容器内
安装mysql
启动:需要的数据挂载 # 安装启动mysql,需要配置密码,重点
docker run -d --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# -d 后台启动
# -p 端口映射
# -v 挂载卷
# -e 环境配置
# --name 容器名称
[root@VM-0-12-centos ~]# docker run -d -p 3302:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wwzhao123! --name mysql01 mysql
99f5c61659e601063b74cc9c4ae0e72ffc8a3662ccc24410dda52c93e5bba81a
# 启动之后,本地链接, navicat 会报client does not support authen,这时需要这样做
mysql> use mysql ;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql> alter user 'root'@'%' identified with mysql_native_password by 'wwzhao123!';
Query OK, 0 rows affected (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
# 检查映射路径是否正确
#容器删除,挂载到本地的数据卷依旧没有丢失
具名挂载和匿名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
docker volume --help
# 匿名卷挂载
[root@VM-0-12-centos ~]# docker volume ls
DRIVER VOLUME NAME
local 3eb951219b0f55baab18e31aa93b44e6837cdb9d20e583807474449725f99af8
local 42ac595e8d4cfbf653724d7e8aa70a13305d8a4f5ae4a226c10bccfa9985d9ee
local 53a9140445eb7134c064ec3d0ff35adc18ba3d247c89a25b00bb595d06d73012
local 03888af86a971c69210e8455dd618159d4c6f7e1a1ef9ceead2f922fe0b31c16
local c3eff2e7141efb0efbf88aecf8474cdc27f3f2d24162f3d2e60d76799719f372
local c16b0d5c87b41f21c8c1e7ee325805357e3e690a4d0f9a79e180e5dae754767e
# 这里发现,这种就是匿名局限,-v 只写了容器内部类的路径,而没有容器外的路径
[root@VM-0-12-centos ~]# docker run -d -P --name nginx03 -v juming-nignx:/etc/nginx nginx
1fd916b61e100651e0698ffa40b5838c8dd8918baa5a7f42125d49949e260fa2
[root@VM-0-12-centos ~]# docker volume ls
DRIVER VOLUME NAME
local 3eb951219b0f55baab18e31aa93b44e6837cdb9d20e583807474449725f99af8
local 42ac595e8d4cfbf653724d7e8aa70a13305d8a4f5ae4a226c10bccfa9985d9ee
local 53a9140445eb7134c064ec3d0ff35adc18ba3d247c89a25b00bb595d06d73012
local 03888af86a971c69210e8455dd618159d4c6f7e1a1ef9ceead2f922fe0b31c16
local c3eff2e7141efb0efbf88aecf8474cdc27f3f2d24162f3d2e60d76799719f372
local c16b0d5c87b41f21c8c1e7ee325805357e3e690a4d0f9a79e180e5dae754767e
local juming-nignx
[root@VM-0-12-centos ~]# docker volume inspect juming-nignx
[
{
"CreatedAt": "2020-12-16T00:25:32+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nignx/_data",
"Name": "juming-nignx",
"Options": null,
"Scope": "local"
}
]
#所有的数据都是存放在,没有指定目录的情况下都是在/var/lib/docker/volumes
# 可以通过具名挂在方便一个卷,大多数情况在使用 具名挂在
[root@VM-0-12-centos docker]# ls
buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
# 如何确定具名挂在匿名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #执行路径挂载
扩展:
通过 # -v 容器路径:ro rw 改变读写权限
#ro 只读
#rw 可读可写
#设置了容器权限,容器对我们挂载出来的内容就是确定了
docker run -d -P --name nginx03 -v jumping_nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx03 -v jumping_nginx:/etc/nginx:rw nginx
# ro 说明只能通过宿主机操作,容器内部不能扩展
初始docker File
DockerFile就是用来构建docker镜像的构建文件!命令脚本!体验,通过脚本可以生成一个镜像
镜像是一层一层的,每个脚本就是一层
# 创建一个Dockerfile文件,建议命名为Dockerfile
# 文件中的内容 指令都是(大写) 参数
[root@VM-0-12-centos docker-test-volume]# vim dockerfile1
[root@VM-0-12-centos docker-test-volume]# cat dockerfile1
FROM centos # 基础镜像
VOLUME ["volum01", "volume02"] ## 匿名挂载
CMD echo "---------ebd----------"
CMD /bin/bash
[root@VM-0-12-centos docker-test-volume]# docker build -f ./dockerfile1 -t wwzhao/centos .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volum01", "volume02"]
---> Running in 236d763784de
Removing intermediate container 236d763784de
---> d2f196890b88
Step 3/4 : CMD echo "---------ebd----------"
---> Running in 0b660a7ca8a5
Removing intermediate container 0b660a7ca8a5
---> 8f74f1ada31b
Step 4/4 : CMD /bin/bash
---> Running in f32425812a09
Removing intermediate container f32425812a09
---> c4142f3f0744
Successfully built c4142f3f0744
Successfully tagged wwzhao/centos:latest
# 启动自己启动的容器
[root@VM-0-12-centos docker-test-volume]# docker run -it wwzhao/centos /bin/bash
[root@6ed2444aad47 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 360 Dec 16 02:23 dev
drwxr-xr-x 1 root root 4096 Dec 16 02:23 etc
drwxr-xr-x 2 root root 4096 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 15:22 media
drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt
dr-xr-xr-x 106 root root 0 Dec 16 02:23 proc
dr-xr-x--- 2 root root 4096 Dec 4 17:37 root
drwxr-xr-x 11 root root 4096 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Dec 16 02:23 sys
drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec 4 17:37 var
drwxr-xr-x 2 root root 4096 Dec 16 02:23 volum01 # 生成的时候是自动挂载的 也是数据卷目录
drwxr-xr-x 2 root root 4096 Dec 16 02:23 volume02
# 在volume01中创建一个文件
查看
[root@VM-0-12-centos ~]# docker inspect 6ed2444aad47
[
......
"Mounts": [
{
"Type": "volume",
"Name": "63cbed5452e96348abff6d07a4209f5047b1e3214637bf8f480219d39662fff5",
"Source": "/var/lib/docker/volumes/63cbed5452e96348abff6d07a4209f5047b1e3214637bf8f480219d39662fff5/_data",
"Destination": "volum01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "5f837b68df526d6603df28293625d33c9a3b8c677606ae16ae94cfa857329962",
"Source": "/var/lib/docker/volumes/5f837b68df526d6603df28293625d33c9a3b8c677606ae16ae94cfa857329962/_data", // 挂载文件地址
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
]
[root@VM-0-12-centos ~]# cd /var/lib/docker/volumes/63cbed5452e96348abff6d07a4209f5047b1e3214637bf8f480219d39662fff5/_data
[root@VM-0-12-centos _data]# ls
test.java
# 这种方式使用的比较多,通常构建自己的镜像,假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
数据卷有一个和外部同步的目录
数据卷容器
两个mysql 同步数据
[root@VM-0-12-centos docker-test-volume]# docker run -it --name docker01 wwzhao/centos
[root@bd2739eb4ab0 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 360 Dec 16 02:37 dev
drwxr-xr-x 1 root root 4096 Dec 16 02:37 etc
drwxr-xr-x 2 root root 4096 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 15:22 media
drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt
dr-xr-xr-x 109 root root 0 Dec 16 02:37 proc
dr-xr-x--- 2 root root 4096 Dec 4 17:37 root
drwxr-xr-x 11 root root 4096 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Dec 16 02:23 sys
drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec 4 17:37 var
drwxr-xr-x 2 root root 4096 Dec 16 02:37 volum01
drwxr-xr-x 2 root root 4096 Dec 16 02:37 volume02
[root@bd2739eb4ab0 /]# cd volum01
[root@bd2739eb4ab0 volum01]# ls
[root@bd2739eb4ab0 volum01]# touch docker01create.txt
========================================================================
[root@VM-0-12-centos _data]# docker run -it --name docker02 --volumes-from docker01 wwzhao/centos
[root@73f81d17d187 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volum01 volume02
[root@73f81d17d187 /]# cd volum01
[root@73f81d17d187 volum01]# ls
docker01create.txt
# 在docker01 上创建的内容会自动同步到docker01上面
# --volumes-from 父子挂载
# docker01 子目录
docker run -it --name docker02 --volumes-from docker01 wwzhao/centos
[root@VM-0-12-centos ~]# docker run -it --name docker03 --volumes-from docker02 wwzhao/centos
[root@e16a61bdbbfa /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volum01 volume02
[root@e16a61bdbbfa /]# .cd volum
bash: $'\345\220\203cd': command not found
[root@e16a61bdbbfa /]# cd volum01/
[root@e16a61bdbbfa volum01]# ls
docker01create.txt
# 只要是 --volumes-from 可以实现文件的共享
# 删除docker02 ,docker01和docker03还是可以共享
各个docker 之间是双向拷贝的概念,共享卷,还是备份,而且中间的丢了,还是可以相互通信
mysql 主从配置
[root@VM-0-12-centos ~]# docker run -d -p 3302:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wwzhao123! --name mysql01 mysql
[root@VM-0-12-centos ~]# docker run -d -p 3302:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wwzhao123! --name mysql03 --volumes-from mysql01 mysql
两个容器数据之间同步
结论:
容器之间配置需不需的传递,数据卷容器生命周期一直持有直到没有容器使用为止。一旦持久化到本期本地,本地的数据是不会删除,永久存在
DockerFile
dockerFile是用来构建docker镜像文件!命令参数脚本!
构建步骤:
1、编写一个dockerFile文件
2、docker build构建一个镜像
3、docker run 运行镜像
4、docker push 发布镜像
查看官方怎么做的
官方的镜像都是基础包,很多功能都没有,我们通常自己搭建自己的包
做镜像
DockerFile的构建过程
基础知识:
1、每个保留关键字(指令)必须是大写字母
2、执行从上到下顺序执行
3、# 表示注释
4、每个指令都是都会创建一个层,并提交
dockerFile 是面向开发的,以后要发布项目,做镜像,就需要编写dockerFike文件,十分简单!
Docker镜像 SpringBoot微服务镜像 已经成为了企业交付的标准,必须要掌握!
步骤:开发、部署、运维,一个不能少
DockFile:构建文件,定义了一切的步骤,好比是一个源代码
DockerImages:通过DockFile构建生成的一个镜像,最终要发布和运行的产品,原来是jar war!
Dock容器:容器就是镜像运行起来提供服务的
DockerImages和dock容器是怎么用
DockerFile指令
FROM # 基础镜像 一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN #docker镜像构建的时候需要运行的命令
ADD # 步骤:搭建一个有tomcat镜像,这个tomcat压缩包!这个是添加的内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录位置
EXPOSE # 指定对外暴露的端口配置
RUN # 运行的
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效而且可以替代
ENTRYPOINT # 可以直接追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会被ONBUILD指令,触发指令
COPY # 类似ADD,将文件拷贝到镜像目录
ENV # 构建的时候设置环境变量
实战测试
Docker Hub中99%的镜像都是从这个基础镜像过来的FROM scratch,然后配置需要配置的文件
自己的Centos
# 1、编写DockFile文件
FROM centos
MAINTAINER wwzhao<614655386@qq.com>
ENV MYPATH /user/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----------end ------"
CMD /bin/bash
# 2、运行命令:
docker build -f ./dockerConfig -t mycentos .
运行结果:
Successfully built 83680d9ffbab
Successfully tagged mycentos:latest
# 3、测试运行
对比原生的,
(1)官方默认是更目录,增加镜像之后修改了命令
(2)没有其他的命令,
可以列出本地镜像的变更史
[root@VM-0-12-centos dockerfile]# docker history 83680d9ffbab
IMAGE CREATED CREATED BY SIZE COMMENT
83680d9ffbab 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
88617d1b2a9b 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
1205bee2602b 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
6a430a8263f8 5 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
66914c52f990 5 minutes ago /bin/sh -c yum -y install net-tools 23.3MB
69184a28b00e 5 minutes ago /bin/sh -c yum -y install vim 58MB
72804d058d01 5 minutes ago /bin/sh -c #(nop) WORKDIR /user/local 0B
a8d3fc2c298d 5 minutes ago /bin/sh -c #(nop) ENV MYPATH=/user/local 0B
8b7fd16df001 5 minutes ago /bin/sh -c #(nop) MAINTAINER wwzhao<6146553… 0B
300e315adb2f 8 days ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 8 days ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 8 days ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB
平时拿到一个镜像,研究一下他是怎么做的了?
CMD和ENTRYPOINT之间的区别
操作:
# 编写dockerFile文件
[root@VM-0-12-centos dockerfile]# vim docker-cmd-test
[root@VM-0-12-centos dockerfile]# cat docker-cmd-test
FROM centos
CMD ["ls", "-a"]
# 构建镜像
[root@VM-0-12-centos dockerfile]# docker build -f ./docker-cmd-test -t testcmd .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : CMD ["ls", "-a"]
---> Running in bab32428404e
Removing intermediate container bab32428404e
---> 318a3b6135b9
Successfully built 318a3b6135b9
Successfully tagged testcmd:latest
# run 运行镜像
[root@VM-0-12-centos dockerfile]# docker run 318a3b6135b9
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加一个命令
[root@VM-0-12-centos dockerfile]# docker run 318a3b6135b9 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
# cmd 清理了 -l 替换了["ls", "-a"] 不是命令就会报错
测试ENTRYPOINT
[root@VM-0-12-centos dockerfile]# vim docker-entrypoint-test
[root@VM-0-12-centos dockerfile]# docker build -f ./docker-entrypoint-test -t testentrypoint .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Running in b8ad21fb0d8a
Removing intermediate container b8ad21fb0d8a
---> 339f601bd3a6
Successfully built 339f601bd3a6
Successfully tagged testentrypoint:latest
# 追加命令是直接追加到命令后面的
[root@VM-0-12-centos dockerfile]# docker run 339f601bd3a6 -l
total 56
drwxr-xr-x 1 root root 4096 Dec 16 04:21 .
drwxr-xr-x 1 root root 4096 Dec 16 04:21 ..
-rwxr-xr-x 1 root root 0 Dec 16 04:21 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 340 Dec 16 04:21 dev
drwxr-xr-x 1 root root 4096 Dec 16 04:21 etc
drwxr-xr-x 2 root root 4096 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 15:22 media
drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt
dr-xr-xr-x 123 root root 0 Dec 16 04:21 proc
dr-xr-x--- 2 root root 4096 Dec 4 17:37 root
drwxr-xr-x 11 root root 4096 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Dec 16 02:23 sys
drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec 4 17:37 var
dockerfile中好多命令十分相似,需要了解他们之间的区别,最后的就是对比测试。
实战:tomcat文件打包
1、准备文件,tomcat 压缩包,jdk压缩包
[root@VM-0-12-centos wwzhao]# ls
apache-tomcat-9.0.41.tar.gz jdk-8u172-linux-x64.tar.gz readme.txt
2、编写dockerfile文件夹,官方命名DockerFile,build会自动寻找这个文件,就不需要指定了
FROM centos
MAINTAINER wwzhao<614655386@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u172-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.41.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local/
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk-8u172-linux-x64
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.41
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.41
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.41/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.41/bin/logs/catalina.out
3、构建镜像
# 通过docker bulild -t wwzhaojingxiang
4、启动
5、访问测试
6、发布项目(由于做了卷挂载,我们可以直接在本地发布)
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.emphasis{color: blue; text-decoration: underline;}
</style>
<title>作业</title>
</head>
<body>
<img src="ding.png">
<table width="800px" height="300px" >
<td height="100px" width="1000"></td>
<form>
<fieldset>
<legend>第一步:软件下载</legend>
<h5 style="color:red;">通过网页可以直接登陆软件,但为了更好的操作体验,强烈建议下载并安装。
</h5>
<h5>软件下载地址:
<a href="">电信</a>
<a href="">联通</a>(右键为另存为或使用工具下载)
</h5>
</fieldset>
</form>
<form>
<fieldset>
<legend>第二步:填写企业信息</legend>
<h5>※企业名称:<input type="text" maxlegenth="30" style="width:200px"> </h5>
<h5>※所属行业:
<input type="text" maxlength="30" value="请选择....">
<select>
<option value="geti">个体</option>
<option value="nongmin">农民</option>
<option value="gongwuyuan">公务员</option>
<option value="shangren">商人</option>
</select> (系统会根据行业自动选择版本,请认真选择)
</h5>
<h5>※所在区域:
<select>
<option value="beijing">北京</option>
<option value="sichuan">四川</option>
<option value="hunan">湖南</option>
</select>
<select>
<option value="beijing">北京</option>
<option value="chengdushi">成都市</option>
<option value="hunanshi">湖南市</option>
</select>
<select>
<option value="dongchengqu" >东城区</option>
<option value="qingniequ">青牛区</option>
<option value="beiqu">北区</option>
</select>
<input type="text" maxlength="30">
</h5>
<h5>※联系人:
<input type="text" maxlength="30">
<select>
<option value="xiansheng">先生</option>
<option value="nvshi">女士</option>
</select>
</h5>
<h5>※联系电话:
<input type="text" value="建议输入手机号码">
</h5>
<h5>验证手机:
<input type="text" maxlength="30" <p><span class="emphasis">获取短信验证码,立即使用</span></p>>
</h5>
<h5>短信验证码:
<input type="text" maxlength="30">(如果不使用短信验证,需人工审核后开通试用)
</h5>
<h5>QQ:
<input type="text" maxlength="30">
</h5>
</fieldset>
</form>
<form>
<fieldset>
<legend>第三步:填写软件登录账号及密码</legend>
<h5>※登录账号:
<input type="text" maxlength="30" value="可以使用企业简称或拼音字母">
<a href="">检测账号</a>
</h5>
<h5>※管理工号:
<input type="text" maxlength="30" value="10000">管理工号默认10000,无需要再次填写,登录时使用
</h5>
<h5>※管理密码:
<input type="text" maxlength="30">
</h5>
<h5>※再次输入密码:
<input type="text" maxlength="30">
</h5>
</fieldset>
</form>
<input type="submit" value="提交">
<input type="reset" value="返回登录">
</body>
</html>
发布自己的镜像
1、注册账号
2、确定账号可以登录
3、在我们的服务器上可以提交镜像
[root@VM-0-12-centos logs]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in 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
[root@VM-0-12-centos logs]# docker login -u wwzhao
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@VM-0-12-centos logs]# docker tag 261c7b4e52e2 wwzhao/tomcatcontainer:1.0
[root@VM-0-12-centos logs]# docker push wwzhao/tomcatcontainer:1.0
The push refers to repository [docker.io/wwzhao/tomcatcontainer]
c83272bca8d8: Pushing [=> ] 1.664MB/58.02MB
3d8b40898846: Pushing [> ] 158.7kB/15.83MB
17cb46f0638f: Pushing [> ] 2.178MB/387.4MB
63d6b307ccdb: Pushing 2.56kB
2653d992f4ef: Pushing [>
阿里云私有
1、登录阿里云
2、找到容器服务
3、创建命名空间
4、创建容器
小结:
Docker 网络原理
docker0 网络
测试
[root@VM-0-12-centos ~]# 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 pfifo_fast state UP group default qlen 1000 # 腾讯云内部服务器
link/ether 52:54:00:84:d2:a5 brd ff:ff:ff:ff:ff:ff
inet 172.21.0.12/20 brd 172.21.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe84:d2a5/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:39:a3:47:11 brd ff:ff:ff:ff:ff:ff # docker地址
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:39ff:fea3:4711/64 scope link
valid_lft forever preferred_lft forever
docker 是如何处理容器网络访问的?
ip addr 容器启动时候会得到一个eth0@if147 ip地址,由Linux分配
[root@VM-0-12-centos ~]# 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
146: eth0@if147: <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 容器内部
原理:
1、每安装一个docker容器,docker就会给dockers分配一个ip,只要安装了docker就会配分配一个网卡docker0,使用的模式桥接模式,这种技术是evth-pair
再次获得地址:
[root@VM-0-12-centos ~]# 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 pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:84:d2:a5 brd ff:ff:ff:ff:ff:ff
inet 172.21.0.12/20 brd 172.21.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe84:d2a5/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:39:a3:47:11 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:39ff:fea3:4711/64 scope link
valid_lft forever preferred_lft forever
147: veth2e88a75@if146: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 86:91:5a:d6:4b:33 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::8491:5aff:fed6:4b33/64 scope link
valid_lft forever preferred_lft forever
- 在启动一个tomcat
[root@VM-0-12-centos ~]# 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 pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:84:d2:a5 brd ff:ff:ff:ff:ff:ff
inet 172.21.0.12/20 brd 172.21.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe84:d2a5/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:39:a3:47:11 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:39ff:fea3:4711/64 scope link
valid_lft forever preferred_lft forever
147: veth2e88a75@if146: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 86:91:5a:d6:4b:33 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::8491:5aff:fed6:4b33/64 scope link
valid_lft forever preferred_lft forever
149: veth0254247@if148: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c2:26:c0:76:0d:6c brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::c026:c0ff:fe76:d6c/64 scope link
valid_lft forever preferred_lft forever
网卡成对出现
evth-pair就是一堆虚拟设备,他们都是成对出现的,一段连接着协议,一段彼此相连,真因为有这个特性,evth-pair就可以通信了,连接网络设备了
OpenStack、Docker、OVS连接都是evth-pair技术
- 测试tomcat01和tomcat02是否可以ping通
[root@VM-0-12-centos ~]# docker exec -it tomcat02 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
148: eth0@if149: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@VM-0-12-centos ~]# 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
146: eth0@if147: <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
[root@VM-0-12-centos ~]# docker exec -it tomcat01 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.056 ms
^C
# 结论:容器和容器之间可以互相ping通的
网络模型图
结论:tomcat01和tomcat02 是公用的一个路由器,docker0
所有的容器在不指定网络的情况下,都是由docker0路由的docker个我们分配一个网络
docker使用的是桥接模式
删除了之后网络就会少一对
--link
思考一个场景,微服务:database url=ip,项目不重启,数据库ip不变也是可以访问服务
[root@VM-0-12-centos ~]# docker run -d -P --name tomcat03 --link tomcat01 tomcat
9826f43754fbdb18e18a371d71f185eb6acc4616047ae5b25e34136b2e90e901
# 可以根据服务名通信
[root@VM-0-12-centos ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.056 ms
# 反向ping
[root@VM-0-12-centos ~]# docker exec -it tomcat01 ping tomcat03
ping: tomcat03: Name or service not known
[root@VM-0-12-centos ~]# docker inspect 2191960cf43e
[
{
"Name": "bridge",
"Id": "2191960cf43eef7cf1d5a24bfeecf83098ecf8a1608d8ed329c93c00b025bcbf",
"Created": "2020-12-13T11:52:12.83846048+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": {
"2cce28ed3c3b0e3ac843369457977636186026072196dd10815d26d8661df262": {
"Name": "tomcat02",
"EndpointID": "5d52daf7658e4a918744f8c345c7b60e9c5087cee06a3e4422992b261630ac95",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"4f0d482bf453806d7d45412c33404020fea694aac6fa9a61653ff257029dd655": {
"Name": "tomcat01",
"EndpointID": "609b2e459dcf593cc89f6c9624615464fe05fd8915a1bbb0a29f6b18449e6c32",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"9826f43754fbdb18e18a371d71f185eb6acc4616047ae5b25e34136b2e90e901": {
"Name": "tomcat03",
"EndpointID": "bf3e33f435e4792529d1db8215b3d11af9338b034722c6d07a80549921c951a3",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
查看配置hosts
[root@VM-0-12-centos ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 tomcat01 4f0d482bf453 // 直接配好了
172.17.0.4 9826f43754fb
--link 在hosts中增加了tomcat01的配置
太他妈的麻烦了,不推荐使用了
dcoker0不支持容器名
定义网络
查看所有的docker网络
[root@VM-0-12-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2191960cf43e bridge bridge local
001f0b5a3f94 host host local
42c4fc7e99f8 none null local
网络模式
bridge : 桥接模式 docker 搭桥
none :不配置网络
host:和宿主机共享网络
container:容器内网络联通!(用的少!局限性很大)
测试
# 直接启动的命令,默认是 --net bridge 就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0 特点,默认,域名不能访问,--link可以打通连接
# 自定义网络实现
# 创建一个自定义
# --driver bridge
# subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@VM-0-12-centos ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
f3efaaef000e5e8607cd4a608ffa14c8b2cbe93374bf19b9819d7824a854ffb6
[root@VM-0-12-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2191960cf43e bridge bridge local
001f0b5a3f94 host host local
f3efaaef000e mynet bridge local
42c4fc7e99f8 none null local
# 自己的网络已经创建好了
[root@VM-0-12-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "f3efaaef000e5e8607cd4a608ffa14c8b2cbe93374bf19b9819d7824a854ffb6",
"Created": "2020-12-18T21:42:30.306486047+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
[root@VM-0-12-centos ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
cfaa6697880449df2a2a946ecaf6b066745150671d01ccf5cb946ed975cd1bd7
[root@VM-0-12-centos ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
6a579289b608e473010bda2a821fa86f1a61690268c7921f3c028972b2f8069a
[root@VM-0-12-centos ~]# docker network inspect ls mynet
[
{
"Name": "mynet",
"Id": "f3efaaef000e5e8607cd4a608ffa14c8b2cbe93374bf19b9819d7824a854ffb6",
"Created": "2020-12-18T21:42:30.306486047+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"6a579289b608e473010bda2a821fa86f1a61690268c7921f3c028972b2f8069a": {
"Name": "tomcat-net-02",
"EndpointID": "d149db80f2fca5bcb29e82971caf4fbec83731865387ed0c77d23644bbba1dbd",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"cfaa6697880449df2a2a946ecaf6b066745150671d01ccf5cb946ed975cd1bd7": {
"Name": "tomcat-net-01",
"EndpointID": "82c9ff69e6712df155169757d0a168b888d50c4516007a47af62310303a829d6",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 无论名称还是ip都能ping通
[root@VM-0-12-centos ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.091 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.061 ms
^C
--- tomcat-net-02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.061/0.076/0.091/0.015 ms
[root@VM-0-12-centos ~]# docker exec -it tomcat-net-01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.041 ms
^C
--- 192.168.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.034/0.037/0.041/0.007 ms
自定义的网络docker都已经维护了这个关系,推荐平时使用自定义网络
好处:
redis 不同集权使用不同的网络,保证集群是安全健康的
mysql 不同集权使用不同的网络,保证集群是安全健康的
网络联通
[root@VM-0-12-centos ~]# 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@VM-0-12-centos ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
[root@VM-0-12-centos ~]# docker network connect mynet tomcat-01
[root@VM-0-12-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "f3efaaef000e5e8607cd4a608ffa14c8b2cbe93374bf19b9819d7824a854ffb6",
"Created": "2020-12-18T21:42:30.306486047+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"69d2ca8e5d7da309ee2da5877a6f5fc8dbc93e34fd58681e2b5a0366c495e27f": {
"Name": "tomcat-01",
"EndpointID": "dbb50af0077ceaba2b51c5863f049f25be1ff2cca37e1e3f615c67aad1587c0a",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"6a579289b608e473010bda2a821fa86f1a61690268c7921f3c028972b2f8069a": {
"Name": "tomcat-net-02",
"EndpointID": "d149db80f2fca5bcb29e82971caf4fbec83731865387ed0c77d23644bbba1dbd",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"cfaa6697880449df2a2a946ecaf6b066745150671d01ccf5cb946ed975cd1bd7": {
"Name": "tomcat-net-01",
"EndpointID": "82c9ff69e6712df155169757d0a168b888d50c4516007a47af62310303a829d6",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
[root@VM-0-12-centos ~]# docker exec -it tomcat-net-01 ping tomcat-01
PING tomcat-01 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat-01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from tomcat-01.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.064 ms
^C
--- tomcat-01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.062/0.063/0.064/0.001 ms
[root@VM-0-12-centos ~]# docker exec -it tomcat-net-01 ping tomcat-02
ping: tomcat-02: Name or service not known
[root@VM-0-12-centos ~]# docker network connect mynet tomcat-02
[root@VM-0-12-centos ~]# docker exec -it tomcat-net-01 ping tomcat-02
PING tomcat-02 (192.168.0.5) 56(84) bytes of data.
64 bytes from tomcat-02.mynet (192.168.0.5): icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from tomcat-02.mynet (192.168.0.5): icmp_seq=2 ttl=64 time=0.054 ms
^C
--- tomcat-02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.054/0.062/0.071/0.011 ms
redis 集群部署
docker搭建集群相当的快
docker network create redis --subnet 172.28.0.0/16
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >>/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.28.0.1${port}
cluster-announce-port 6379
cluster-announce-port 16379
appendonly yes
EOF
done
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.28.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 637${port}:6379 -p 1637${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-alpine3.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
spring-boot项目docker运行
1、建立springboot项目
2、开发程序
3、编写dockerfile文件
4、打包运行
5、上传到服务器
6、build\run
docker build -f Dockerfile -t spring-boot-first .
docker run -d -p 8080:8080 --name spring-boot-first spring-boot-first
7、测试
curl http://localhost:8080/test/test