Docker
Docker学习
- Docker概述
- Docker安装
- Docker命令
- Docker镜像
- 容器数据卷
- DockerFile
- Docker网络原理
- IDEA整合Docker
- Docker Compose(集群)
- Docker Swarm
- CI\CD Jenkins流水线
Docker概述
Docker为什么会出现?
一款产品:开饭—上线!两套环境,应用环境,应用配置
开发-----运维。问题?明明在我的电脑上可以运行,怎么你这里就不行呢?版本更新导致服务不可用,对于运维来说,考验就十分大,开发即运维
环境配置是十分麻烦的,每一个机器都要部署环境(集群Redis,ES,Hadoop…) !费时费力
发布一个项目jar(Redis,MySQL,jdk,ES) ,项目能不能带上环境安装打包!
之前在服务器配置一个应用的环境Redis,Mysql,jdk,ES,Hadoop,配置超级麻烦,不能够跨平台。
Windows发布到Linux!环境差别很大
传统的运维:Jar,运维来做部署的事情
现在:开发打包部署上线,一套流程做完!
Docker给以上的问题提出了解决方案!
Docker的思想来自于集装箱,每个箱子都是相互隔离的。Dokcer通过隔离机制,可以将服务器利用到极致
Docker的历史
2010年,几个搞IT的年轻人,就在美国成立了一家公司,dotCloud
做一些pass的云计算服务!LXC有关的容器技术!
他们将自己的技术(容器化技术)命名,就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意 dotCloud,就活不下去
开源,开放源代码
2013年,将Docker开源
Docker越来越多的人发现了Docker的优点!火了,Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布
Docker为什么这么火? 十分的轻巧
在容器技术出来之前,我们都是使用虚拟机技术,VMware
虚拟机:在windows中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
vm:linux centos原生镜像(一个电脑)隔离,需要开发多个虚拟机
Docker:隔离,镜像(最核心的环境 4m,+jdk+mysql),十分的小巧,运行镜像就可以了,小巧。
到现在,所有开发人员都必须要会Docker
聊聊Docker
Docker是基于Go语言开发的,
文档地址,Docker的文档是很详细的
Docker镜像中心 ,远程仓库
Docker能干嘛?
之前的虚拟机技术
虚拟机技术缺点:
- 资源占用十分多
- 冗余步骤多
- 启动非常慢
容器化技术
容器化技术不是模拟的一个完整的操作系统
比较Docker和虚拟机技术的不同
- 传统的虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用是直接运行在宿主机内,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间是互相隔离的,每个容器内都有一个属于自己的文件系统。互不影响
DevOps(开发运维)
更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就和搭积木一样
项目打包为一个镜像,扩展服务器A,服务器B。
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压榨到极致
Docker安装
Docker的基本组成
镜像(image)
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像====》tomcat容器(提供服务器),
通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器的)
容器(container)
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令
目前就可以吧这个容器理解为一个简易的linux系统
仓库(repository)
仓库就是存放镜像的地方!
仓库分为共有仓库和私有仓库!
Docker Hub
阿里云。。。都有容器服务器(配置镜像加速)
安装Docker
环境准备
- 需要会一点点linux基础
- CentOS 7
- 使用xshell连接远程服务器进行操作
环境查看
# 系统内核是3.10以上的
[root@iZwz90og9utae1lg37hyz7Z ~]# uname -r
3.10.0-1062.18.1.el7.x86_64
# 系统版本
[root@iZwz90og9utae1lg37hyz7Z ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
安装
[查看帮助文档]([root@iZwz90og9utae1lg37hyz7Z ~]# cat /etc/os-release NAME=“CentOS Linux” VERSION=“7 (Core)” ID=“centos” ID_LIKE=“rhel fedora” VERSION_ID=“7” PRETTY_NAME=“CentOS Linux 7 (Core)” ANSI_COLOR=“0;31” CPE_NAME=“cpe:/o:centos:centos:7” HOME_URL=“https://www.centos.org/” BUG_REPORT_URL=“https://bugs.centos.org/” CENTOS_MANTISBT_PROJECT=“CentOS-7” CENTOS_MANTISBT_PROJECT_VERSION=“7” REDHAT_SUPPORT_PRODUCT=“centos” REDHAT_SUPPORT_PRODUCT_VERSION=“7”)
明确说明需要centos7以上才支持,首先需要卸载久的版本
# 1、卸载旧的版本
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2、需要的安装包
$ sudo yum install -y yum-utils
# 3、设置镜像的仓库
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认是从国外的!
$ sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 使用阿里云的,十分快
# 更新yum软件包索引
[root@iZwz90og9utae1lg37hyz7Z ~]# yum makecache fast
# 4、安装docker引擎 docker-ce 社区版 ee企业版
$ sudo yum install docker-ce docker-ce-cli containerd.io
# 5、启动docker
$ sudo systemctl start docker
# 6、使用 docker version 测试是否安装成功
# 7、测试hello-world
$ sudo docker run hello-world
# 8、查看一下下载的这个hello world在不在
[root@iZwz90og9utae1lg37hyz7Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 4 months ago 13.3kB
# 9、卸载docker
$ sudo yum remove docker-ce docker-ce-cli containerd.io # 卸载依赖
$ sudo rm -rf /var/lib/docker # 删除资源(docker默认的资源路径)
阿里云镜像加速
1、登入阿里云,找到容器镜像服务
2、找到镜像加速地址
3、配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://ggb52j62.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
回顾HelloWorld流程
run的流程分析图
底层原理
Docker是怎么工作的?
Docker是一个Client-Server 结构的系统,Docker的守护进程进行在主机上,通过Socket从客户端访问!
DockerServer接收到Docker-Client的指令,就会执行这个命令
Docker为什么比VM快
- Docker有比虚拟机更少的抽象层
- Docker利用的是宿主机的内核,VM是需要GuestOS。
所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的,
而docker是利用宿主机的操作系统,省略了这个复杂的过程,是秒级别的。
Docker的常用命令
帮助命令
docker version # 显示docker版本信息
docker info # 显示docker的系统信息,包括镜像和容器的信息
docker 命令 --help # 帮助命令
帮助文档的命令:https://docs.docker.com/reference/
镜像命令
docker images 查看所有本主机的镜像
[root@iZwz90og9utae1lg37hyz7Z /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 4 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的版本信息,标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像id
docker search 搜索镜像
[root@iZwz90og9utae1lg37hyz7Z /]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 9566 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3473 [OK]
# 可选项
--filter=STARS=3000 # 过滤收藏数大于3000的
[root@iZwz90og9utae1lg37hyz7Z /]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 9566 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3473 [OK]
**docker pull ** 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
[root@iZwz90og9utae1lg37hyz7Z /]# docker pull mysql
Using default tag: latest # 如果不写版本,默认下载最新版
latest: Pulling from library/mysql
afb6ec6fdc1c: Pull complete # 分层下载:docker image的核心,联合文件系统
0bdc5971ba40: Pull complete
97ae94a2c729: Pull complete
f777521d340e: Pull complete
1393ff7fc871: Pull complete
a499b89994d9: Pull complete
7ebe8eefbafe: Pull complete
597069368ef1: Pull complete
ce39a5501878: Pull complete
7d545bca14bf: Pull complete
211e5bb2ae7b: Pull complete
5914e537c077: Pull complete
Digest: sha256:a31a277d8d39450220c722c1302a345c84206e7fd4cdb619e7face046e89031d # 签名 防伪
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址
# 其实这两个命令是等价的
docker pull mysql
docekr pull docker.io/library/mysql:latest
# 指定版本下载
[root@iZwz90og9utae1lg37hyz7Z /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
afb6ec6fdc1c: Already exists
0bdc5971ba40: Already exists
97ae94a2c729: Already exists
f777521d340e: Already exists
1393ff7fc871: Already exists
a499b89994d9: Already exists
7ebe8eefbafe: Already exists
4eec965ae405: Pull complete
a531a782d709: Pull complete
270aeddb45e3: Pull complete
b25569b61008: Pull complete
Digest: sha256:d16d9ef7a4ecb29efcd1ba46d5a82bda3c28bd18c0f1e3b86ba54816211e1ac4
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi -f 删除镜像
[root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f 镜像id # 删除指定镜像
[root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像(空格分开)
[root@iZwz90og9utae1lg37hyz7Z /]# docker rmi -f $(docker images -qa) #骚操作,采用联合查询删除所有镜像
容器命令
说明:有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run[可选参数] 镜像id
#参数说明
--name = "Name" #给容器取个别名 tomcat01 tomcat02
-d #后台方式运行
-it #使用交互方式运行,进入容器查看内容
-p(小写) #指定容器的端口,8080:8080
-p 主机端口:容器端口 (常用)
-p 容器端口
-P(大写) #随机指定端口
# 测试,启动并进入容器
[root@iZwz90og9utae1lg37hyz7Z /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 470671670cac 4 months ago 237MB
[root@iZwz90og9utae1lg37hyz7Z /]# docker run -it 470671670cac /bin/bash
[root@eea5ced1bcb8 /]# ls # 查看容器内容的centos,基础版本很多命令不完善
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退回主机
[root@eea5ced1bcb8 /]# exit
列出所有运行中的容器
# docker ps 命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q # 只显示容器的编号
[root@iZwz90og9utae1lg37hyz7Z /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
[root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
eea5ced1bcb8 470671670cac "/bin/bash" 5 minutes ago Exited (127) 2 minutes ago
7c6d68fe38bf bf756fb1ae65 "/hello" 29 minutes ago Exited (0) 29 minutes ago
47934e45992d bf756fb1ae65 "/hello" 3 hours ago Exited (0) 3 hours ago
[root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
eea5ced1bcb8 470671670cac "/bin/bash" 9 minutes ago Exited (127) 6 minutes ago
[root@iZwz90og9utae1lg37hyz7Z /]# docker ps -aq
eea5ced1bcb8
7c6d68fe38bf
47934e45992d
退出容器
exit #直接容器停止并退出
Ctrl+P+Q #容器不停止退出
删除容器
docker rm 容器id #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm-f
docekr rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
启动和停止容器的操作
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
常用的其他命令
后台启动容器
# docker run -d 镜像名
[root@iZwz90og9utae1lg37hyz7Z /]# docker run -d centos
# 问题:docker ps ,发现centos停止了??
#常见的坑:docker容器使用后天运行,就必须要有一个前天进程,docker发现没有应用,就会自动停止
#nginx,容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了
查看日志
docker logs [可选项]
-tf # 显示日志
--tail number # 显示日志条数
[root@iZwz90og9utae1lg37hyz7Z /]# docker logs -tf --tail 10 容器id
查看容器中的进程信息 ps
#命令 docker top 容器id
[root@iZwz90og9utae1lg37hyz7Z ~]# docker top d7f8882680a1
UID PID PPID C STIME TTY TIME
root 22262 22245 0 17:40 pts/0 00:00:00
查看镜像的元数据
#命令 docker inspect 容器id
# 测试
[root@iZwz90og9utae1lg37hyz7Z ~]# docker inspect d7f8882680a1
[
{
"Id": "d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94",
"Created": "2020-05-30T09:40:07.580695306Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 22262,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-05-30T09:40:07.935601958Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",
"ResolvConfPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/hostname",
"HostsPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/hosts",
"LogPath": "/var/lib/docker/containers/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94/d7f8882680a11fa697b52b00487f927becadff47500d9164be3ef3c5b5151f94-json.log",
"Name": "/gallant_austin",
"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,
"Capabilities": null,
"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/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284-init/diff:/var/lib/docker/overlay2/e1d29bc072eab6c1fafe40da590a23718c50eb94cf0dc9b63a6445795d2e2e69/diff",
"MergedDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/merged",
"UpperDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/diff",
"WorkDir": "/var/lib/docker/overlay2/ca896847bd3647809cf2bb90a22239e99a33cee8158cfcd958020aebff46b284/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "d7f8882680a1",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"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": "20200114",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS",
"org.opencontainers.image.created": "2020-01-14 00:00:00-08:00",
"org.opencontainers.image.licenses": "GPL-2.0-only",
"org.opencontainers.image.title": "CentOS Base Image",
"org.opencontainers.image.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "3c28f68ab437d44fc52e3132fe473dac6f8c4f217860af2c44164863c6e6b192",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/3c28f68ab437",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "518937c65fb1d275e0dfb828fee65418dda8ddc497a6e0cbc62867474f3b808b",
"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": "912b291ba3c83933000fd3176a476f87bbbb02aa38d5ef59511f5a2e4fc43e2b",
"EndpointID": "518937c65fb1d275e0dfb828fee65418dda8ddc497a6e0cbc62867474f3b808b",
"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@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it d7f8882680a1 /bin/bash
# 进入容器后的操作
[root@d7f8882680a1 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:40 pts/0 00:00:00 /bin/bash
root 17 0 0 09:53 pts/1 00:00:00 /bin/bash
root 30 17 0 09:53 pts/1 00:00:00 ps -ef
#方式二:
docker attach 容器id
#测试
[root@d7f8882680a1 /]# docker attach d7f8882680a1
正在执行当前的代码。。。
# docker exec #进入容器后进入一个新的终端,可以在里面操作
# docker attach #进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
# 测试,将容器内的test.java文件复制到主机的home目录下
# 进入容器内部
[root@iZwz90og9utae1lg37hyz7Z home]# docker attach d7f8882680a1
[root@d7f8882680a1 /]# cd /home
# 在容器内部创建一个文件
[root@d7f8882680a1 home]# touch test.java
[root@d7f8882680a1 home]# ls
test.java
# 退出容器
[root@d7f8882680a1 home]# exit
exit
# 将文件拷贝出来到主机上
[root@iZwz90og9utae1lg37hyz7Z /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
d7f8882680a1 centos "/bin/bash" 34 minutes ago Exited (127) About a minute ago
[root@iZwz90og9utae1lg37hyz7Z /]# docker cp d7f8882680a1:/home/test.java /home
[root@iZwz90og9utae1lg37hyz7Z /]# cd home
[root@iZwz90og9utae1lg37hyz7Z home]# ls
test.java www
#问题? 拷贝是手动过程,未来我们使用 -v卷的技术,可以实现自动同步
命令小结
docker的命令是十分多的,特此做个 笔记总结:
体验docker
1、使用Docker安装Nginx
# 1、搜索镜像 search 建议去docker hub搜索,可以看到帮助文档信息
# 2、下载镜像 pull
# 3、启动
[root@iZwz90og9utae1lg37hyz7Z ~]# docker run -d --name myNginx -p 3344:80 nginx
# 4、启动成功后,本地测试
[root@iZwz90og9utae1lg37hyz7Z ~]# curl localhost:3344
# http://112.74.167.52:3344/
# 注意:这里可能会有个小问题,如果这里没有正常放回界面,应该是阿里云的安全组那边没有开放端口,进入ECS控制台添加安全组开放端口即可
# 5、进入nginx容器
[root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myNginx /bin/bash
$测试:
[root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myNginx /bin/bash
# 进入容器了
root@b645aa7b2116:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@b645aa7b2116:/# cd /etc/nginx
root@b645aa7b2116:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
root@b645aa7b2116:/etc/nginx#
端口暴露的概念
思考的问题? 每次改动nginx配置文件,都需要进入容器内??十分麻烦,要是可以在容器外部提供一个映射路径,达到在容器外修改文件,容器内就能自动修改,那就OK, -v数据卷技术可以实现
2、使用docker安装一个tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到,docker -it --rm ,用完即删除,用来测试用
# 下载启动
[root@iZwz90og9utae1lg37hyz7Z ~]# docker pull tomcat 下载镜像
[root@iZwz90og9utae1lg37hyz7Z ~]# docker run -d -p 3355:8080 --name myTomcat tomcat # 运行
# localhost:3355 报404的错误,这个时候说明外网已经可以访问了
# 进入容器
[root@iZwz90og9utae1lg37hyz7Z ~]# docker exec -it myTomcat /bin/bash
root@d03c0c1b5ef3:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
# 发现问题,webapps目录下面为空,阉割版,所有访问的时候没有内容,阿里云镜像的原因,默认是最小的镜像。保证最小可运行的环境
复制webapps.dist中的内容到webapps目录下即可正常访问
思考:我们以后要部署项目,如果每次都要进入容器的话就很麻烦,要是可以在容器外部提供一个映射路径 ,webapps,在外部放置项目就自动同步到内部就好了!
3、部署ES+kibana
# es 暴露的端口很多
# es十分耗内存
# es的数据一般需要放置到安全目录!挂载
# --net somenetwork 这个是网络配置
# 启动es 下载安装一步到位
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动了 linux就卡住,内存爆炸了
# docker stats 查看cpu状态
# 增加内存限制 -e
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 查看内存消耗
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK
859d68a4564b elasticsearch 0.40% 338.9MiB / 1.795GiB 18.44% 0B / 0B 0B /
# 访问测试
[root@pihao ~]# curl localhost:9200
{
"name" : "859d68a4564b",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "67U8HpnDTPS9vqQJEaAkWg",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
使用kibana连接elasticsearch,网络怎么连接呢?
容器内部之间要怎么进行连接呢
可视化
- 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
访问测试:http://112.74.167.52:8088/
选择本地:
可视化面板,平时用的不多!
Docker镜像讲解
镜像是什么
所有的应用,直接打包docker镜像,就可以直接跑起来,包括代码、库、环境变量和皮遏制文件;
如何得到镜像:
-
从远程仓库下载
-
朋友拷贝
-
自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS (联合文件系统)
docker的镜像实际上由一层一层的文件系统组成,这种从层级的文件系统UnionFS
分层理解
所有的docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!
如何提交一个自己的镜像??
commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战观测:
官网提供的tomcat镜像的webapps目录是空的,那我们就做一个webapps目录下面有文件的,然后发布
# 启动一个默认的tomcat
# 发现这个默认的tomcat是没有webapps应用
# 我自己进去拷贝了基本的文件
# 将我们操作过的容器通过commit提交作为一个镜像,我们以后就使用这个修改过的镜像即可,这就我我们自己的一个修改过的镜像,结合maven的 mvn install理解
[root@pihao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
f44a55d3dd55 tomcat "catalina.sh run" 7 minutes ago Up 7 minutes 0.0.0.0:8080->8080/tcp
[root@pihao ~]# docker commit -a="pihao" -m="add webapps application" f44a55d3dd55 tomcat_pihao:1.0
通过实操至此,差不多算是入门docker了!!!! 继续加油~~~
容器数据卷
什么是容器数据卷
docker理念
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据也会丢失,需求:数据可以持久化
Mysql,容器删了,那就是删库跑路了,需求:Mysql数据可以存储在本地。
容器之间可以有一个数据共享的技术!docker容器中产生的数据,同步到本地
这就是数据卷技术,目录的挂载,将我们容器内的目录,挂载到Linux上面。
总结:容器的持久化和同步操作!容器间也是可以数据共享的
使用数据卷
方式一:直接使用命令来挂载 -v
[root@pihao ~]# docker run -it -v 主机目录:容器内目录 镜像id
# 测试:
[root@pihao home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来之后我们通过docker inspect 容器id 查看元数据
[root@pihao home]# docker inspect 6a08f0d81c50
"Mounts": [ 挂载 -v 卷
{
"Type": "bind",
"Source": "/home/ceshi", 主机内地址
"Destination": "/home", docker容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
#同步测试
继续测试:
- 停止容器
- 在宿主机上修改文件
- 启动容器
- 容器内的数据依旧是同步的
好处:我们以后修改只需要在本地修改即可,容器会自动同步过去!
实战:Mysql数据同步
思考:Mysql的数据持久化问题!
# 获取镜像
[root@pihao ~]# docker pull mysql:5.7
# 安装启动mysql,需要配置密码的,这是要注意点
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # 官方提供的设置密码命令
# 运行镜像,做数据挂载
[root@pihao ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat_pihao 1.0 8512e11068c0 12 hours ago 652MB
portainer/portainer latest 1ec116aed60c 46 hours ago 79.1MB
mysql 5.7 a4fdfd462add 9 days ago 448MB
tomcat 9.0 1b6b1fe7261e 2 weeks ago 647MB
tomcat latest 1b6b1fe7261e 2 weeks ago 647MB
nginx latest 9beeba249f3e 2 weeks ago 127MB
elasticsearch 7.6.2 f29a1ee41030 2 months ago 791MB
centos latest 470671670cac 4 months ago 237MB
# 可以做多个数据挂载 : /etc/mysql/conf.d(这个是mysql的配置文件目录) /var/lib/mysql(这个是mysql的数据库目录)
-d 后台运行
-d 端口映射
-v 卷挂载
-e 环境配置
--name 取别名
# 启动第一个mysql
[root@pihao ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功之后使用本地的连接工具Navicat测试连接mysql
# Navicat连接到服务器的3310,------3310和容器内的3306做了映射,这个时候就能连上了
# 在本地测试创建一个数据库,查看一下映射路径是否也创建了
假设将容器删除,发现我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据的持久化功能!
具名和匿名挂载
# 匿名挂载
-v 容器内路径 (不写主机的路径)
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume情况
[root@pihao data]# docker volume ls
DRIVER VOLUME NAME
local 0bd6ec25d165dfd5e55ec8d7376a619f720e71c94b062fef5bcd9d643890202f
local 5352b1b1d189180f75ae95a4aba702af3eab6dbf22c7196ee0b73491ca78ae39
# 这里发现,这就是匿名挂载,因为我们在-v的时候只写了容器内的路径,而没有取名字
# 具名挂载
# 再开一个nginx 这时给容器内的路径取一个名字:juming
[root@pihao /]# docker run -d -P -v juming:/etc/nginx --name nginx02 nginx
20bfd4124e5fadaf25a9dce86dfb8d216ade483db25e1d767b144f695b2c74ab
[root@pihao /]# docker volume ls
DRIVER VOLUME NAME
local juming # 取的名字
# 通过-v 卷名:容器内路径
# 查看卷的信息 docker volume inspect 卷名
[root@pihao /]# docker volume inspect juming
[
{
"CreatedAt": "2020-05-31T10:53:25+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming/_data",
"Name": "juming",
"Options": null,
"Scope": "local"
}
]
所有的docker容器内的卷,没有指定目录的情况下都是在: /var/lib/docker/volumes/xxxx/_data
我们通过具名挂载,可以方便的找到我们的一个卷,大多数情况下载使用的 具名挂载
# 如何确实是具名挂载还是匿名挂载??还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
# ro read only 只读
# rw read and write 可读可写
# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
[root@pihao /]# docker run -d -P -v juming:/etc/nginx:ro --name nginx01 nginx
[root@pihao /]# docker run -d -P -v juming:/etc/nginx:rw --name nginx02 nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的
初识DockerFile
DockerFile就是用来构建docker镜像的构建文件:命令脚本!先体验一下!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层!
# 创建一个dockerfile文件,名字可以随便取,建议dockerfile01
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"] # 这里其实是匿名挂载,在容器外部必定会生成一个目录与它同步
CMD echo "------end------"
CMD bin/bash
#这里每个命令都是镜像的一层
# 将命令打包
[root@pihao docker_volume_test]# docker build -f dockerfile01 -t pihao/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 470671670cac
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in ce323b96416b
Removing intermediate container ce323b96416b
---> d8f8fdc5edd8
Step 3/4 : CMD echo "------end------"
---> Running in cedae7372d3a
Removing intermediate container cedae7372d3a
---> 136048f7f683
Step 4/4 : CMD bin/bash
---> Running in d381121bac22
Removing intermediate container d381121bac22
---> 9f36ff977d42
Successfully built 9f36ff977d42
Successfully tagged pihao/centos:1.0
[root@pihao docker_volume_test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pihao/centos 1.0 9f36ff977d42 14 seconds ago 237MB # 打包好的镜像
# 启动一下自己生成的容器
[root@pihao docker_volume_test]# docker run -it 9f36ff977d42 /bin/bash
[root@0f1d1bf75b84 /]# ls -l
drwxr-xr-x 2 root root 4096 May 11 2019 srv
dr-xr-xr-x 13 root root 0 May 31 04:31 sys
drwxrwxrwt 7 root root 4096 Jan 13 21:49 tmp
drwxr-xr-x 12 root root 4096 Jan 13 21:49 usr
drwxr-xr-x 20 root root 4096 Jan 13 21:49 var
drwxr-xr-x 2 root root 4096 May 31 04:31 volume01 # 这两个目录就是我们生成镜像的时候自动挂载的,数据卷目录
drwxr-xr-x 2 root root 4096 May 31 04:31 volume02
这个卷:volume01,volume02 在外部一定有一个与它同步的目录!
# 使用inspect命令查看一下这个容器的卷挂载路径
[root@pihao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
48bbedc992a3 9f36ff977d42 "/bin/bash" 41 minutes ago Up 41 minutes
[root@pihao ~]# docker inspect 48bbedc992a3
"Mounts": [
{
"Type": "volume",
"Name": "56e6675052e05ea4a9b08eb72ca9bd776627c6e360a6b4ffbd205519cc82eff2",
"Source": "/var/lib/docker/volumes/56e6675052e05ea4a9b08eb72ca9bd776627c6e360a6b4ffbd205519cc82eff2/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "670c6b43a2af71397c18a85e92b393745eb9bf0b1318e5dd0529a6c39eacba83",
"Source": "/var/lib/docker/volumes/670c6b43a2af71397c18a85e92b393745eb9bf0b1318e5dd0529a6c39eacba83/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
# 发现 volume01 和volume02 挂载的同步文件在主机的 /var/lib/docker/volumes/xxxx/_date目录下
查看同步情况:
在容器内的volume01下创建一个container.txt文件
然后在volume01文件对应的主机同步目录中查看是否已经同步完成:
这种方式在以后的工作中经常使用,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载卷,就要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器
场景:多个mysql同步数据,容器与容器之间信息交互
# 启动3个容器,通过我们自己写的镜像启动
启动pihao/centos:1.0 ,取名为docker01
启动pihao/centos:1.0 ,取名为docker02 --volumes-from docker01
现在要做的操作:
在docker01的volume01中新建一个文件夹docker01,看看会不会同步的到docker02的volume01中
# 进入容器docker01 新建文件夹docker01
[root@pihao docker_volume_test]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 7 minutes ago Up 7 minutes docker02
9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 14 minutes ago Up 14 minutes docker01
[root@pihao docker_volume_test]# docker attach 9dda52409402
[root@9dda52409402 /]# ls
opt proc root run sbin srv sys tmp usr var volume01 volume02
[root@9dda52409402 /]# cd volume01
[root@9dda52409402 volume01]# mkdir docker01
[root@9dda52409402 volume01]# ls
docker01
# 进入容器docker02,查看文件是否被同步过来
[root@pihao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 12 minutes ago Up 12 minutes docker02
9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 19 minutes ago Up 19 minutes docker01
[root@pihao ~]# docker attach 4b8f6d78b9ea
[root@4b8f6d78b9ea /]# ls
opt proc root run sbin srv sys tmp usr var volume01 volume02
[root@4b8f6d78b9ea /]# cd volume01
[root@4b8f6d78b9ea volume01]# ls
docker01 # 发现已经被同步过来(docker01创建的数据同步到了docker02上)
启动pihao/centos:1.0 ,取名为docker03 -volumes–from docker01
# 进入docker01,检查文件是否同步过来
[root@pihao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5c69147c3e0 pihao/centos:1.0 "/bin/sh -c bin/bash" 3 minutes ago Up 3 minutes docker03
4b8f6d78b9ea pihao/centos:1.0 "/bin/sh -c bin/bash" 25 minutes ago Up 25 minutes docker02
9dda52409402 pihao/centos:1.0 "/bin/sh -c bin/bash" 32 minutes ago Up 32 minutes docker01
[root@pihao ~]# docker attach 9dda52409402
[root@9dda52409402 volume01]# ls
docker01 docker03 # 发现docker03已经同步过来了
# 测试 可以删除docker01,查看一下docker02和docker03是否还可以访问volume01这个文件夹
# 发现依旧存在
多个mysql实现数据共享
# mysql01
[root@pihao ~]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# mysql02
[root@pihao ~]# docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候,就可以实现两个容器数据同步
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
但是一旦持久化到了本地,本地的数据是不会删除的
DockerFile
DockerFile介绍
dockerfile 是用来构建docker镜像的文件,!命令参数脚本
构建步骤
- 编写一个dockerfile文件
- docker build 构建一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub\阿里云镜像仓库)
看看官方是怎么做的??DockerHub上随便搜一个镜像
发现跳转到github,发现也是一组命令构成
官方既然可以制作镜像,我们也可以!!!
DockerFile构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每个指令都是创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单
简单地说,之前将你写的代码打包生成war包或者jar包,现在呢?公司要求将你的代码打包生成docker镜像
Docker镜像逐渐成为企业交付的标准,必须要掌握~~~~
步骤:开发,部署,。。。缺一不可
-
DokcerFile: 构建文件,定义了一切的步骤,源代码
-
DockerImages: 通过DockerFile构建生成的镜像,最终发布和运行的产品,原来是jar,war
-
Docker容器: 容器就是镜像运行起来提供服务的
DockerFile的指令
以前的话我们就是使用别人的,现在我们知道这些指令后,我们来练习自己写一个镜像!
FROM # 基础镜像,就是一切从这里构建 centos
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包就是添加的内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录位置
EXPOSE # 暴露端口配置 -p
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFil,这个时候就会触发onbuild的指令
COPY # 类似ADD命令,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量! 比如说设置内存大小,mysql的密码
实战测试:构建自己的centos
Docker Hub中,百分之九九的镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建
创建一个自己的centos
# 1、编写dockerfile的配置文件(我在home目录下编写一个了mydockerfile-centos的文件,内容如下)
FROM centos
MAINTAINER pihao<827699764@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----------------end------------"
CMD /bin/bash
# 2、再通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名字:【TAG】
[root@pihao dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 .
# 执行结果:
Successfully built 844b891d4781
Successfully tagged mycentos:1.0
# 3、测试运行
对比:之前的centos
我们增加之后的镜像
查看镜像历史变更:
# 我们可以列出本地进行的变更历史 docker history 镜像id
[root@pihao dockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 1.0 844b891d4781 15 minutes ago 321MB
centos latest 470671670cac 4 months ago 237MB
[root@pihao dockerfile]# docker history mycentos:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
844b891d4781 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
cc7835c68b84 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
617d78fe4151 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
fbfd40657f5c 15 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
6ce2a8dca855 15 minutes ago /bin/sh -c yum -y install net-tools 24MB
3639c1768f75 15 minutes ago /bin/sh -c yum -y install vim 59.8MB
301d6576cf44 15 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
f7cd9d68bb8d 15 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
3c2904681fb0 15 minutes ago /bin/sh -c #(nop) MAINTAINER pihao<82769976… 0B
470671670cac 4 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 4 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 4 months ago /bin/sh -c #(nop) ADD file:aa54047c80ba30064… 237MB
我们平时拿到一个镜像,可以研究一下它是怎么做的??
CMD 和 ENTRYPOINT的区别
测试CMD
# dockerfile
FROM centos
CMD ["ls","-a"]
# 这个命令非常简单,及时启动这个容器的时候执行 ls -a 这个命令
# 构建容器
[root@pihao dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 .
# 运行容器,发现 li -a 生效
[root@pihao dockerfile]# docker run cmdtest:1.0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
[root@pihao dockerfile]#
# 想追加一个命令 -l 期待效果如: ls -al
[root@pihao dockerfile]# docker run cmdtest:1.0 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
# 发现有问题,因为在cmd的清理下, -l替换了CMD["ls","-a"]的命令,-l不是命令,所以报错
# 命令换成 ls -al即可
[root@pihao dockerfile]# docker run cmdtest:1.0 ls -al
total 56
drwxr-xr-x 1 root root 4096 May 31 11:29 .
drwxr-xr-x 1 root root 4096 May 31 11:29 ..
-rwxr-xr-x 1 root root 0 May 31 11:29 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 31 11:29 dev
drwxr-xr-x 1 root root 4096 May 31 11:29 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
测试ENTRYPOINT
# dockerfile
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建容器
[root@pihao dockerfile]# docker build -f dockerfile-entrypoint-test -t entrypoint-test:1.0 .
# 运行容器,发现 li -a 生效
[root@pihao dockerfile]# docker run entrypoint-test:1.0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
# 想追加一个命令 -l 期待效果如: ls -al
[root@pihao dockerfile]# docker run entrypoint-test:1.0 -l
total 56
drwxr-xr-x 1 root root 4096 May 31 11:42 .
drwxr-xr-x 1 root root 4096 May 31 11:42 ..
-rwxr-xr-x 1 root root 0 May 31 11:42 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 31 11:42 dev
drwxr-xr-x 1 root root 4096 May 31 11:42 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
# 运行成功
# 发现这里的 -l 直接追加到了ENTRYPOINT ["ls","-a"]中
DockerFile中很多命令都十分相似,需要了解他们的区别,最好就是通过对比的方式来学习
实战:Tomcat镜像
1、准备镜像文件tomcat压缩包,jdk的压缩包
[root@pihao tomcat]# ls -l
-rw-r--r-- 1 root root 9722154 May 31 20:00 apache-tomcat-8.5.45.tar.gz
-rw-r--r-- 1 root root 180362463 May 31 19:56 jdk-11.0.4_linux-x64_bin.tar.gz
-rw-r--r-- 1 root root 0 May 31 20:17 readme.txt # readme.txt 空文件
2、编写dockerfile文件,官方命名 Dockerfile ,build会自动寻找这个文件,就不需要 -f 指定了
FROM centos
MAINTAINER pihao<827699764@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-11.0.4_linux-x64_bin.tar.gz /usr/local/
ADD apache-tomcat-8.5.45.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local/
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk-11.0.4
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.45
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.45
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 这里注意,linux的path环境变量是【冒号:】分隔的
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.5.45/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.45/logs/catalina.out
3、构建镜像
[root@pihao tomcat]# docker build -t diytomcat . # 注意:这里的-f不用写,因为先前的dockerfile的名字就是Dockerfile
.
.
.
Successfully built 31d4a6fa8956
Successfully tagged diytomcat:latest
# 构建成功
4、启动这个容器
[root@pihao tomcat]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest 31d4a6fa8956 6 minutes ago 614MB
# 说明 -v 这里挂载了webapps目录 和 logs目录
[root@pihao tomcat]# docker run -d -p 9090:8080 --name pihao-diy-tomcat -v /home/tomcat/test:/usr/local/apache-tomcat-8.5.45/webapps/test -v /home/tomcat/logs:/usr/local/apache-tomcat-8.5.45/logs diytomcat
5、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地发布项目)
# 切换到主机的/tomcat/test目录,创建WEB-INF目录
[root@pihao test]# mkdir WEB-INF
[root@pihao test]# ls
WEB-INF
[root@pihao WEB-INF]# ls
index.jsp web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
Hello World!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>
访问地址:主机ip:9090/test,项目部署成功,可以直接访问ok
我们以后开发的步骤,需要掌握Dockerfile的编写,我们之后的一切都是使用docker镜像来发布运行!
发布自己的镜像到DockerHub
DockerHUb
- 地址:https://hub.docker.com/ 注册自己的账号
- 确定这个账号可以登入
- 在服务器上提交自己的镜像
[root@pihao ~]# 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
- 登入完毕后就可以提交镜像了,就是一步 docker push
[root@pihao ~]# docker login -u pihao
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@pihao ~]#
[root@pihao ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
truevoly/oracle-12c latest 21789d4d876f 16 months ago 5.7GB
jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB
[root@pihao ~]# docker push jaspeen/oracle-11g
The push refers to repository [docker.io/jaspeen/oracle-11g]
5f70bf18a086: Preparing
7a080c2f6e4d: Layer already exists
59af826791e8: Layer already exists
69264aa86d7e: Layer already exists
denied: requested access to the resource is denied # 发现给拒绝了,因为这里是根据名字上传到仓库,而这里的是jaspeen账号,那肯定没有权限
[root@pihao ~]# 所以要把这个名字改成自己账号的名字,可以使用docker tag 命令
docker tag 修改镜像名字
发布自己的镜像到阿里云服务器上
-
1、登入阿里云
-
2、找到容器镜像服务
-
3、创建命名空间
- 4、创建容器镜像
- 5、浏览阿里云页面信息
-
6、push到阿里云仓库
# 退出之前的账号 [root@pihao ~]# docker logout Removing login credentials for https://index.docker.io/v1/ # 登入阿里云的账号 [root@pihao ~]# docker login --username=决魂耗子 registry.cn-shenzhen.aliyuncs.com # 密码是开通阿里云镜像服务时的那个密码 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@pihao ~]#
[root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE truevoly/oracle-12c latest 21789d4d876f 16 months ago 5.7GB jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB pihao/oracle-11g latest 0c8711fe4f0f 4 years ago 281MB # 按照阿里云页面提示修改镜像的 tag [root@pihao ~]# docker tag jaspeen/oracle-11g registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test:1.0 [root@pihao ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE truevoly/oracle-12c latest 21789d4d876f 16 months ago jaspeen/oracle-11g latest 0c8711fe4f0f 4 years ago pihao/oracle-11g latest 0c8711fe4f0f 4 years ago registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test 1.0 0c8711fe4f0f 4 years ago # 提交,ok [root@pihao ~]# docker push registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test The push refers to repository [registry.cn-shenzhen.aliyuncs.com/docker-pihao-01/pihao-test] 5f70bf18a086: Pushed 7a080c2f6e4d: Pushing [==> ] 4.903MB/108.7MB 59af826791e8: Pushed 69264aa86d7e: Pushing [=> ] 5.404MB/172.3MB
阿里云镜像的就参考官网文档即可
小结
Docker网络
理解Docker0
请求所有环境做测试
三个网络
# 问题:docker 是如何处理容器网络访问的,比如容器内的tomcat怎么连接mysql呢??
[root@pihao ~]# docker run -d tomcat -P --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr 发现容器启动的时候会得到一个 eth0@if79 的ip地址,这时docker分配的
[root@pihao ~]# 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
78: eth0@if79: <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@pihao ~]#
# 思考,linux能不能ping同容器内部!
[root@pihao ~]# 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.094 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.081 ms
# linux可以ping通docker容器内部
原理
1、我们每启动一个docker容器,docker就会给容器分配一个ip,我们只要安装了Docker,就会有一个网卡docker0
桥接模式,我们使用的技术是veth-pair技术
再次测试 ip addr,(启动了一个tomcat01容器之后),发现多了一个网络 79: vetha37f3dc@if78(跟容器内的那个地址类似)
2、再启动一个容器测试,发现又多了一对网卡!
# 而且还发现这些容器带来的网卡都是一对一对的
# veth-pair技术就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为有这个特性,veth-pair 充当一个侨联,连接各种虚拟网络设备
3、我们现在在Docker中启动了tomcat01,tomcat02两个容器,而这两个容器之间是互相独立的,那么他们之间能够ping通嘛?
# tomcat02 的ip是 172.17.0.2
[root@pihao ~]# docker exec -it tomcat02 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.139 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.096 ms
# 结论: 容器和容器之间是可以Ping 通的,因为都是在同一个网段下 docker0 172.17.0.1
绘制一个网络连接模型图:
结论:tomcat01 和tomcat02是共用的一个路由器,docker01
所有的容器不指定网络的情况下,都是由Docker0来路由的,docker会给每个容器分配一个可用 IP
255.255.0.1/16 可以存25535个地址
255.255.0.1/24 可以存255个地址
小结
Docker使用的是Linxux桥接,宿主机中是一个Docker容器的网桥 docker0
Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高。(内网传递文件,速度非常快 10m 10 m的)
只要容器删除,对应的网桥一对也就删除了!
思考一个场景,我们编写了一个微服务,database url = ip:xxxxxx,而我们每次启动容器的时候ip会变化,能不能通过某种技术,我们直接来ping 通容器的名字,作用效果就像SpringCloud中的feign,通过微服务的名字就能实现远程调用。高可用
–link
不用通过网络,直接通过容器的名字来访问
[root@pihao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4c7d8ebced2 tomcat "catalina.sh run" 45 minutes ago Up 45 minutes 0.0.0.0:32769->8080/tcp tomcat02
081e1f8db911 tomcat "catalina.sh run" 59 minutes ago Up 59 minutes 0.0.0.0:32768->8080/tcp tomcat01
# 想直接通过容器名字来访问,发现行不通
[root@pihao ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何解决呢??
# 在启动一个tomcat03 启动是使用 --link 命令指定要连接的容器tomcat02
[root@pihao ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
9ec98d9557a1f2424212eda8e036883006cc970ab09daa84391c05e3ec70f2d3
# 通过--link,就可以直接使用容器名字访问
[root@pihao ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.135 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.103 ms
# 缺陷,反向可以ping通嘛??
[root@pihao ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@pihao ~]# 发现反向连接就不行
探究 :inspect
[root@pihao ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e12a90f69e50 bridge bridge local
7514a428f3d0 host host local
f1f4981f4fbb none null local
[root@pihao ~]# docker network inspect e12a90f69e50
[
{
"Name": "bridge",
"Id": "e12a90f69e507dae3504769ee12399ec18e427de2d29b675cbf593e4b01f371c",
"Created": "2020-06-01T09:17:54.742162379+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{ # docker0的信息
"Subnet": "172.17.0.0/16", # 255*255
"Gateway": "172.17.0.1" # 路由
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": { # 容器内的信息
"081e1f8db911bcca7288c0ed3eee687c36a290c0f9b9f5e523a8099389342c91": {
"Name": "tomcat01",
"EndpointID": "c9b47b00655cb11db1735d74ce346ada99b79ad9f399c7686ca944f145a018d1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"9ec98d9557a1f2424212eda8e036883006cc970ab09daa84391c05e3ec70f2d3": {
"Name": "tomcat03",
"EndpointID": "e1bf65587d0ae28997b46dc2ffe49fc9ea89f27ac072e34b62573440da6ca66f",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"d4c7d8ebced2387ece1ea16052d3d38c085434552ab9141c171531402295c69c": {
"Name": "tomcat02",
"EndpointID": "5bd840c78f1a6da803ef55c2086f3961db45a897309e30aff1be1d77d01dcd0e",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/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": {}
}
]
[root@pihao ~]#
docker inpect tomcat03(使用了--kink连接 tomcat02 ),查看如下图,有一个Links
还有一种方式查看它的连接配置,就是进入容器内容,查看它的映射路径,看看是不是用容器的名字来映射对应的地址 比如:tomcat02: 172.17.0.3
[root@pihao ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
172.17.0.3 tomcat02 d4c7d8ebced2 # 找到了,在这里,不知可以使用容器的名字,还能使用容器id来访问
172.17.0.4 9ec98d9557a1
[root@pihao ~]#
再来查看一下tomcat02的配置
[root@pihao ~]# docker exec -it tomcat02 cat /etc/hosts
127.0.0.1 localhost
172.17.0.3 d4c7d8ebced2
[root@pihao ~]# 发现这里并没有配置tomcat03的路径,那就不能通过tomcat03来访问了,那就再次使用 -- link了
本质探究: --link就是我们在hosts配置中增加了一个172.17.0.3 tomcat02 d4c7d8ebced2
其实我们在使用Docker 已经不建议使用 --link了!!
我们要自定义网络,不使用默认的Docker0网络
Docker0的问题:他不支持容器名连接访问
自定义网络
# 查看所有的docker 网络
[root@pihao ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e12a90f69e50 bridge bridge local
7514a428f3d0 host host local
f1f4981f4fbb none null local
[root@pihao ~]#
网络模式
-
bridge 桥接:在docker上搭桥(默认,自己创建也是用bridge模式)
-
none : 不配置网络
-
host : 主机,和宿主机共享网络
-
container : 容器内网络连通(用的少,局限性很大)
测试
# 我们之前直接启动的命令,--net bridge,默认会有这个参数,这个就是我们的docker0
[root@pihao ~]# docker run -d -P --name tomcat01 tomcat
[root@pihao ~]# docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点,默认使用的,域名不能访问, --link可以打通连接
# 我们可以自定义一个网络
[root@pihao ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
-d, --driver string Driver to manage the Network (default "bridge") # 桥接
--gateway strings IPv4 or IPv6 Gateway for the master subnet # 指定网关
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment # 设置子网(必须要配置)
[root@pihao ~]#
创建一个自己的网络
# --driver bridge
# --subnet 192.168.0.0/16 支持范围: 192.168.0.2~192.168.255.255
# --gateway 192.168.0.1
[root@pihao ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
8f69e37f277cb7c27c28852076b9d5beafa73c597c2464bbf6d1418710c3e6be
[root@pihao ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e12a90f69e50 bridge bridge local
7514a428f3d0 host host local
8f69e37f277c mynet bridge local # 我们自定义的网络
f1f4981f4fbb none null local
[root@pihao ~]#
查看自己的网络
再次启动tomcat测试,启动的时候指定我们自己定义的网络 mynet
[root@pihao ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
b5db4c5c94d049c6caaef2b2ae39c34e9470ac0c4dd44a59bea77b57cce98649
[root@pihao ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
28129f9f6304265405274bfbfe3b348a7f70ece8f3772fafed7d955c17ff78ef
启动完毕后再来检查我们的 mynet 网络
最后自定义网络能不能通过容器名来访问,不使用 --link
[root@pihao ~]# 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.128 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.105 ms
# 发现可以,没问题
结论:我们自定义网络Docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
好处:保证不同的集群使用不同的网络,保证集群是安全和健康的。因为都在不同的网段!!
网络连通
现有的容器及所在网络:
使用docker0网络下的tomcat01来 Ping 一下mynet 网络下的tomcat-net-01
[root@pihao ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
[root@pihao ~]# 发现不行,肯定不行呀,因为这都属于不同的网段下了
# 思考:那如果我想要他能ping通,该怎么操作呢??
图示:
注意:这里说的 要打通 还不是两个网络直接打通(Docker0打通mynet),而是 容器与网卡打通(tomcat-01 与mynet打通)!!!
如何打通??
# 测试打通 tomcat01 - mynet
[root@pihao ~]# docker network connect mynet tomcat01
# 打通之后查看一下网络
[root@pihao ~]# docker network inspect mynet
# 发现连通之后就是将 tomcat01 放到了mynet 网络下
# 这就是所谓的一个容器两个 IP
再来使用 tomcat01 ping 一下 tomcat-net-01
[root@pihao ~]# docker exec -it tomcat01 ping tomcat-net-01
# 发现现在通了(不同的网卡的容器)
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.100 ms
# 而tomcat02是Ping不通的,因为tomcat02没有和 mynet 打通
[root@pihao ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
[root@pihao ~]#
结论:假设要跨网络去操作别人,就需要使用 docker network connect 网络名 容器名 来打通!!!
实战:部署Redis集群
集群模式:分片+高可用+负载均衡
# 创建redis集群的网卡
[root@pihao ~]# 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
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >>/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# shell配置文件的脚本ok
# 启动 第一个 redis
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 启动 第二个 redis
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 启动 第三个 redis
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 启动 第四个 redis
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 启动 第五个 redis
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 启动 第六个 redis
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 六个redis启动后:
[root@pihao conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8be3b0272fa5 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp redis-6
7daf1edb4fa3 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 30 seconds ago Up 29 seconds 0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp redis-5
277223569dd6 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp redis-4
e5455ca3d11b redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp redis-3
af4a01eb4e49 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp redis-2
2250d384e975 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-1
[root@pihao conf]#
# 进入启动一个 redis-1的容器
[root@pihao conf]# docker exec -it redis-1 /bin/sh (注意:这里发现redis没有 /bin/bash命令 只有 /bin/sh 命令)
# 默认进来的是 /data 目录
/data # ls 查看到有两个文件
appendonly.aof nodes.conf
# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
# 三台主机master
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
# 三台从机slave
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 # 15是11的从机
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 # 16是12的从机
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 # 14是13的从机
M: fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379
replicates 73bc0387c4e7006621cf71201b799a8611c51716
S: 8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379
replicates fe1da2ced57ea42176134194c8f919478e938ec7
S: 090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379
replicates 2dd905acf6fd1a633c3c2d246fbc78ab166148a8
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379
slots: (0 slots) slave
replicates fe1da2ced57ea42176134194c8f919478e938ec7
M: 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379
slots: (0 slots) slave
replicates 73bc0387c4e7006621cf71201b799a8611c51716
S: 090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379
slots: (0 slots) slave
replicates 2dd905acf6fd1a633c3c2d246fbc78ab166148a8
M: 73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered. # 创建成功啦
# 连接集群 -c 表示的是连接集群 不加的话表示单机
/data # redis-cli -c
127.0.0.1:6379>
查看集群信息
开始测试
# set k1 v1
# docker stop
# get k1 看看能不能拿到值,发现拿到值了,并且发现是通过14这太从机获取到的,说明高可用生效了
docker 搭建redis完成
## 再次查看集群信息,发现172.38.0.13:6379@16379 master,fail,并且172.38.0.14:6379@16379 myself,maste(13挂了,14成了主机)
172.38.0.14:6379> cluster nodes
8a5ef9825fb194d43b02dcc731de3d2a7c28ca79 172.38.0.15:6379@16379 slave fe1da2ced57ea42176134194c8f919478e938ec7 0 1591447999393 5 connected
090fda90e4dcd7ca8466987c7150e3302a9c8662 172.38.0.16:6379@16379 slave 2dd905acf6fd1a633c3c2d246fbc78ab166148a8 0 1591448000397 6 connected
35f7de80fc3debca9e8fc6c84c6dfd88291f9695 172.38.0.14:6379@16379 myself,master - 0 1591448000000 7 connected 10923-16383
fe1da2ced57ea42176134194c8f919478e938ec7 172.38.0.11:6379@16379 master - 0 1591447999000 1 connected 0-5460
73bc0387c4e7006621cf71201b799a8611c51716 172.38.0.13:6379@16379 master,fail - 1591447080985 1591447080000 3 connected
2dd905acf6fd1a633c3c2d246fbc78ab166148a8 172.38.0.12:6379@16379 master - 0 1591447999000 2 connected 5461-10922
172.38.0.14:6379>
我们使用了docker之后,所有的技术都会慢慢变得简单起来!
SpringBoot微服务打包Docker镜像
1、构建SpringBoot项目
2、打包应用
3、编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
4、构建镜像
5、发布运行
[root@pihao eclipse]# ls
Dockerfile docker-test-0.0.1-SNAPSHOT.jar # 只要这两个文件
[root@pihao eclipse]# docker build -t pihao-docker-test .
Sending build context to Docker daemon 16.47MB
Step 1/5 : FROM java:8
8: Pulling from library/java
5040bd298390: Pull complete
fce5728aad85: Pull complete
76610ec20bf5: Pull complete
60170fec2151: Pull complete
e98f73de8f0d: Pull complete
11f7af24ed9c: Pull complete
49e2d6393f32: Pull complete
bb9cdec9c7f3: Pull complete
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:8
---> d23bdf5b1b1b
Step 2/5 : COPY *.jar /app.jar
---> cd9911f3fe9c
Step 3/5 : CMD ["--server.port=8080"]
---> Running in 5926ef3df86e
Removing intermediate container 5926ef3df86e
---> 12bf641f1df0
Step 4/5 : EXPOSE 8080
---> Running in 1e5a2f7bf6c6
Removing intermediate container 1e5a2f7bf6c6
---> 658947a6d2b7
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Running in 4296335cbd4c
Removing intermediate container 4296335cbd4c
---> d6df5ff457b9
Successfully built d6df5ff457b9
Successfully tagged pihao-docker-test:latest
# 查看构建的镜像
[root@pihao eclipse]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pihao-docker-test latest d6df5ff457b9 12 seconds ago 660MB
tomcat latest 1b6b1fe7261e 3 weeks ago 647MB
redis 5.0.9-alpine3.11 3661c84ee9d0 6 weeks ago 29.8MB
java 8 d23bdf5b1b1b 3 years ago 643MB
# 运行容器
[root@pihao eclipse]# docker run -d -P --name springbootweb-docker pihao-docker-test
39d59e8a9bc26264b418c387f147caac40884eaaf31544c50b29a37dfc8d41
# 查看随机随机生成的端口
[root@pihao eclipse]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39d59e8a9bc2 pihao-docker-test "java -jar /app.jar …" 41 seconds ago Up 40 seconds 0.0.0.0:32777->8080/tcp springbootweb-docker
# 访问测试
[root@pihao eclipse]# curl localhost:32777/hello
hello
[root@pihao eclipse]#
# 完美运行
思考:如果有很多镜像呢??100个镜像,要怎么管理??
Docker Compose
Docker Swarm
CI/CD之Jenkins
只要学不死,就往死里学!!!