Docker笔记
1.Docker 入门
1.1.Docker概述
Docker为什么出现?
-
一款产品: 开发–上线 两套环境 应用环境 应用配置!
-
开发 — 运维 问题:我在我的电脑上可以运行
-
版本更新 导致服务不可用 对于运维来说考验十分大
-
环境配置是十分的麻烦 每一个及其都要部署环境(集群Redis、ES、Hadoop…) 费事费力
-
发布一个项目( jar + (Redis MySQL JDK ES) ) 项目能不能带上环境安装打包
-
服务器配置一个应用的环境 Redis MySQL JDK ES Hadoop 配置超麻烦了 不能够跨平台
-
开发环境Windows 最后发布到Linux
-
传统:开发jar 运维来做
-
现在:开发打包部署上线 一套流程做完
-
安卓流程:java — apk —发布(应用商店)一 张三使用apk一安装即可用!
-
docker流程: java-jar(环境) — 打包项目帯上环境(镜像) — ( Docker仓库:商店)
-
Docker给以上的问题,提出了解决方案
Docker的思想就来自于集装箱
-
JRE – 多个应用(端口冲突) – 原来都是交叉的隔离
-
Docker核心思想 打包装箱 每个箱子是互相隔离的
-
Docker通过隔离机制 可以将服务器利用到极致
-
本质:所有的技术都是因为出现了一些问题 我们需要去解决 才去学习
1.2.Docker历史
-
2010年 几个的年轻人 就在美国成立了一家公司 dotcloud
-
做一些pass的云计算服务!LXC(Linux Container容器)有关的容器技术
-
Linux Container容器是一种内核虚拟化技术 可以提供轻量级的虚拟化 以便隔离进程和资源
-
他们将自己的技术(容器化技术)命名就是 Docker
-
Docker刚刚延生的时候 没有引起行业的注意 dotCloud 就活不下去 所以就开源
开源
- 2013年 Docker开源
- 越来越多的人发现docker的优点 火了
- Docker每个月都会更新一个版本
- 2014年4月9日,Docker1.0发布
docker为什么这么火
-
十分的轻巧
-
在容器技术出来之前 我们都是使用虚拟机技术
-
虚拟机:在window中装一个VMware 通过这个软件我们可以虚拟出来一台或者多台电脑 笨重
-
虚拟机也属于虚拟化技术 Docker容器技术 也是一种虚拟化技术
VMware : linux centos 原生镜像(一个电脑!) 隔离、需要开启多个虚拟机! 几个G 几分钟
docker: 隔离,镜像(最核心的环境 4m + jdk + mysql)十分的小巧,运行镜像就可以了!小巧! 几个M 秒级启动!
聊聊Docker
Docker基于Go语言开发的!开源项目!
docker官网:https://www.docker.com/
文档:https://docs.docker.com/ Docker的文档是超级详细的
1.3.Docker能干嘛
之前的虚拟机技术
虚拟机技术缺点:
-
资源占用十分多
-
冗余步骤多
-
3启动很慢
容器化技术
容器化技术不是模拟一个完整的操作系统
比较Docker和虚拟机技术的不同:
- 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
应用更快速的交付和部署
-
传统:一对帮助文档 安装程序。
-
Docker:打包镜像发布测试一键运行
更便捷的升级和扩缩容
-
使用了 Docker之后 我们部署应用就和搭积木一样
-
项目打包为一个镜像 扩展服务器A 服务器B更简单的系统运维
-
在容器化之后,我们的开发 测试环境都是高度一致的
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
2.Docker安装
2.1.Docker的基本组成
镜像(image):
- docker镜像就好比是一个目标,可以通过这个目标来创建容器服务,tomcat镜像>run>容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
容器(container):
-
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的
-
启动,停止,删除,基本命令
-
目前就可以把这个容器理解为就是一个简易的 Linux系统
仓库(repository):
-
仓库就是存放镜像的地方
-
仓库分为公有仓库和私有仓库 (很类似git)
-
Docker Hub是国外的
-
阿里云…都有容器服务器(配置镜像加速!)
2.2.安装Docker
环境准备
1.Linux要求内核3.0以上
2.CentOS 7
# 系统内核
[root@localhost /]# uname -r
3.10.0-1160.76.1.el7.x86_64 # 要求3.0以上
# 系统版本
[root@localhost /]# 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"
安装Docker
帮助文档:https://docs.docker.com/engine/install/
卸载与安装
#1.卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#2.需要的安装包
yum install -y yum-utils
#3.设置镜像的仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
#上述方法默认是从国外的,不推荐
#推荐使用国内的
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新yum软件包索引
yum makecache fast
#4.安装docker相关的 docker-ce 社区版 docker-ee 企业版
yum install docker-ce docker-ce-cli containerd.io # 这里我们使用社区版即可
#5.启动docker
systemctl start docker
#6. 使用docker version查看是否按照成功
docker version
#7. 测试
docker run hello-world
#8.查看已经下载的镜像(从这里可以查看已有镜像的id)
[root@localhost /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
卸载docker
#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源
rm -rf /var/lib/docker
# /var/lib/docker 是docker的默认工作路径!
2.3.阿里云镜像加速
1.1.登录阿里云找到容器服务
1.2.找到镜像加速器
1.3.配置使用
#1.创建一个目录
sudo mkdir -p /etc/docker
#2.编写配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://oltiqh2r.mirror.aliyuncs.com"]
}
EOF
#3.重启服务
sudo systemctl daemon-reload
sudo systemctl restart docker
2.4.回顾HelloWorld流程
docker run 流程图
底层原理
Docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
Docker-Server接收到Docker-Client的指令,就会执行这个命令!
为什么Docker比Vm快
1.docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
2.docker利用的是宿主机的内核,而不需要Guest OS。
GuestOS: VM(虚拟机)里的的系统(OS)
HostOS:物理机里的系统(OS)
因此,当新建一个 容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引导、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个复杂的过程,因此新建一个docker容器只需要几秒钟。
3.Docker的常用命令
3.1.帮助命令
docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/build/
3.2.镜像命令
docker images #查看所有本地主机上的镜像 可以使用docker image ls代替
docker search #搜索镜像
docker pull #下载镜像 docker image pull
docker rmi #删除镜像 docker image rm
docker images查看所有本地的主机上的镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
# 解释
#REPOSITORY # 镜像的仓库源
#TAG # 镜像的标签(版本) ---lastest 表示最新版本
#IMAGE ID # 镜像的id
#CREATED # 镜像的创建时间
#SIZE # 镜像的大小
# 可选项
Options:
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的id
# 列出所有镜像详细信息
[root@localhost ~]# docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
# docker images -aq #列出所有镜像的id
[root@localhost ~]# docker images -q
feb5d9fea6a5
docker search 搜索镜像
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13123 [OK]
mariadb MariaDB Server is a high performing open sou… 5017 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 621 [OK]
percona Percona Server is a fork of the MySQL relati… 584 [OK]
# 可选项 docker search --help
[root@localhost ~]# docker search --help
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 output
# 过滤 搜索出来的镜像收藏STARS数量大于9000的 docker search mysql --filter=STARS=9000
[root@localhost ~]# docker search mysql --filter=STARS=9000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13123 [OK]
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag(版本)]
[root@localhost ~]# docker pull mysql
Using default tag: latest # 如果不写tag(版本) 默认就是latest(最新的)
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载:docker image 的核心 联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
#等价于
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
[root@localhost ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists # 以前下载过了 可以共用的
93619dbc5b36: Already exists
99da31dd6142: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
# docker rmi 批量删除镜像 根据id指定删除镜像
[root@localhost ~]# docker rmi -f c20987f18b13 镜像id 删除指定的镜像
docker rmi -f $(docker images -aq) # $(docker images -aq) 查出所有的镜像id 然后根据镜像id批量删除
[root@localhost~]# docker stop $(docker ps -a -q)
3.3.容器命令
说明:我们有了镜像才可以创建容器 Linux 下载centos镜像来学习
镜像下载
# docker中下载centos
docker pull centos
docker run 镜像id # 新建容器并启动
docker ps 列出所有运行的容器 docker container list
docker rm 容器id # 删除指定容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
[root@localhost~]# docker container list #h和docker ps相同
新建容器并启动
docker run [可选参数] image | docker container run [可选参数] image
#参书说明
--name ="Name" # 给容器赋值名字 用来区分
-d # 后台方式运行 跟nohup相似
-i # 使用交互方式运行
-t # 进入容器查看内容
-p # 指定容器的端口 -p 8080(宿主机):8080(容器)
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P(大写) 随机指定端口
# 测试、启动并进入容器 主机名称有区别就可以看出进没进容器 主机名字就是镜像Id
[root@localhost /]# docker run -it centos /bin/bash # 后面的/bin/bash的作用是表示载入容器后运行bash
# docker中必须要保持一个进程的运行
# 要不然整个容器启动后就会马上kill itself
# 这样当你使用docker ps 查看启动的容器时
# 就会发现你刚刚创建的那个容器并不在已启动的容器队列中
# 这个/bin/bash就表示启动容器后启动bash
[root@e3e1a08cff7a /]# ls 查看容器内的Centos 基础版本 很多命令都是不完善的
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@e3e1a08cff7a /]# exit #从容器退回主机
exit
列出所有运行的容器
docker ps 命令 # 列出当前正在运行的容器
-a, --all # 列出当前正在运行的容器 + 带出历史运行过的容器
-n=?, --last int # 列出最近创建的?个容器 ?为1则只列出最近创建的一个容器,为2则列出2个
-q, --quiet # 只列出容器的编号
退出容器
exit # 容器直接退出
ctrl +P +Q # 容器不停止退出 ---注意:这个很有用的操作
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -rf
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q|xargs docker rm # 删除所有的容器
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
3.4.常用其他命令
后台启动命令
# 命令 docker run -d 镜像名
[root@localhost~]# docker run -d centos
a8f922c255859622ac45ce3a535b7a0e8253329be4756ed6e32265d2dd2fac6c
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 问题docker ps. 发现centos 停止了
# 常见的坑,docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
# 查看关于日志的信息以及怎么使用
docker logs --help
# 自己编写一个小脚本让他有日志信息否则运行时没有日志信息
docker run -d centos /bin/sh -c "while true;do echo 6666;sleep 1;done" #模拟日志
# 显示日志
-tf --tail number # 显示日志信息 -t是显示时间 -f持续更新显示 --tail number 显示number条日志
# 查看n行日志
docker logs -t --tail n 容器id
# 显示全部日志信息 并且持续更新
docker logs -tf 容器id
查看容器中进程信息ps
# 命令 docker top 容器id 查看容器中的进程
docker top 2e01b3333cbc
查看镜像的元数据(容器的内部信息)
# 命令
docker inspect 容器id
#测试
docker inspect 55321bcae33d
[root@localhost ~]# docker inspect c109c4603669
[
{
"Id": "c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db", # 容器id
"Created": "2022-09-05T14:20:09.367362185Z",
"Path": "/bin/sh", # 开启一个shell终端
"Args": [
"-c", # 容器执行脚本
"while true;do echo 6666;sleep 1;done"
],
"State": {
"Status": "running", # 容器的状态
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 76269,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-09-05T14:20:09.607130704Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db/hostname",
"HostsPath": "/var/lib/docker/containers/c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db/hosts",
"LogPath": "/var/lib/docker/containers/c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db/c109c4603669d78a269a0fea6f0e4f5333e6067ec64a7120b0e6990f4e2bd9db-json.log",
"Name": "/amazing_swartz",
"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/dc5afe1a107eb52814a2aa197dab799b3520fadf45c5c325840524658b816412-init/diff:/var/lib/docker/overlay2/1df4d2ed45f644912e8bbb015da6068ce2dc4f149d0ce20c44586acc773fc61a/diff",
"MergedDir": "/var/lib/docker/overlay2/dc5afe1a107eb52814a2aa197dab799b3520fadf45c5c325840524658b816412/merged",
"UpperDir": "/var/lib/docker/overlay2/dc5afe1a107eb52814a2aa197dab799b3520fadf45c5c325840524658b816412/diff",
"WorkDir": "/var/lib/docker/overlay2/dc5afe1a107eb52814a2aa197dab799b3520fadf45c5c325840524658b816412/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "c109c4603669",
"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 6666;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "662462c192e051bb49eb3df2b13fc33a0429f288ab2bb44df5ad3e1b33c7426f",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/662462c192e0",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "234ee1328ec1c365cb6b7f0171c49bf40f8457a1eb517436cc4fff2caae51e74",
"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": "6057227c558119251707b6c0db6330684e5a254cf2946c6f8b2924c7776200c7",
"EndpointID": "234ee1328ec1c365cb6b7f0171c49bf40f8457a1eb517436cc4fff2caae51e74",
"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
}
}
}
}
]
进入当前正在运行的容器
# 我们通常容器都是在后台运行,需要进入容器,修改一些配置
# 方式一 开启一个新的bash或shell终端窗口
# 命令
docker exec -it 容器id bashshell
[sh-4.4# ~]# docker ps
[sh-4.4# ~]# ps -ef
# 方式二 不开启新的终端窗口
dcoker attach 容器id
# 测试
[root@localhost ~]# docker attach dce7bshk8oou7
正在执行当前的代码...
# 区别
docker exec #进入容器后开启一个新的终端
docker attach # 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
# 运行容器并且进入交互模式
[root@localhost /]# docker run -it centos /bin/bash
[root@a9525c9c9393 /]# cd home
[root@a9525c9c9393 home]# ls
# 在容器内部进行创建文件
[root@a9525c9c9393 home]# touch test.java
[root@a9525c9c9393 home]# ls
test.java
# 退出容器并且不结束容器运行 查看正在运行的容器id
[root@a9525c9c9393 home]# [root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9525c9c9393 centos "/bin/bash" 30 seconds ago Up 29 seconds beautiful_ritchie
# 进入容器
[root@localhost /]# docker attach a9525c9c9393
# 退出容器并且结束容器
[root@a9525c9c9393 home]# exit
exit
# 从容器中拷贝到本机
[root@localhost /]# docker cp a9525c9c9393:/home/test.java /home
[root@localhost /]# cd home
# 查看是否拷贝成功
[root@localhost home]# ls
test.java
[root@localhost home]#
# 拷贝是一个手动过程,未来我们可以使用-v卷的技术,可以实现自动同步 /home /home
3.5.小结
docker中镜像和容器的区别:
1.镜像是包含了各种环境或者服务的一个模板 而容器是镜像的一个实例
2.镜像是不能运行的 是静态的 而容器是可以运行的 是动态的
命令大全
attach Attach to a running container # 当前shell下attach连接指定运行镜像
build Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit Create a new image from a containers changes # 提交当前容器为新的镜像
cp Copy files/folders from a container to a HOSTDIR or to STDOUT # 从容器中拷贝指定文件或者目录到宿主机中
create Create a new container # 创建一个新的容器,同run 但不启动容器
diff Inspect changes on a containers filesystem # 查看docker容器变化
events Get real time events from the server # 从docker服务获取容器实时事件
exec Run a command in a running container # 在已存在的容器上运行命令
export Export a containers filesystem as a tar archive# 导出容器的内容流作为一个tar归档文件(对应import)
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Import the contents from a tarball to create a filesystem image # 从tar包中的内容创建一个新的文件系统映像(对应export)
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container or image # 查看容器详细信息
kill Kill a running container # kill指定docker容器
load Load an image from a tar archive or STDIN # 从一个tar包中加载一个镜像(对应save)
login Register or log in to a Docker registry # 注册或者登陆一个docker源服务器
logout Log out from a Docker registry # 从当前Docker registry退出
logs Fetch the logs of a container # 输出当前容器日志信息
pause Pause all processes within a container # 暂停容器
port List port mappings or a specific mapping for the CONTAINER # 查看映射端口对应的容器内部源端口
ps List containers # 列出容器列表
pull Pull an image or a repository from a registry # 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to a registry # 推送指定镜像或者库镜像至docker源服务器
rename Rename a container # 重命名容器
restart Restart a running container # 重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或多个镜像(无容器使用该镜像才可以删除,否则需要删除相关容器才可以继续或者-f强制删除)
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save an image(s) to a tar archive # 保存一个镜像为一个tar包(对应load)
search Search the Docker Hub for images # 在docker
hub中搜索镜像
start Start one or more stopped containers # 启动容器
stats Display a live stream of container(s) resource usage statistics # 统计容器使用资源
stop Stop a running container # 停止容器
tag Tag an image into a repository # 给源中镜像打标签
top Display the running processes of a container # 查看容器中运行的进程信息
unpause Unpause all processes within a container # 取消暂停容器
version Show the Docker version information # 查看容器版本号
wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值
3.6.作业练习(安装)
作业一:Docker 安装Nginx
# 1.搜索镜像
[root@localhost ~]# docker search nginx
# 2.拉取镜像
[root@localhost ~]# docker pull nginx
# 3.查看镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 8 months ago 141MB
mysql latest 3218b38490ce 8 months ago 516MB
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
centos latest 5d0da3dc9764 11 months ago 231MB
# 4.启动运行
[root@localhost ~]# docker run -d --name nginx01 -p 3344:80 nginx
66f84ea1a1679cc5f062e4c7aab26f051d30df710e23e7685597257933eb7d61
# -d 后台运行
# --name 给容器起名字
# -p 宿主机端口:容器内部端口
# 5.查看运行情况
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d320470acea6 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 6.本机自测运行情况
[root@localhost ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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>
# 成功访问nginx80 端口
外部也可以访问到
# 7.进入容器,修改配置
[root@localhost ~]# docker exec -it nginx01 /bin/bash
root@d320470acea6:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@d320470acea6:/# cd /etc/nginx
root@d320470acea6:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
root@d320470acea6:/etc/nginx#
端口暴露的概念
思考问题:我们每次都需要改动nginx配置,都需要进入容器内部?十分的麻烦,我们要是可以在容器外部提供一个映射路径,达到可以在容器外部修改文件名,容器内部就可以进行自动修改?-数据卷
作业二:用docker 来装一个tomcat
# 1.搜索镜像
[root@localhost ~]# docker search tomcat
# 2.拉取镜像
[root@localhost ~]# docker pull tomcat
# 3.查看镜像
[root@localhost ~]# docker images
# 4.启动运行
[root@localhost ~]# docker run -d --name tomcat01 -p 3355:8080 tomcat
360c1575e51593850917c7835c6b3e9b02d5cb54f3630f4c493dcb1d108b8581
# -d 后台运行
# --name 给容器起名字
# -p 宿主机端口:容器内部端口
# 5.测试访问没有问题
# 5.1.发现问题
# 但是我们发现了一个问题 这个tomcat不完整
# linux命令少了 webapps目录为空
# 原因:阿里云镜像默认是最小的 把所有不必要的都剔除掉
# 保证最小可运行的环境
# 5.2.解决方法
# 方式一:将webapps.dist下的文件都拷贝到webapps下即可
# 方式二:将webapps.dist改名成webapps即可
# 这样docker部署tomcat就可以访问了
# 扩展
# 下载 tomcat9.0
# 之前的启动都是后台,停止了容器,容器还是可以查到, docker run -it --rm 镜像名 一般是用来测试,用完就删除
[root@localhost ~]# docker run -it --rm tomcat:9.0
# 扩展
# 已经运行了tomcat 我们把它停止看一下是否删除了 并没有已经删除了
问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,比如webapps,我们在外部放置项目,就自动同步内部就好了!
作业三:部署elasticsearch+kibana
# Elasticsearch 暴露的端口很多
# Elasticsearch 十分耗内存
# Elasticsearch 的数据一般需要放置到安全目录!挂载
# --net somenetwork ? 网络配置
# 启动Elasticsearch
[root@localhost ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 测试一下启动Elasticsearch是否成功启动
[root@localhost ~]# curl localhost:9200
{
"name" : "f93e12029746",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "TQ35zd5tRaKE7tYkcQXm3w",
"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"
}
# 测试成功就关掉Elasticsearch 防止耗内存
[root@localhost ~]# docker stop f93e12029746
f93e12029746
# 查看docker容器使用内存情况
[root@localhost ~]# docker stats
# 测试成功就关掉Elasticsearch 增加内存的限制 修改配置文件 -e 环境配置修改
[root@localhost ~]#docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 查看状态
docker stats 3553281f0124
# 访问成功
[root@localhost ~]# curl localhost:9200
{
"name" : "3553281f0124",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "ADbhVlrORX-900UonZqA_w",
"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连接es (elasticSearch)?思考网络如何才能连接
Portainer 可视化面板安装
- portainer(先用这个)
docker run -d -p 8080:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD再用)
什么是portainer?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
# 安装命令
[root@localhost home]# docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
Unable to find image 'portainer/portainer:latest' locally
latest: Pulling from portainer/portainer
94cfa856b2b1: Pull complete
49d59ee0881a: Pull complete
a2300fd28637: Pull complete
Digest: sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f
Status: Downloaded newer image for portainer/portainer:latest
b7213da870de3fb291a30d24471b689306b0109faf5b28aca19d697f01c6cf7f
- 测试访问: 外网:9000 :http://192.168.0.130:9000/
-
设置密码登录上去选择本地
-
进入之后的面板
4.镜像原理之联合文件系统
4.1.镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来
如何得到镜像:
- 从远处仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
4.2.Docker镜像加载原理
- UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
- 镜像加载原理
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装虚拟机的centos都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
虚拟机是分钟级别的,容器是秒级别的。
4.3.分层的镜像
我们去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
思考:为什么要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了,比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中只需要加载一份base镜像,这样就可以为多有的容器服务了,而且每一层都可以被共享
查看镜像分层的方式可以通过docker image inspect 命令
[root@localhost ~]# docker image inspect redis:latest
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:7e718b9c0c8c2e6420fe9c4d1d551088e314fe923dce4b2caf75891d82fb227d",
"sha256:89ce1a07a7e4574d724ea605b4877f8a73542cf6abd3c8cbbd2668d911fa5353",
"sha256:9eef6e3cc2937e452b2325b227ca28120a70481be25404ed9aad27fa81219fd0",
"sha256:ee748697d275b904f1d5604345d70b647a8c145b9f05aeb5ca667e1f256e43d8",
"sha256:f1f7964d40afa49c6ef63ab11af91044e518a2539f567783ce997d3cea9ce8f6",
"sha256:3d9fda8ff875e549d54e9d7504ce17d27423fe27dafbb92127c603dddad7fa13"
]
},
理解:
所有的 Docker|镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终是保持当前所有镜像的组合,理解这一点是非常重要的。下图拒了一个简单的例子,每个镜像包含三个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层和之前的图中略有区别,主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5的一个更新版
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。 Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系統。 Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfiter一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合井,对外提供统一的视图。
特点
Docker镜像都是只读的 当容器启动时 一个新的可写层被加载到镜像顶部
这一层就是我们通常说的容器层 容器之下的都叫镜像层
4.4.commit镜像
docker commit # 提交容器成为一个新的副本
docker commit -m # "提交的描述信息" -a="作者" 容器id 目标镜像名:[tag] 命令和git原理类似
实战测试
# 1.启动一个默认的tomcat
# 2.发现这个默认的tomcat是没有webapps应用的 镜像的原因:官方镜像默认webapps下面没有文件的
# 3.我自己拷贝进去了基本的文件
# 4.将我们自己操作过后的容器通过commit提交为一个镜像 我们以后就可以使用自己修改过的镜像 这就是我们自己的一个修改过的镜像
[root@localhost ~]# docker commit -a="xiao" -m="add webapps app" a0d539971acd tomcat02:1.0
sha256:ab7aa3ba7a164203e1f9a5bd8d8f633a64a2e184cdd82301c3ee6a6e49cb8f3a
# 5.查看我们提交的镜像
docker images
如果你想要保存当前的状态 就通过commit提交 获得一个镜像 就好比我们以前学习VM时候 快照
5. 容器数据卷
5.1.什么是容器数据卷
docker的理念回顾
-
将应用环境打包成一个镜像
-
数据问题 如果数据都在容器中 那么我们容器删除 数据就会丢失 需求:数据可以持久化
-
MySQL 容器删除了 删库跑路 需求:MySQL的数据可以存储在本地
-
容器之间可以有一个数据共享的技术 docker容器中产生的数据 同步到本地
这就是卷技术,目录的挂载,将容器内的目录挂载在Linux上面
总结一句话:容器的持久化和同步操作 容器间也是可以数据共享的
5.2.使用命令来挂载
docker run -it -v 主机目录:容器的目录
# 测试
[root@localhost home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 容器启动的时候我们可以通过docker inspect 容器id 去查看容器相信信息
测试文件的同步
再来测试
-
停止容器
-
宿主机上修改文件
-
启动容器
-
容器内的数据依旧是同步的
优点:我们以后修改只需要在本地进行修改即可 容器内部会自动进行同步
实战:安装MySQL
# 获取镜像
[root@localhost ~]# docker pull mysql:5.7
# 运行容器,需要做数据挂载 安装MySQL需要配置密码 下面是官方命令
[root@localhost ~]#docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动我们的-d后台运行 -p端口映射 -v数据卷挂载 -e环境配置 --name容器名字
[root@localhost /]# 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=123.com --name mysql01 mysql
# 启动成功后 我们在本地使用Navict来测试连接一下
# Navict连接到服务器3310后 3310和容器内部的3306进行映射 这个时候就可以连接上了
# 本地测试新建数据库 查看映射的路径是否可以同步数据
假设我们把容器删除
5.3.具名和匿名挂载
# 匿名挂载 -v只指定了容器内的路径 没有指定容器外的路径
[root@localhost /]# docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
[root@localhost /]# docker volume ls
# 具名挂载 -v指定了容器外的路径 也指定卷名 # -v /juming-nginx 这个是指定路径 juming-nginx 这个是卷名
[root@localhost ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx
# 查看所有的volume的情况
[root@localhost /]# docker volume ls
# 通过查看volume就可以看到 卷名:容器内路径
[root@localhost /]# docker volume inspect juming-nginx
# 进入这个路径 查看一下
[root@localhost /]# cd /var/lib/docker/volumes/juming-nginx/_data/
# 查看一下是否有nginx的配置文件
[root@localhost _data]# ls
# 看到了nginx的配置文件 证明拿到了nginx的配置文件 没有错
所有的docker容器内的卷,在没有指定路径的情况下都是在/var/lib/docker/volumes/xxx/_data
我们通过具名挂载可以方便找到我们的一个卷,大多数情况下都是使用具名挂载
# 如何确定是匿名挂载还是具名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v 宿主机路径:容器内路径 # 指定路径挂载
拓展
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦设置了这个容器权限 容器对我们挂载出来的内容就有了限制了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v /etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
docker run -d -P --name nginx02 -v /etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作 容器内部是无法进行操作的
5.4.初识DockerFile
DockerFile就是用来构建docker镜像的构建文件 命令脚本 先体验一下
通过这个脚本可以生成一个镜像 镜像是一层层的 所以脚本是一个个的命令
# 文件中的内容 命令(大写)
# 参数:
# FROM centos # 当前构建这个镜像 以centos为基础
# VOLUME ["volume01","volume02"] # 生成的时候就挂载卷
# CMD echo "---end---" # 构建成功之后输出end
# CMD /bin/bash # 构建成功后默认走的是bash控制台
# 这里的每个命令就是镜像的一层
# 创建一个dockerfile文件 名字可以随机 建议Dockerfile
[root@localhost docker-test-volume]docker build -f /home/docker-test-volume/dockerfile1 -t xiao/centos:1.0 .
# build # 构建一个镜像
# -f # 通过-f指定的文件来构建镜像
# -t # 生成(name)镜像
# . # 当前目录下
# 查看一下是否构建镜像成功
docker images
# 启动一下自己写的容器
这个卷和外部一定有一个同步的目录
查看一下卷挂载的路径
[root@localhost data]# docker inspect fca535846c94
# 测试一下文件是否已经被同步出去了
[root@localhost _data]# cd /var/lib/docker/volumes/a15fa5acea56bd53fae7fc7b71a328cf26a6a2eb5c38b76ee7cdf5bf917dbe1e/_data
[root@localhost _data]# ls
这种方式未来的使用非常多 因为我们自己通常会构建自己的镜像
假设构建镜像的时候没有挂载 需要自己手动挂载镜像 -v 卷名:容器内路径
5.5.数据卷容器
多个MySQL同步数据
启动3个容器 通过我们刚在自己写的镜像启动
启动第一个容器
启动第二个容器
docker01的数据同步到了docker02
启动第三个容器并且也挂载docker01
# 测试 :可以删除容器dcoker01,查看docker02和docker03时候还可以访问这个文件
# 测试结果是依然可以访问到
多个MySQL实现数据共享
# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=338218 --name mysql01 mysql:5.7
# docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=338218 --name mysql02 --volumes-from mysql01 mysql:5.7# # 这个时候可以实现两个容器数据同步
结论:
容器之间配置信息的传递 数据卷容器的生命周期这一直持续到没有容器使用为止
但是一旦持久化到了本地 这个时候 本地的数据不会被删除
6.DockerFile
6.1.DockerFile介绍
dockerfile是用来构建docker镜像的文件,命令参数脚本
构建步骤:
-
编写一个dockerfile文件
-
docker build构建为一个镜像
-
docker run 运行镜像
-
docker push发布镜像(DockerHub、阿里云镜像仓库)
查看一下官方是怎么做的
很多官方的镜像都是基础包 很多功能都没有 我们通常会自己搭建自己的镜像
官方可以制作镜像 那我们也可以
6.2.DockerFile镜像的构建
基础知识:
-
每个保留关键字(指令)都是必须是大写字母
-
执行从上到下顺序执行
-
表示注释
-
每一个指令都会创建提交一个新的镜像层,并提交
-
dockerfile是面向开发的 我们以后要发布项目 做镜像 就需要编写dockerfile文件 这个文件十分简单
-
Docker镜像逐渐成为了企业交付的标准 必须要掌握
-
步骤:开发 部署,运维…缺一不可
-
DockerFile:构建文件 定义了一切的步骤 源代码
-
DockerImages:通过DockerFile构建生成的镜像 最终发布和运行的产品
-
Docker容器:容器就是镜像运行起来提供服务的
6.3.Docker指令
FROM # 基础镜像 一切从这里开始
MAINTAINER # 镜像是谁写的 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像 这个tomcat压缩包 添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定容器运行时的shell命令 只有最后一个生效 可被替代
ENTRYPOINT # 指定容器运行时的shell命令 可以追加命令
ONBUILD # 当构建一个被继承DockerFile这个还是会就会运行ONBUILD的指令 触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
6.4.实战训练
Docker Hub中99%的镜像都是从这个基础镜像过来的FROM scratch 然后配置需要的软件和配置来进行构建的
创建一个自己的centos
# 1、编写Dockerfile文件[root@localhost dockerfile]# cat mydockerfile-centos FROM centosMAINTAINER eric<doctor_eric@163.com>ENV MYPATH /usr/localWORKDIR $MYPATHRUN yum -y install vimRUN yum -y install net-toolsEXPOSE 80CMD echo $MYPATHCMD echo "----end----"CMD /bin/bash# 2、通过这个文件构建镜像# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]Successfully built dc4556607d09Successfully tagged mycentos:0.1# 3、测试运行
对比:之前原生的centos
# 1.编写 Dockerfile文件
[root@localhost dockerfile]# vim myDockerfile
[root@localhost dockerfile]# cat myDockerfile
FROM centos:7
MAINTAINER xiao<1559567258@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.通过这个myDockerfile文件构建镜像
[root@localhost dockerfile]# docker build -f myDockerfile -t mycentos:0.1 .
Sending build context to Docker daemon 2.048kB
Step 1/11 : FROM centos:7
---> eeb6ee3f44bd
Step 2/11 : MAINTAINER xiao<1559567258@qq.com>
---> Using cache
---> 3bce5ca94a90
Step 3/11 : ENV MYPATH /usr/local
---> Using cache
---> d7b10d43dfd9
Step 4/11 : WORKDIR $MYPATH
---> Using cache
---> 2798b9857343
Step 5/11 : RUN yum install vim
---> Running in f9c8c6aa2670
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
* base: mirrors.huaweicloud.com
* extras: mirrors.neusoft.edu.cn
* updates: mirrors.neusoft.edu.cn
Resolving Dependencies
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-common = 2:7.4.629-8.el7_9 for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: which for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: perl(:MODULE_COMPAT_5.16.3) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: libperl.so()(64bit) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: libgpm.so.2()(64bit) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Running transaction check
---> Package gpm-libs.x86_64 0:1.20.7-6.el7 will be installed
---> Package perl.x86_64 4:5.16.3-299.el7_9 will be installed
--> Processing Dependency: perl(Socket) >= 1.3 for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Scalar::Util) >= 1.10 for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl-macros for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(threads::shared) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(threads) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(constant) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Time::Local) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Time::HiRes) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Storable) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Socket) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Scalar::Util) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Pod::Simple::XHTML) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Pod::Simple::Search) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Getopt::Long) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Filter::Util::Call) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Temp) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec::Unix) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec::Functions) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Path) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Exporter) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Cwd) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Carp) for package: 4:perl-5.16.3-299.el7_9.x86_64
---> Package perl-libs.x86_64 4:5.16.3-299.el7_9 will be installed
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-filesystem for package: 2:vim-common-7.4.629-8.el7_9.x86_64
---> Package which.x86_64 0:2.20-7.el7 will be installed
--> Running transaction check
---> Package perl-Carp.noarch 0:1.26-244.el7 will be installed
---> Package perl-Exporter.noarch 0:5.68-3.el7 will be installed
---> Package perl-File-Path.noarch 0:2.09-2.el7 will be installed
---> Package perl-File-Temp.noarch 0:0.23.01-3.el7 will be installed
---> Package perl-Filter.x86_64 0:1.49-3.el7 will be installed
---> Package perl-Getopt-Long.noarch 0:2.40-3.el7 will be installed
--> Processing Dependency: perl(Pod::Usage) >= 1.14 for package: perl-Getopt-Long-2.40-3.el7.noarch
--> Processing Dependency: perl(Text::ParseWords) for package: perl-Getopt-Long-2.40-3.el7.noarch
---> Package perl-PathTools.x86_64 0:3.40-5.el7 will be installed
---> Package perl-Pod-Simple.noarch 1:3.28-4.el7 will be installed
--> Processing Dependency: perl(Pod::Escapes) >= 1.04 for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
--> Processing Dependency: perl(Encode) for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
---> Package perl-Scalar-List-Utils.x86_64 0:1.27-248.el7 will be installed
---> Package perl-Socket.x86_64 0:2.010-5.el7 will be installed
---> Package perl-Storable.x86_64 0:2.45-3.el7 will be installed
---> Package perl-Time-HiRes.x86_64 4:1.9725-3.el7 will be installed
---> Package perl-Time-Local.noarch 0:1.2300-2.el7 will be installed
---> Package perl-constant.noarch 0:1.27-2.el7 will be installed
---> Package perl-macros.x86_64 4:5.16.3-299.el7_9 will be installed
---> Package perl-threads.x86_64 0:1.87-4.el7 will be installed
---> Package perl-threads-shared.x86_64 0:1.43-6.el7 will be installed
---> Package vim-filesystem.x86_64 2:7.4.629-8.el7_9 will be installed
--> Running transaction check
---> Package perl-Encode.x86_64 0:2.51-7.el7 will be installed
---> Package perl-Pod-Escapes.noarch 1:1.04-299.el7_9 will be installed
---> Package perl-Pod-Usage.noarch 0:1.63-3.el7 will be installed
--> Processing Dependency: perl(Pod::Text) >= 3.15 for package: perl-Pod-Usage-1.63-3.el7.noarch
--> Processing Dependency: perl-Pod-Perldoc for package: perl-Pod-Usage-1.63-3.el7.noarch
---> Package perl-Text-ParseWords.noarch 0:3.29-4.el7 will be installed
--> Running transaction check
---> Package perl-Pod-Perldoc.noarch 0:3.20-4.el7 will be installed
--> Processing Dependency: perl(parent) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: perl(HTTP::Tiny) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: groff-base for package: perl-Pod-Perldoc-3.20-4.el7.noarch
---> Package perl-podlators.noarch 0:2.5.1-3.el7 will be installed
--> Running transaction check
---> Package groff-base.x86_64 0:1.22.2-8.el7 will be installed
---> Package perl-HTTP-Tiny.noarch 0:0.033-3.el7 will be installed
---> Package perl-parent.noarch 1:0.225-244.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
vim-enhanced x86_64 2:7.4.629-8.el7_9 updates 1.1 M
Installing for dependencies:
gpm-libs x86_64 1.20.7-6.el7 base 32 k
groff-base x86_64 1.22.2-8.el7 base 942 k
perl x86_64 4:5.16.3-299.el7_9 updates 8.0 M
perl-Carp noarch 1.26-244.el7 base 19 k
perl-Encode x86_64 2.51-7.el7 base 1.5 M
perl-Exporter noarch 5.68-3.el7 base 28 k
perl-File-Path noarch 2.09-2.el7 base 26 k
perl-File-Temp noarch 0.23.01-3.el7 base 56 k
perl-Filter x86_64 1.49-3.el7 base 76 k
perl-Getopt-Long noarch 2.40-3.el7 base 56 k
perl-HTTP-Tiny noarch 0.033-3.el7 base 38 k
perl-PathTools x86_64 3.40-5.el7 base 82 k
perl-Pod-Escapes noarch 1:1.04-299.el7_9 updates 52 k
perl-Pod-Perldoc noarch 3.20-4.el7 base 87 k
perl-Pod-Simple noarch 1:3.28-4.el7 base 216 k
perl-Pod-Usage noarch 1.63-3.el7 base 27 k
[root@localhost dockerfile]# docker build -f myDockerfile -t mycentos:0.1 .
Sending build context to Docker daemon 2.048kB
Step 1/10 : FROM centos:7
---> eeb6ee3f44bd
Step 2/10 : MAINTAINER xiao<1559567258@qq.com>
---> Using cache
---> 3bce5ca94a90
Step 3/10 : ENV MYPATH /usr/local
---> Using cache
---> d7b10d43dfd9
Step 4/10 : WORKDIR $MYPATH
---> Using cache
---> 2798b9857343
Step 5/10 : RUN yum -y install vim
---> Running in 91b1fa8ad6af
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
* base: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.bupt.edu.cn
* updates: mirrors.bupt.edu.cn
Resolving Dependencies
--> Running transaction check
---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-common = 2:7.4.629-8.el7_9 for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: which for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: perl(:MODULE_COMPAT_5.16.3) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: libperl.so()(64bit) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Processing Dependency: libgpm.so.2()(64bit) for package: 2:vim-enhanced-7.4.629-8.el7_9.x86_64
--> Running transaction check
---> Package gpm-libs.x86_64 0:1.20.7-6.el7 will be installed
---> Package perl.x86_64 4:5.16.3-299.el7_9 will be installed
--> Processing Dependency: perl(Socket) >= 1.3 for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Scalar::Util) >= 1.10 for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl-macros for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(threads::shared) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(threads) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(constant) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Time::Local) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Time::HiRes) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Storable) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Socket) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Scalar::Util) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Pod::Simple::XHTML) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Pod::Simple::Search) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Getopt::Long) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Filter::Util::Call) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Temp) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec::Unix) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec::Functions) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Spec) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(File::Path) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Exporter) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Cwd) for package: 4:perl-5.16.3-299.el7_9.x86_64
--> Processing Dependency: perl(Carp) for package: 4:perl-5.16.3-299.el7_9.x86_64
---> Package perl-libs.x86_64 4:5.16.3-299.el7_9 will be installed
---> Package vim-common.x86_64 2:7.4.629-8.el7_9 will be installed
--> Processing Dependency: vim-filesystem for package: 2:vim-common-7.4.629-8.el7_9.x86_64
---> Package which.x86_64 0:2.20-7.el7 will be installed
--> Running transaction check
---> Package perl-Carp.noarch 0:1.26-244.el7 will be installed
---> Package perl-Exporter.noarch 0:5.68-3.el7 will be installed
---> Package perl-File-Path.noarch 0:2.09-2.el7 will be installed
---> Package perl-File-Temp.noarch 0:0.23.01-3.el7 will be installed
---> Package perl-Filter.x86_64 0:1.49-3.el7 will be installed
---> Package perl-Getopt-Long.noarch 0:2.40-3.el7 will be installed
--> Processing Dependency: perl(Pod::Usage) >= 1.14 for package: perl-Getopt-Long-2.40-3.el7.noarch
--> Processing Dependency: perl(Text::ParseWords) for package: perl-Getopt-Long-2.40-3.el7.noarch
---> Package perl-PathTools.x86_64 0:3.40-5.el7 will be installed
---> Package perl-Pod-Simple.noarch 1:3.28-4.el7 will be installed
--> Processing Dependency: perl(Pod::Escapes) >= 1.04 for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
--> Processing Dependency: perl(Encode) for package: 1:perl-Pod-Simple-3.28-4.el7.noarch
---> Package perl-Scalar-List-Utils.x86_64 0:1.27-248.el7 will be installed
---> Package perl-Socket.x86_64 0:2.010-5.el7 will be installed
---> Package perl-Storable.x86_64 0:2.45-3.el7 will be installed
---> Package perl-Time-HiRes.x86_64 4:1.9725-3.el7 will be installed
---> Package perl-Time-Local.noarch 0:1.2300-2.el7 will be installed
---> Package perl-constant.noarch 0:1.27-2.el7 will be installed
---> Package perl-macros.x86_64 4:5.16.3-299.el7_9 will be installed
---> Package perl-threads.x86_64 0:1.87-4.el7 will be installed
---> Package perl-threads-shared.x86_64 0:1.43-6.el7 will be installed
---> Package vim-filesystem.x86_64 2:7.4.629-8.el7_9 will be installed
--> Running transaction check
---> Package perl-Encode.x86_64 0:2.51-7.el7 will be installed
---> Package perl-Pod-Escapes.noarch 1:1.04-299.el7_9 will be installed
---> Package perl-Pod-Usage.noarch 0:1.63-3.el7 will be installed
--> Processing Dependency: perl(Pod::Text) >= 3.15 for package: perl-Pod-Usage-1.63-3.el7.noarch
--> Processing Dependency: perl-Pod-Perldoc for package: perl-Pod-Usage-1.63-3.el7.noarch
---> Package perl-Text-ParseWords.noarch 0:3.29-4.el7 will be installed
--> Running transaction check
---> Package perl-Pod-Perldoc.noarch 0:3.20-4.el7 will be installed
--> Processing Dependency: perl(parent) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: perl(HTTP::Tiny) for package: perl-Pod-Perldoc-3.20-4.el7.noarch
--> Processing Dependency: groff-base for package: perl-Pod-Perldoc-3.20-4.el7.noarch
---> Package perl-podlators.noarch 0:2.5.1-3.el7 will be installed
--> Running transaction check
---> Package groff-base.x86_64 0:1.22.2-8.el7 will be installed
---> Package perl-HTTP-Tiny.noarch 0:0.033-3.el7 will be installed
---> Package perl-parent.noarch 1:0.225-244.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
vim-enhanced x86_64 2:7.4.629-8.el7_9 updates 1.1 M
Installing for dependencies:
gpm-libs x86_64 1.20.7-6.el7 base 32 k
groff-base x86_64 1.22.2-8.el7 base 942 k
perl x86_64 4:5.16.3-299.el7_9 updates 8.0 M
perl-Carp noarch 1.26-244.el7 base 19 k
perl-Encode x86_64 2.51-7.el7 base 1.5 M
perl-Exporter noarch 5.68-3.el7 base 28 k
perl-File-Path noarch 2.09-2.el7 base 26 k
perl-File-Temp noarch 0.23.01-3.el7 base 56 k
perl-Filter x86_64 1.49-3.el7 base 76 k
perl-Getopt-Long noarch 2.40-3.el7 base 56 k
perl-HTTP-Tiny noarch 0.033-3.el7 base 38 k
perl-PathTools x86_64 3.40-5.el7 base 82 k
perl-Pod-Escapes noarch 1:1.04-299.el7_9 updates 52 k
perl-Pod-Perldoc noarch 3.20-4.el7 base 87 k
perl-Pod-Simple noarch 1:3.28-4.el7 base 216 k
perl-Pod-Usage noarch 1.63-3.el7 base 27 k
perl-Scalar-List-Utils x86_64 1.27-248.el7 base 36 k
perl-Socket x86_64 2.010-5.el7 base 49 k
perl-Storable x86_64 2.45-3.el7 base 77 k
perl-Text-ParseWords noarch 3.29-4.el7 base 14 k
perl-Time-HiRes x86_64 4:1.9725-3.el7 base 45 k
perl-Time-Local noarch 1.2300-2.el7 base 24 k
perl-constant noarch 1.27-2.el7 base 19 k
perl-libs x86_64 4:5.16.3-299.el7_9 updates 690 k
perl-macros x86_64 4:5.16.3-299.el7_9 updates 44 k
perl-parent noarch 1:0.225-244.el7 base 12 k
perl-podlators noarch 2.5.1-3.el7 base 112 k
perl-threads x86_64 1.87-4.el7 base 49 k
perl-threads-shared x86_64 1.43-6.el7 base 39 k
vim-common x86_64 2:7.4.629-8.el7_9 updates 5.9 M
vim-filesystem x86_64 2:7.4.629-8.el7_9 updates 11 k
which x86_64 2.20-7.el7 base 41 k
Transaction Summary
================================================================================
Install 1 Package (+32 Dependent packages)
Total download size: 19 M
Installed size: 63 M
Downloading packages:
warning: /var/cache/yum/x86_64/7/base/packages/perl-Carp-1.26-244.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY
Public key for perl-Carp-1.26-244.el7.noarch.rpm is not installed
Public key for perl-Pod-Escapes-1.04-299.el7_9.noarch.rpm is not installed
--------------------------------------------------------------------------------
Total 1.8 MB/s | 19 MB 00:10
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Importing GPG key 0xF4A80EB5:
Userid : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>"
Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5
Package : centos-release-7-9.2009.0.el7.centos.x86_64 (@CentOS)
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : gpm-libs-1.20.7-6.el7.x86_64 1/33
Installing : 2:vim-filesystem-7.4.629-8.el7_9.x86_64 2/33
Installing : 2:vim-common-7.4.629-8.el7_9.x86_64 3/33
Installing : which-2.20-7.el7.x86_64 4/33
install-info: No such file or directory for /usr/share/info/which.info.gz
Installing : groff-base-1.22.2-8.el7.x86_64 5/33
Installing : 1:perl-parent-0.225-244.el7.noarch 6/33
Installing : perl-HTTP-Tiny-0.033-3.el7.noarch 7/33
Installing : perl-podlators-2.5.1-3.el7.noarch 8/33
Installing : perl-Pod-Perldoc-3.20-4.el7.noarch 9/33
Installing : 1:perl-Pod-Escapes-1.04-299.el7_9.noarch 10/33
Installing : perl-Encode-2.51-7.el7.x86_64 11/33
Installing : perl-Text-ParseWords-3.29-4.el7.noarch 12/33
Installing : perl-Pod-Usage-1.63-3.el7.noarch 13/33
Installing : 4:perl-macros-5.16.3-299.el7_9.x86_64 14/33
Installing : perl-Storable-2.45-3.el7.x86_64 15/33
Installing : perl-Exporter-5.68-3.el7.noarch 16/33
Installing : perl-constant-1.27-2.el7.noarch 17/33
Installing : perl-Socket-2.010-5.el7.x86_64 18/33
Installing : perl-Time-Local-1.2300-2.el7.noarch 19/33
Installing : perl-Carp-1.26-244.el7.noarch 20/33
Installing : perl-PathTools-3.40-5.el7.x86_64 21/33
Installing : perl-Scalar-List-Utils-1.27-248.el7.x86_64 22/33
Installing : 1:perl-Pod-Simple-3.28-4.el7.noarch 23/33
Installing : perl-File-Temp-0.23.01-3.el7.noarch 24/33
Installing : perl-File-Path-2.09-2.el7.noarch 25/33
Installing : perl-threads-shared-1.43-6.el7.x86_64 26/33
Installing : perl-threads-1.87-4.el7.x86_64 27/33
Installing : 4:perl-Time-HiRes-1.9725-3.el7.x86_64 28/33
Installing : perl-Filter-1.49-3.el7.x86_64 29/33
Installing : 4:perl-libs-5.16.3-299.el7_9.x86_64 30/33
Installing : perl-Getopt-Long-2.40-3.el7.noarch 31/33
Installing : 4:perl-5.16.3-299.el7_9.x86_64 32/33
Installing : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 33/33
Verifying : perl-HTTP-Tiny-0.033-3.el7.noarch 1/33
Verifying : perl-threads-shared-1.43-6.el7.x86_64 2/33
Verifying : perl-Storable-2.45-3.el7.x86_64 3/33
Verifying : groff-base-1.22.2-8.el7.x86_64 4/33
Verifying : perl-Exporter-5.68-3.el7.noarch 5/33
Verifying : perl-constant-1.27-2.el7.noarch 6/33
Verifying : perl-PathTools-3.40-5.el7.x86_64 7/33
Verifying : 4:perl-macros-5.16.3-299.el7_9.x86_64 8/33
Verifying : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 9/33
Verifying : 1:perl-parent-0.225-244.el7.noarch 10/33
Verifying : perl-Socket-2.010-5.el7.x86_64 11/33
Verifying : which-2.20-7.el7.x86_64 12/33
Verifying : 2:vim-filesystem-7.4.629-8.el7_9.x86_64 13/33
Verifying : perl-File-Temp-0.23.01-3.el7.noarch 14/33
Verifying : 1:perl-Pod-Simple-3.28-4.el7.noarch 15/33
Verifying : perl-Time-Local-1.2300-2.el7.noarch 16/33
Verifying : 1:perl-Pod-Escapes-1.04-299.el7_9.noarch 17/33
Verifying : perl-Carp-1.26-244.el7.noarch 18/33
Verifying : 2:vim-common-7.4.629-8.el7_9.x86_64 19/33
Verifying : perl-Scalar-List-Utils-1.27-248.el7.x86_64 20/33
Verifying : perl-Pod-Usage-1.63-3.el7.noarch 21/33
Verifying : perl-Encode-2.51-7.el7.x86_64 22/33
Verifying : perl-Pod-Perldoc-3.20-4.el7.noarch 23/33
Verifying : perl-podlators-2.5.1-3.el7.noarch 24/33
Verifying : 4:perl-5.16.3-299.el7_9.x86_64 25/33
Verifying : perl-File-Path-2.09-2.el7.noarch 26/33
Verifying : perl-threads-1.87-4.el7.x86_64 27/33
Verifying : 4:perl-Time-HiRes-1.9725-3.el7.x86_64 28/33
Verifying : gpm-libs-1.20.7-6.el7.x86_64 29/33
Verifying : perl-Filter-1.49-3.el7.x86_64 30/33
Verifying : perl-Getopt-Long-2.40-3.el7.noarch 31/33
Verifying : perl-Text-ParseWords-3.29-4.el7.noarch 32/33
Verifying : 4:perl-libs-5.16.3-299.el7_9.x86_64 33/33
Installed:
vim-enhanced.x86_64 2:7.4.629-8.el7_9
Dependency Installed:
gpm-libs.x86_64 0:1.20.7-6.el7
groff-base.x86_64 0:1.22.2-8.el7
perl.x86_64 4:5.16.3-299.el7_9
perl-Carp.noarch 0:1.26-244.el7
perl-Encode.x86_64 0:2.51-7.el7
perl-Exporter.noarch 0:5.68-3.el7
perl-File-Path.noarch 0:2.09-2.el7
perl-File-Temp.noarch 0:0.23.01-3.el7
perl-Filter.x86_64 0:1.49-3.el7
perl-Getopt-Long.noarch 0:2.40-3.el7
perl-HTTP-Tiny.noarch 0:0.033-3.el7
perl-PathTools.x86_64 0:3.40-5.el7
perl-Pod-Escapes.noarch 1:1.04-299.el7_9
perl-Pod-Perldoc.noarch 0:3.20-4.el7
perl-Pod-Simple.noarch 1:3.28-4.el7
perl-Pod-Usage.noarch 0:1.63-3.el7
perl-Scalar-List-Utils.x86_64 0:1.27-248.el7
perl-Socket.x86_64 0:2.010-5.el7
perl-Storable.x86_64 0:2.45-3.el7
perl-Text-ParseWords.noarch 0:3.29-4.el7
perl-Time-HiRes.x86_64 4:1.9725-3.el7
perl-Time-Local.noarch 0:1.2300-2.el7
perl-constant.noarch 0:1.27-2.el7
perl-libs.x86_64 4:5.16.3-299.el7_9
perl-macros.x86_64 4:5.16.3-299.el7_9
perl-parent.noarch 1:0.225-244.el7
perl-podlators.noarch 0:2.5.1-3.el7
perl-threads.x86_64 0:1.87-4.el7
perl-threads-shared.x86_64 0:1.43-6.el7
vim-common.x86_64 2:7.4.629-8.el7_9
vim-filesystem.x86_64 2:7.4.629-8.el7_9
which.x86_64 0:2.20-7.el7
Complete!
Removing intermediate container 91b1fa8ad6af
---> 3d00a2ca3556
Step 6/10 : RUN yum -y install net-tools
---> Running in a1734a3dafbd
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
* base: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.bupt.edu.cn
* updates: mirrors.bupt.edu.cn
Resolving Dependencies
--> Running transaction check
---> Package net-tools.x86_64 0:2.0-0.25.20131004git.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
net-tools x86_64 2.0-0.25.20131004git.el7 base 306 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 306 k
Installed size: 917 k
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1
Verifying : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1
Installed:
net-tools.x86_64 0:2.0-0.25.20131004git.el7
Complete!
Removing intermediate container a1734a3dafbd
---> 373b9da17329
Step 7/10 : EXPOSE 80
---> Running in d3e42e4887ee
Removing intermediate container d3e42e4887ee
---> a5e76e701a21
Step 8/10 : CMD echo $MYPATH
---> Running in de14bbf2f0a8
Removing intermediate container de14bbf2f0a8
---> 2071e6abd054
Step 9/10 : CMD echo "----end----"
---> Running in 621b4c53b471
Removing intermediate container 621b4c53b471
---> c668343fed61
Step 10/10 : CMD /bin/bash
---> Running in d68e3457124e
Removing intermediate container d68e3457124e
---> 24f054918674
Successfully built 24f054918674
Successfully tagged mycentos:0.1
# 看到Successfully 就代表构建成功了
构建成功
对比之前原生的centos
我们增加之后的镜像
# 3.我们可以列出本地镜像的变更历史:docker history 镜像id
[root@localhost dockerfile]# docker history 24f054918674
IMAGE CREATED CREATED BY SIZE COMMENT
24f054918674 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
c668343fed61 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
2071e6abd054 15 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
a5e76e701a21 15 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
373b9da17329 15 minutes ago /bin/sh -c yum -y install net-tools 182MB
3d00a2ca3556 15 minutes ago /bin/sh -c yum -y install vim 237MB
2798b9857343 28 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
d7b10d43dfd9 28 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
3bce5ca94a90 28 minutes ago /bin/sh -c #(nop) MAINTAINER xiao<155956725… 0B
eeb6ee3f44bd 11 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 11 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 11 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
6.5.用实战看CMD和ENTRYPOINT的区别
CMD 和 ENTRYPOINT 区别
测试CMD
# 1.dockefile文件
FROM centos
CMD ["ls","-a"]
# 2.构建CMD镜像
[root@localhost dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-a"]
---> Running in 0bc2d4f51b5a
Removing intermediate container 0bc2d4f51b5a
---> 822b816c7988
Successfully built 822b816c7988
Successfully tagged cmdtest:latest
# 3.启动CMD镜像 发现ls -a生效
[root@localhost dockerfile]# docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
# 4.想追加一个命令 但是却发现报错了
[root@localhost dockerfile]# docker run cmdtest -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
#CMD的情况下 -l 替换了 CMD ["ls","-a"]命令 -l 不是命令所以报错
测试ENTRYPOINT
# 1.dockefile文件
FROM centos
ENTRYPOINT ["ls","-a"]
# 2.构建CMD镜像
[root@localhost dockerfile]# docker build -f dockerfile-entrypoint-test -t myentrypoint .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 82fc907ae06a
Removing intermediate container 82fc907ae06a
---> 8ff38c6303ee
Successfully built 8ff38c6303ee
Successfully tagged myentrypoint:latest
# 3.启动CMD镜像 发现ls -a生效
[root@localhost dockerfile]# docker run myentrypoint
.
..
.dockerenv
bin
dev
etc
home
# 4.想追加一个命令 成功了
[root@localhost dockerfile]# docker run myentrypoint -l
total 0
drwxr-xr-x. 1 root root 6 Sep 6 18:24 .
drwxr-xr-x. 1 root root 6 Sep 6 18:24 ..
-rwxr-xr-x. 1 root root 0 Sep 6 18:24 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Sep 6 18:24 dev
drwxr-xr-x. 1 root root 66 Sep 6 18:24 etc
drwxr-xr-x. 2 root root 6 Nov 3 2020 home
#ENTRYPOINT的情况下 -l 追加了 ENTRYPOINT ["ls","-a"]命令 ls -al 是命令所以执行
通过测试可以看出:
- CMD和ENTRYPOINT都可以执行其中的命令
- 如果在运行的时候追加命令,CMD会报错,而ENTRYPOINT会将追加的命令拼接在其文件中的命令之后,并且会正常运行
6.6.实战Tomcat镜像
-
准备镜像文件 tomcat、jdk的压缩包
-
编写dockerfile文件 文件命名为`Dockerfile 就不需要-f去指定了 build会自动寻找这个文件
FROM centos:7 MAINTAINER xiao<1559567258@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u171-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-7.0.57.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_171 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-7.0.57 ENV CATALINA_BASH /usr/local/apache-tomcat-7.0.57 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-7.0.57/bin/startup.sh && tail -F /usr/local/apache-tomcat-7.0.57/bin/logs/catalina.out
-
构建镜像
[root@localhost build]# docker build -t diytomcat . Sending build context to Docker daemon 199.8MB Step 1/15 : FROM centos:7 ---> eeb6ee3f44bd Step 2/15 : MAINTAINER xiao<1559567258@qq.com> ---> Using cache ---> 3bce5ca94a90 Step 3/15 : COPY readme.txt /usr/local/readme.txt ---> 115843bac5c9 Step 4/15 : ADD jdk-8u171-linux-x64.tar.gz /usr/local/ ---> 70ca3087e85f Step 5/15 : ADD apache-tomcat-7.0.57.tar.gz /usr/local/ ---> 780d781b4de8 Step 6/15 : RUN yum -y install vim ---> Running in 4ebb343679ea Loaded plugins: fastestmirror, ovl Determining fastest mirrors
-
启动镜像
[root@localhost build]# docker run -d -p 9090:8080 --name xiaodetomcat -v /home/xiao/build/test:/usr/local/apache-tomcat-7.0.57/webapps/test -v /home/xiao/build/tomcatlogs/:/usr/local/apache-tomcat-7.0.57/logs diytomcat # 解释 第一个挂载是将webapps下的test映射到本地tomcat下的test -v /home/xiao/build/test:/usr/local/apache-tomcat-7.0.57/webapps/test # 解释 第二个挂载是将apache-tomcat-7.0.57下的日志映射到本地tomcat下的tomcatlogs -v /home/xiao/build/tomcatlogs/:/usr/local/apache-tomcat-7.0.57/logs
-
本地自测
-
访问测试
访问http://192.168.0.130:9090/ 可以看到成功的界面
-
发布项目(由于做了卷挂载 我们直接在本地编写项目就可以发布了)
在本地xiao/test文件夹下创建WEB-INF文件夹 在WEB-INF下编写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>
-
在xiao/test 下编写index.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.io.*,java.util.*, javax.servlet.*" %> <html> <head> <title>hello,eric</title> </head> <body> <h1>显示当前时间与日期</h1> <% Date date = new Date(); out.print( "<h2 align=\"center\">" +date.toString()+"</h2>"); %> </body> </html>
-
测试访问http://192.168.0.130:9090/test/
我们以后的开发步骤:需要掌握Dockerfile的编写 我们之后的一切都是使用docker镜像来发布运行
6.7.发布自己的镜像
Docker Hub
-
地址https://hub.docker.com/
-
注册账号 确定这个账号可以登录
-
登录服务器
# 使用docker login -u [用户名] 回车输入密码 [root@localhost test]# docker login -u xiaodockerhub Password: xxxxxxxxxxxxxxxxx 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 # 登陆成功
-
登录完毕后就可以提交上去镜像,就是一步 docker push
# 这里提交出现了错误,因为需要在diytomcat前面加上自己DockerHub的username [root@localhost build]# docker push diytomcat Using default tag: latest The push refers to repository [docker.io/library/diytomcat] 296ed9f2d49b: Preparing 8e201b5db1e3: Retrying in 3 seconds ac1c094ebd4b: Preparing fe4ff5b5da21: Preparing 174f56854903: Preparing denied: requested access to the resource is denied # 拒绝
- 一定要修改diytomcat的镜像名字为ericbooney/diytomcat 所以为了避免出现错误 在build的时候就要在名称前面加上自己docker hub的用户名
# 修改diytomcat为xiaodockerhub/diytomcat:1.0 也尽量带上版本号 [root@localhost build]# docker tag diytomcat xiaodockerhub/diytomcat:1.0 # 再次进行提交 可以看到成功提交 [root@localhost build]# docker push xiaodockerhub/diytomcat:1.0 The push refers to repository [docker.io/xiaodockerhub/diytomcat] 296ed9f2d49b: Pushed 8e201b5db1e3: Pushed ac1c094ebd4b: Pushed fe4ff5b5da21: Pushed 174f56854903: Pushed 1.0: digest: sha256:10372adfe32fda75b480e72363538a2785a3c5255d67c244472d8cb98eadc5e2 size: 1372
阿里云镜像服务上
-
登录阿里云
-
找到容器镜像服务
-
创建个人实例 (我已经创建过了)
-
创建一个命名空间(防止冲突 隔离)
- 创建容器对象
- 浏览阿里云
-
登陆阿里云服务器
# docker login --username=[用户名] registry.cn-beijing.aliyuncs.com 回车输入密码 [root@localhost build]# docker login --username=yaoxiao registry.cn-beijing.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 # 登录成功
-
生成镜像名字 + 版本号
# docker tag [imagesID] [名字]:[imagesTag] [root@localhost build]# docker tag 6686537a35ad registry.cn-beijing.aliyuncs.com/xiao-namespace/xiao-repository:1.0 [root@localhost build]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE xiaodockerhub/diytomcat 1.0 6686537a35ad 2 hours ago 842MB registry.cn-beijing.aliyuncs.com/xiao-namespace/xiao-repository 1.0 6686537a35ad 2 hours ago 842MB
-
提交镜像
# docker push registry.cn-beijing.aliyuncs.com/xiao-namespace/xiao-repository:[镜像版本号] [root@localhost build]# docker push registry.cn-beijing.aliyuncs.com/xiao-namespace/xiao-repository:1.0 The push refers to repository [registry.cn-beijing.aliyuncs.com/xiao-namespace/xiao-repository] 296ed9f2d49b: Pushed 8e201b5db1e3: Pushed ac1c094ebd4b: Pushed fe4ff5b5da21: Pushed 174f56854903: Pushed 1.0: digest: sha256:10372adfe32fda75b480e72363538a2785a3c5255d67c244472d8cb98eadc5e2 size: 1372
-
推送镜像成功 阿里云查看
小结
7.Docker网络
7.1.理解网络
三个网络
问题:docker是如何处理容器网络访问的?
# 启动一个镜像
[root@localhost ]# docker run -d -P --name tomcat01 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
0e29546d541c: Pull complete
9b829c73b52b: Pull complete
cb5b7ae36172: Pull complete
6494e4811622: Pull complete
668f6fcc5fa5: Pull complete
dc120c3e0290: Pull complete
8f7c0eebb7b1: Pull complete
77b694f83996: Pull complete
0f611256ec3a: Pull complete
4f25def12f23: Pull complete
Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Status: Downloaded newer image for tomcat:latest
09f55246d8bcb638fe4eab079f9a220b8e0de68703ca61a049f4787e007fb349
Docker查找容器ip报错
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip addr": executable file not found in $PATH: unknown
解决方案:
#进入容器内部执行apt-get update
[root@aliyun ~]# docker exec -it tomcat /bin/bash
root@1a8bddcb0fdd:/usr/local/tomcat# apt-get update
Hit:1 http://security.debian.org/debian-security bullseye-security InRelease
Get:2 http://deb.debian.org/debian bullseye InRelease [116 kB]
Hit:3 http://deb.debian.org/debian bullseye-updates InRelease
# apt install -y iproute2
root@1a8bddcb0fdd:/usr/local/tomcat# apt install -y iproute2
Reading package lists... Done
Building dependency tree... Done
# 查看容器的内部网络地址 ip addr 发现容器启动的是否会得到一个eth0@if5 ip地址 docker分配
[root@localhost ~]# docker exec -it tomcat 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
6: eth0@if7: <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通容器内部
[root@localhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.043 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.066 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.045 ms
# Linux可以ping通docker容器内部
原理
-
我们每启动一个docker容器 docker就会给docker容器分配一个ip 我们只要安装了docker 就会有一个网卡docker0桥接模式 使用的技术是**evth-pair技术 ** Linux宿主机的的docker0Ip地址和容器里Ip地址是同一个网段 所以可以ping通
再次测试ip addr 多了一对网卡
-
再启动一个容器测试 发现又多了一对网卡
-
再启动一个tomcat
# 查看容器的内部网络地址 ip addr [root@localhost ~]# docker exec -it tomcat ip addr
- 发现又多了一个 Ip
# 我们发现这些网卡都是一对对的
# veth-pair 就是一对的虚拟设备接口 它们都是成对出现的 一段连着协议 一段彼此相连
# 正因为有这个特性veth-pair充当一个桥梁 连接各种虚拟网络设备
# OpenStack Docker容器之间的连接 OVS的连接 都是使用veth-pair技术
-
测试tomcat01 ping tomcat02 是否可以ping通
# 容器内没有ping的命令需要自己添加 apt-get update root@5935436df8be:/usr/local/tomcat# apt-get update Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB] Get:2 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB] Get:3 http://security.debian.org/debian-security bullseye-security InRelease [48.4 kB] Get:4 http://deb.debian.org/debian bullseye/main amd64 Packages [8182 kB] Get:5 http://security.debian.org/debian-security bullseye-security/main amd64 Packages [182 kB] Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [2596 B] Fetched 8574 kB in 4min 7s (34.8 kB/s) Reading package lists... Done # 添加ping命令 apt-get install iputils-ping root@82eb94a7bf7e:/usr/local/tomcat# apt-get install iputils-ping Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed:iputils-ping 0 upgraded, 1 newly installed, 0 to remove and 48 not upgraded. Unpacking iputils-ping (3:20210202-1) ... Setting up iputils-ping (3:20210202-1) ...
# 我们发现两个容器之间可以ping通
[root@localhost ~]# 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.086 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.048 ms
绘制一个网络模型图:
结论:
-
tomcat01和tomcat02是共用的一个路由器 docker0
-
tomcat01并不是直接ping tomcat02而是通过 docker0 进行广播或者去docker0路由表里面找tomcat02的ip地址
-
所有的容器在不指定网络的情况下 都是由docker0路由的 docker会给我们的容器分配一个默认的可用Ip
小结
- Docker使用的是Linux桥接 宿主机中是一个Docker容器的网桥 docker0
-
Docker中所有的网络接口都是虚拟的 虚拟的转发效率比较高(内网传递文件)
-
只要容器删除 对应的网桥就没了
7.2.--link
思考一个场景,我们编写了一个微服务,database url=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以通过名字来访问容器?
-
# tomcat01 ping tomcat02 通过域名是否可以ping通 [root@localhost /]# docker exec -it tomcat01 ping tomcat02 ping: tomcat02: Name or service not known
-
# 如何解决呢? [root@localhost ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat # 通过域名ping通方法:启动tomcat03 并且加上 --link 再次ping发现可以ping通 [root@localhost /]# 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.092 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.084 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.081 ms
-
# 反向的连接可以ping通吗 [root@localhost /]# docker exec -it tomcat02 ping tomcat03 ping: tomcat03: Name or service not known # 因为tomcat02没有配置 --link #我们发现不可以
-
# 通过docker network ls 找到桥接的Id 通过桥接Id 查网络详细信息 [root@localhost /]# docker network ls NETWORK ID NAME DRIVER SCOPE d8c099900403 bridge bridge local 4c7a93e7f4f3 host host local a607863d78f7 none null local
-
# 通过docker network inspect d8c099900403 查看到镜像启动的时候都是docker0随机分配的地址 [root@localhost /]# docker network inspect d8c099900403 [ { "Name": "bridge", "Id": "d8c099900403ea6b2cc65be5a605fe6f858e56740ef1db58b08a09b7140cf962", "Created": "2022-09-08T16:42:16.282036189+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" } ] }
-
其实这个tomcat03就是本地配置了tomcat02的配置
# 查看一下tomcat03的hosts的配置 [root@localhost /]# 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.3 tomcat02 5d2e2ec20d90 172.17.0.4 6521f824223c
-
本质探究:-–link就是我们在hosts配置中增加了一个172.17.0.3 tomcat02 5d2e2ec20d90
-
我们现在 玩Docker已经不建议使用–link了
-
自定义网络 不适用于docker0
-
dcoker0问题:他不支持容器名连接访问!
7.3.自定义网络
查看所有的docker网络
docker network ls
网络模式
-
bridge:桥接 docker(默认 自己创建的也是使用bridge模式)
-
none:不配置网络
-
host:和宿主机共享网络
-
container:容器内网络连通(用的少 局限很大)
测试
# 我们直接启动的命令 --net bridge 而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点:默认 域名不能访问 --link可以打通连接
# 我们可以自定义一个网络
# -d bridge # 桥接
# --subnet 192.168.0.0/16 # 子网
# --gateway 192.168.0.1 # 网关
[root@localhost ~]# docker network create -d bridge --subnet 192.168.1.1/16 --gateway 192.168.1.0 mynet
08a4a83e77b441c97aca4b65ff98c6cea6d5c23d7960a00c5300b8dde611e957
# 查看创建的网络 docker network ls
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a57903d80dfc bridge bridge local
4c7a93e7f4f3 host host local
08a4a83e77b4 mynet bridge local
a607863d78f7 none null local
# 查看创建的网络详细信息
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "08a4a83e77b441c97aca4b65ff98c6cea6d5c23d7960a00c5300b8dde611e957",
"Created": "2022-09-08T18:18:58.3257889+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.1.1/16",
"Gateway": "192.168.1.0"
}
]
}
# 启动两个容器
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
7487eb49042828dabe42a5a2dbc3ef216a827fbee261604522b1b311974834c6
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
a573e94e493a90dcbc4fe5655219873a858ef083beb7393e283c820f4481fff1
# 查看创建的网络里是否包含了 tomcat-net-01和tomcat-net-02
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "08a4a83e77b441c97aca4b65ff98c6cea6d5c23d7960a00c5300b8dde611e957",
"Created": "2022-09-08T18:18:58.3257889+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.1.1/16",
"Gateway": "192.168.1.0"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7487eb49042828dabe42a5a2dbc3ef216a827fbee261604522b1b311974834c6": {
"Name": "tomcat-net-01",
"EndpointID": "33974acf020a53a54d5708c722f4ced3175fa467696fe1f86ce94b1c508db11f",
"MacAddress": "02:42:c0:a8:00:01",
"IPv4Address": "192.168.0.1/16",
"IPv6Address": ""
},
"a573e94e493a90dcbc4fe5655219873a858ef083beb7393e283c820f4481fff1": {
"Name": "tomcat-net-02",
"EndpointID": "0c311ea5fdc65f2b7d405fcdcb83533ec7d83f47182c5e86398b751277b01e58",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 再次测试ping连接
[root@localhost /]# 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.102 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.076 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=0.081 ms
64 bytes from 192.168.0.2: icmp_seq=5 ttl=64 time=0.075 ms
# 现在不需要使用--link也可以ping名字了!
[root@localhost /]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from tomcat-net-02.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from tomcat-net-02.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from tomcat-net-02.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.075 ms
64 bytes from tomcat-net-02.mynet (192.168.0.2): icmp_seq=5 ttl=64 time=0.050 ms
小结:我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐使用这个网络
好处:
-
redis - 不同集群使用不同的网络 保证集群是健康和安全的
-
mysql - 不同集群使用不同的网络 保证集群是健康和安全的
7.3.1.网络连通
# 查看怎么连通
[root@localhost /]# docker network --helo
# 查看connect 命令怎么使用
[root@localhost /] docker network connect --help
# 测试打通 tomcat01 -> mynet
[root@localhost ~]# docker network connect mynet tomcat01
# 连通之后将tomcat01放到了mynet网络下
# 一个容器两个ip地址 阿里云服务:公网ip 私网ip
# 测试tomcat01 ping tomcat-net-01 是否可以ping通
[root@localhost /]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.1) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.1): icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from tomcat-net-01.mynet (192.168.0.1): icmp_seq=2 ttl=64 time=0.092 ms
64 bytes from tomcat-net-01.mynet (192.168.0.1): icmp_seq=3 ttl=64 time=0.083 ms
64 bytes from tomcat-net-01.mynet (192.168.0.1): icmp_seq=4 ttl=64 time=0.075 ms
# tomcat02 和tomcat-net-01是否可以ping通
[root@localhost /]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
结论:如果需要跨网络操作别人 就需要使用docker network connect
进行连通
7.4.实战:部署Redis集群
shell脚本
# 创建网卡
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
# 运行6个节点
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
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
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
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
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
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
# 创建集群
/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[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: ebfbbc88a83fa84c3d73fe048fc37ab82841fa0e 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: ed7bac9d22ce436c650f9a51c3ae7a3aa84a7537 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 2f1fdb553165c31c599f5cdbac5a42fa15901602 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: d2edadd37c2b243ffa3a13ac7bb352062160f4b8 172.38.0.14:6379
replicates 2f1fdb553165c31c599f5cdbac5a42fa15901602
S: 98bec4772bd3cdc7335111f75bc3f6b6ad2fae26 172.38.0.15:6379
replicates ebfbbc88a83fa84c3d73fe048fc37ab82841fa0e
S: 6e8dda893836d8182af1a7cbe0ff71b32d0743ef 172.38.0.16:6379
replicates ed7bac9d22ce436c650f9a51c3ae7a3aa84a7537
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: ebfbbc88a83fa84c3d73fe048fc37ab82841fa0e 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 98bec4772bd3cdc7335111f75bc3f6b6ad2fae26 172.38.0.15:6379
slots: (0 slots) slave
replicates ebfbbc88a83fa84c3d73fe048fc37ab82841fa0e
S: d2edadd37c2b243ffa3a13ac7bb352062160f4b8 172.38.0.14:6379
slots: (0 slots) slave
replicates 2f1fdb553165c31c599f5cdbac5a42fa15901602
S: 6e8dda893836d8182af1a7cbe0ff71b32d0743ef 172.38.0.16:6379
slots: (0 slots) slave
replicates ed7bac9d22ce436c650f9a51c3ae7a3aa84a7537
M: 2f1fdb553165c31c599f5cdbac5a42fa15901602 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: ed7bac9d22ce436c650f9a51c3ae7a3aa84a7537 172.38.0.12:6379
slots:[5461-10922] (5462 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.
docker搭建redis集群完成
我们使用了docker后,所有技术都会变得更加方便
8.IDEA整合Dockers
创建项目
-
架构springboot项目
-
打包应用
- 编写dockerfile(idea中安装docker插件比较方便)
- 将jar包和Dockerfile文件传输到Linux服务器上
-
# 构建镜像xiao666 [root@localhost idea]# docker build -t xiao666 . Sending build context to Docker daemon 17.66MB Step 1/5 : FROM java:8 ---> d23bdf5b1b1b Step 2/5 : COPY *.jar /app.jar ---> 3b4ebe0fcd41
-
# 发布运行 [root@localhost idea]# docker run -d -P --name xiao-springboot-web xiao666 . 3db41b0b9a9ec44f15c57e891380b0fbed580ecd949bccaf757fc5a1d8ad9598
-
# 本地测试 [root@localhost idea]# curl localhost:49167/hello Hello,Xiao[root@localhost idea]#
-
浏览器测试 浏览器测试如果没有加跨域注解是访问失败的
以后我们使用了Docker之后 给别人交互的就是一个镜像即可
Docker进阶篇
1.Docker Compose
1.1.简介
DockerFile build run 单个容器
Docker Compose 来轻松高效的管理容器->批量运行编排多个容器
Compose 是Docker 官方开源项目 需要安装
官方介绍:
定义 运行多个容器
yaml file 配置文件
Compose是一个用于定义和运行多容器Docker应用程序的工具 使用Compose 您可以使用一个YAML文件来配置应用程序的服务 然后使用一个single command命令创建并启动配置中的所有服务 要了解Compose的所有特性的更多信息 请参阅特性列表
所有环境都可使用Compose
在所有环境中组合工作:生产阶段开发测试以及CI工作流 您可以在常用用例中了解更多关于每个用例的信息
三步骤:
使用Compose基本上有三个步骤:
用Dockerfile定义你的应用环境 这样它就可以在任何地方被复制
- Dockerfile 保证我们的项目可以在任何地方运行
在docker-compose中定义组成应用程序的服务 所以它们可以在一个孤立的环境中一起运行
services: 容器、应用
docker-compose.yml
运行docker compose, docker compose命令将启动并运行你的整个应用程序 你也可以使用docker-compose二进制文件运行docker-compose
- 启动项目
作用:批量容器编排
我自己的理解
Compose
是Docker官方的开源项目 需要安装
Dockerfile
让程序在任何地方运行
Compose
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
Compose: 重要的概念
- 服务services 容器 应用 (web redis mysql…)
- 项目project 一组关联的容器
1.2.安装
卸载 sudo rm /usr/local/bin/docker-compose
-
下载
# 不建议用官方地址 非常慢 而且版本太高不稳定 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 这个可能快点 curl -L https://dn-dao-github-mirror.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
-
授权
sudo chmod +x /usr/local/bin/docker-compose
1.3.体验
- 应用 app.py
- Dockerfile 应用打包为镜像
- Docker-compose.yaml (定义整个服务、需要的环境:web、redis)
- python计数器应用
1.3.1.快速开始
-
应用app.py
# 创建一个文件夹 mkdir composetest # 进入这个文件夹 cd composetest
-
创建
app.py
文件[root@localhost home]# vim app.py # 文件内容 import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) if __name__ == "__main__": app.run(host="0.0.0.0",debug=True)
-
创建
requirements.txt
文件[root@localhost composetest]# vim requirements.txt # 文件内容 flask redis
-
创建
Dockerfile
文件[root@localhost composetest]# vim Dockerfile # 文件内容 FROM python:3.6-alpine ADD . /code WORKDIR /code RUN pip install -r requirements.txt CMD ["python","app.py"] # 这告诉 Docker: # 从Python 3.6-alpine映像开始构建ying'xiang # 将当前目录添加到./code映像中的路径中 # 将工作目录设置为 /code # 安装Python依赖项 # 将容器的命令设置为python app.py
-
Docker-compose.yaml文件(定义整个服务于,需要的环境,web、redis)
# 创建一个docker-compose.yaml文件 [root@localhost composetest]# vim docker-compose.yaml # 文件内容 version: "3.3" services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine" # 此Compose文件定义了两个服务 web和redis # 该web服务使用从Dockerfile当前目录中构建的镜像 # 将容器上的公开端口5000转发到主机上的端口5000 # 我们使用Flask web服务器的默认端口5000 # 该redis服务使用从DockerHub注册表中提取的公共Redis映像
-
在当前文件下启动docker-compose up
[root@192 composetest]# docker-compose up Creating network "composetest_default" with the default driver Building web Step 1/10 : FROM python:3.7-alpine # ... Successfully built f34d94accbfe # 成功built Successfully tagged composetest_web:latest # ... redis_1 | 1:C 05 Feb 2022 03:43:44.272 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started redis_1 | 1:C 05 Feb 2022 03:43:44.272 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf redis_1 | 1:M 05 Feb 2022 03:43:44.274 * monotonic clock: POSIX clock_gettime redis_1 | 1:M 05 Feb 2022 03:43:44.275 * Running mode=standalone, port=6379. # redis 端口6379 # ... redis_1 | 1:M 05 Feb 2022 03:43:44.275 * Ready to accept connections web_1 | * Serving Flask app 'app.py' (lazy loading) # Flask app 'app.py web_1 | * Environment: production web_1 | Use a production WSGI server instead. web_1 | * Debug mode: off web_1 | * Running on all addresses. # 警告:这是一个开发服务器。不要在生产部署中使用它。 web_1 | WARNING: This is a development server. Do not use it in a production deployment. web_1 | * Running on http://172.18.0.2:5000/ (Press CTRL+C to quit) # Flask网页运行成功 web_1 | 192.168.64.1 - - [05/Feb/2022 03:45:00] "GET / HTTP/1.1" 200 - # 访问常规
# 服务启动成功 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 16036f07b287 redis:alpine "docker-entrypoint.s…" 31 minutes ago Up 13 minutes 6379/tcp composetest_redis_1 8e2f95d3f13c composetest_web "python app.py" 31 minutes ago Up 13 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp composetest_web_1 # 测试服务是否正常 [root@localhost ~]# curl localhost:5000 Hello World! I have been seen 1 times. [root@localhost ~]# curl localhost:5000 Hello World! I have been seen 2 times. [root@localhost ~]# curl localhost:5000 Hello World! I have been seen 3 times. [root@localhost ~]# curl localhost:5000
# 查看运行容器和下载的镜像
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16036f07b287 redis:alpine "docker-entrypoint.s…" 36 minutes ago Up 18 minutes 6379/tcp composetest_redis_1
8e2f95d3f13c composetest_web "python app.py" 36 minutes ago Up 18 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp composetest_web_1
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
composetest_web latest 3c2fcb7d9c91 36 minutes ago 55.5MB
<none> <none> 7c0401c80946 2 hours ago 41.8MB
redis alpine 3900abf41552 9 months ago 32.4MB
python 3.6-alpine 3a9e80fa4606 9 months ago 40.7MB
python 3.7-alpine a1034fd13493 9 months ago 41.8MB
hello-world latest feb5d9fea6a5 11 months ago 13.3kB
composetest_web_1 默认服务名:
文件名_服务名_num
多个服务器 集群 _num 代表 副本数量
集群状态 服务都不可能只有一个运行实例 弹性 高可用
kubectl service 负载均衡
# docker-compose.yaml文件
version: "3"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
# 根据docker-compose.yaml自动生成了两个服务:
1. web(网络服务)
2. redis服务
# 该服务使用从 Docker Hub 注册表中提取的公共 Redis 映像
# 1.版本问题version
# 2.version版本不要填太高
docker-compose步骤:
1.应用 app.py
2.创requirements.txt文件
3.Dockefile 应用打包为镜像
4.docker-compose.yaml文件(定义整个服务需要的环境 web redis) 完整的上线服务
5.启动docker-compose项目(docker-compose up)
docker-compose up启动流程:
1.创建网络
2.执行Docker-compose yaml
3.启动服务
最终上线了两个项目:
- Creating composetest_web_1 … done
- Creating composetest_redis_1 … done
1.3.2网络
网络
-
网络规则
# 查看网络 docker network ls [root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 75c8249cf43b bridge bridge local 109bac1879eb composetest_default bridge local 08092ffccab6 host host local cb9aae29a8ef none
运行10个服务打包为一个完整项目Compose自动维护了一个网络(项目中的内容都在同一个网络下 可以通过域名访问)
# 查看网络详细 docker network inspect composetest_default [root@localhost ~]# docker network inspect composetest_default "Containers": { "16036f07b287b0bfa28413692d04a60b15eb69d7518c480f3097c3822c7eb393": { "Name": "composetest_redis_1", "EndpointID": "da457e336dd031a4d62b739fb608752d614755930ef5bd4f7e39d7d82bce15bd", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" }, "8e2f95d3f13c32a87d791965f1821e0324eea13f86a6c0c1a869aa0781964bf8": { "Name": "composetest_web_1", "EndpointID": "c9206af0c98883cfa6bc3001e8d445c696aa0d929bbdf8c6076adcc1d36a095d", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } } # 如果在同一个网络下 可以通过域名进行访问
# 停止命令 docker-compose down # 方式一: # docker-compose down # 方式二: # Ctrl + c
- docker run单个容器启动
- docker-compose通过docker-compose编写yaml配置文件 可以通过compose一键启动所有服务 停止
Docker小结:
1.Docker镜像 通过run启动容器
2.DockerFile构建镜像(服务打包)
3.docker-compose启动项目(编排 多个微服务/环境)
4.Docker网络
1.4.yaml 规则
docker-compose.yaml 核心
# 总共三层
version: '' # 版本
services: #服务
服务1: web
# 服务配置
images:
port:
network:
depends_on: # 启动依赖(顺序)
...
服务2: redis
...
# 其他配置 网络 卷 全局规则
volumes:
network:
confits:
1.5.实战
1.6.实战开源项目-WordPress
- 下载项目
- 如果需要自己的镜像,可以自定义 Dockerfile
- 编写docker-compose.yaml
- docker-compose up -d 后台启动
- 使用Compose一键部署WP博客
- 自己编写微服务上线
开源项目(博客)
-
# 下载项目 我这个项目是官方的 [root@localhost my_wordpress]# mkdir my_wordpress
-
# 进入这个文件夹 [root@localhost my_wordpress]# cd my_wordpress/
-
# 创建一个文件 [root@localhost my_wordpress]# vim docker-compose.yml # 文件内容 services: db: image: mariadb:10.6.4-focal command: '--default-authentication-plugin=mysql_native_password' volumes: - db_data:/var/lib/mysql restart: always environment: - MYSQL_ROOT_PASSWORD=somewordpress - MYSQL_DATABASE=wordpress - MYSQL_USER=wordpress - MYSQL_PASSWORD=wordpress expose: - 3306 - 33060 wordpress: image: wordpress:latest ports: - 80:80 restart: always environment: - WORDPRESS_DB_HOST=db - WORDPRESS_DB_USER=wordpress - WORDPRESS_DB_PASSWORD=wordpress - WORDPRESS_DB_NAME=wordpress volumes: db_data:
-
启动项目
-
访问测试:
实战微服务
-
编写微服务
package com.xiao.dockercloud.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @Classname 测试 * @Description TODO * @Date 2022/9/9 23:59 * @Created by ylp */ @RestController public class HelloController { @Autowired private StringRedisTemplate redisTemplate; @GetMapping("/hello") public String hello(){ Long views = redisTemplate.opsForValue().increment("views"); return "Hello Xiao Thank You Views"+views; } }
-
dockerfile 构建镜像
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
-
docker-compose 编排项目
version: '3.3' services: xiaoapp: build: . image: xiaoapp depends_on: - redis ports: - "8080:8080" redis: image: "library/redis:alpine"
-
docker-compose up --build
# 启动项目并且部署 [root@localhost xiaoapp]# docker-compose up --build Creating network "xiaoapp_default" with the default driver Building xiaoapp
-
本地自测 浏览器自测:
# 本地自测 浏览器自测: [root@localhost ~]# curl localhost:8080/hello Hello Xiao Thank You Views1[root@localhost ~]# curl localhost:8080/hello Hello Xiao Thank You Views2[root@localhost ~]# curl localhost:8080/hello Hello Xiao Thank You Views3[root@localhost ~]# curl localhost:8080/hello Hello Xiao Thank You Views4[root@localhost ~]# curl localhost:8080/hello Hello Xiao Thank You Views5[root@localhost ~]# curl localhost:8080/hello
小结:
- Docker Compose 是一个开源项目 用来统一编排多个应用的
- 多个应用 多个服务 => 这些应用都会在同一个网络下 => 可通过域名直接访问
- 默认的服务名为:文件夹名称_镜像名_副本数量(运行数量)
- Dockerfile 用于构建镜像 docker-compose.yaml 用于编排项目 同时组装多个应用
- docker-compose.yaml 文件结构总共三层
- docker compose版本
- 服务
- 服务的属性
- 其他配置
- 如何使用:
- 准备好项目并编写 Dockerfile(可省略 如果直接使用仓库镜像的话)
- 编写docker-compose.yaml
- 在当前目录(docker-compose.yaml文件所在目录)运行 docker-compose up 停止 docker-compose down
2.Docker Swarm
工作模式
搭建集群
$ docker swarm --help
Usage: docker swarm COMMAND
Manage Swarm
Commands:
ca # Display and rotate the root CA
init # 初始化一个Swarm
join # 加入一个集群作为一个节点 和/或 管理者
join-token # 管理生成的令牌
leave # 离开swarm
unlock # 解锁swarm
unlock-key # 解锁密钥管理
update # 更新swarm
$ docker swarm init --help
-
设置主节点(192.168.0.131)
# 初始化节点 [root@localhost /]# docker swarm init --advertise-addr 192.168.0.131 # Swarm初始化: 当前节点(...)现在是一个manager(管理节点)。 Swarm initialized: current node (wee6ow9y9nqk4ztn8xcla4309) is now a manager. # 翻译:要添加一个worker(工作节点)到这个swarm,运行以下命令(令牌) To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-3l5b0p89d3o87cm3khemqeignks4bgdx08jey90apd1icvfvpf-9zzk6l53ehjwv4ru3sy9zc8qm 192.168.0.131:2377 # 翻译:要添加一个swarm(管理节点)到swarm,运行'docker swarm join-token manager', To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
-
生成令牌(管理生成的令牌)
# 生成管理节点的令牌 $ docker swarm join-token manager # 生成工作节点的令牌 $ docker swarm join-token worker
-
将docker-2加入工作节点
# 添加一个工作节点的命令 [root@localhost /]# docker swarm join --token SWMTKN-1-3l5b0p89d3o87cm3khemqeignks4bgdx08jey90apd1icvfvpf-9zzk6l53ehjwv4ru3sy9zc8qm 192.168.0.131:2377 This node joined a swarm as a worker. # 成功变为工作节点
-
查看所有节点信息
[root@localhost /]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 9u4hvly7d9c0kwg7era50iwwn localhost.localdomain Ready Active 20.10.17 wee6ow9y9nqk4ztn8xcla4309 * localhost.localdomain Ready Active Leader 20.10.17
-
将docker-3加入工作节点
# 添加一个工作节点的命令 [root@localhost /]# docker swarm join --token SWMTKN-1-3l5b0p89d3o87cm3khemqeignks4bgdx08jey90apd1icvfvpf-9zzk6l53ehjwv4ru3sy9zc8qm 192.168.0.131:2377 This node joined a swarm as a worker. # 成功变为工作节点
# 查看所有节点信息 [root@localhost /]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 9u4hvly7d9c0kwg7era50iwwn localhost.localdomain Ready Active 20.10.17 qhjnsfh7mekxr6rgo4j3yfaxv localhost.localdomain Ready Active 20.10.17 wee6ow9y9nqk4ztn8xcla4309 * localhost.localdomain Ready Active Leader 20.10.17
-
将docker-4加入管理节点
# 生成管理节点的令牌 [root@localhost /]# docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-3l5b0p89d3o87cm3khemqeignks4bgdx08jey90apd1icvfvpf-3mpf1d2rbbjzpl7ky02qxbwa0 192.168.0.131:2377 # 加入管理节点 [root@localhost ~]# docker swarm join --token SWMTKN-1-3l5b0p89d3o87cm3khemqeignks4bgdx08jey90apd1icvfvpf-3mpf1d2rbbjzpl7ky02qxbwa0 192.168.0.131:2377 This node joined a swarm as a manager. # 成功变为管理节点
-
# 查看所有节点信息 [root@localhost /]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 9u4hvly7d9c0kwg7era50iwwn localhost.localdomain Ready Active 20.10.17 i01kql67nqpayyic6i95z8aqo localhost.localdomain Ready Active Reachable 20.10.17 qhjnsfh7mekxr6rgo4j3yfaxv localhost.localdomain Ready Active 20.10.17 wee6ow9y9nqk4ztn8xcla4309 * localhost.localdomain Ready Active Leader 20.10.17
-
移除节点
# 从swarm中删除一个节点 | -f 删除多个节点 $ docker node rm 节点id [root@localhost /]# docker node rm 6rdhf93we35s9pjlmj73tubta # 管理节点自己离开 $ docker swarm leave --force [root@192 ~]# docker swarm leave --force Node left the swarm.
2.1.Raft一致性协议了解
双主双从 => 假设一个节点挂了 其他节点是否可用 不可用
Raft协议:保证大多数节点存活才可用
- 三个管理器的群体最多可以容忍一个管理器的损失
- 一个五管理器群可以容忍最大同时丢失两个管理器节点
- 一个N管理器集群最多可以容忍管理器的丢失 (N-1)/2
- Docker 建议一个群最多有七个管理器节点
ps:manager 节点不是越多越好
- 三个manager节点 停止一个manager之后仍可用
- 三个manager节点 停止两个manager之后不可用
实验:
-
[root@localhost /]# systemctl docker [root@localhost /]# docker node ls # 日志含义可能在线的managers太少了 确保半数以上的managers在线 Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
-
将某一个worker节点离开,仍可用
[root@localhost /]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION iz6uklv45q2n3m9k698h2zurf localhost.localdomain Down Active 20.10.17 om92u8zv81jgw8aey7gdixhrs localhost.localdomain Ready Active Reachable 20.10.17 y4o5cy31v386te7n0as513st6 localhost.localdomain Ready Active Reachable 20.10.17 yfx4k4z9h653fvrzaggt2p83j * localhost.localdomain Ready Active Leader 20.10.17
-
work节点不能查看节点信息 仅用来工作,命令只能在manager(管理节点)上执行
[root@localhost /]# docker node ls # 来自daemon的错误响应:这个节点不是一个集群管理器 # 工作节点不能用于查看或修改集群状态 # 请在管理节点上执行此命令或将当前节点提升为管理节点 Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
2.2.Swarm集群弹性创建服务
扩缩容功能 创建服务 动态扩展服务 更新服务 日志 灰度发布(更新网站(服务)时依旧提出服务 不挂404)
功能:扩缩容功能(扩容:增加容器 缩容:减少容器)灰度发布
目的:创建 nginx 服务 动态扩展服务 动态更新服务
[root@192 ~]# docker service --help
Usage: docker service COMMAND
Manage services
Commands:
create # 创建一个新服务
inspect # 显示一个或多个服务的详细信息
logs # 获取服务或任务的日志
ls # 服务列表
ps # 列出一个或多个服务的任务
rm # 删除一个或多个服务
rollback # 回滚恢复对服务配置的更改
scale # 扩展扩展一个或多个复制业务
update # 更新服务
-
创建服务(docker-1)
以前是docker run(单机),现在是 docker service (集群)
[root@localhost /]# docker service create -p 9999:80 --name xiao-nginx nginx lnhsiqaadct5mfl2yo52e84sv overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged # 启动成功 # 理解: # docker run 容器启动 不具有扩缩容 不具有滚动更新 # docker service 服务启动 具有扩缩容 具有滚动更新
-
查看服务(docker-1)
[root@localhost /]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS lnhsiqaadct5 xiao-nginx replicated 1/1 nginx:latest *:9999->80/tcp # REPLICAS副本只有一个 说明在集群中只存在一个 # 虽然是在docker-1机器上创建的 但也有可能跑在其他机器上
-
动态扩缩容 扩容到3个副本 集群中的任意节点都可访问 实现高可用
[root@localhost /]# docker service update --replicas 3 xiao-nginx xiao-nginx overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged
查看扩容是否成功
[root@localhost /]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS lnhsiqaadct5 xiao-nginx replicated 3/3 nginx:latest *:9999->80/tcp # 成功
查看分配到哪个机器
-
动态扩容(scale 同 updata)
[root@localhost /]# docker service scale xiao-nginx=10 xiao-nginx scaled to 10 overall progress: 10 out of 10 tasks 1/10: running [==================================================>] 2/10: running [==================================================>] 3/10: running [==================================================>] 4/10: running [==================================================>] 5/10: running [==================================================>] 6/10: running [==================================================>] 7/10: running [==================================================>] 8/10: running [==================================================>] 9/10: running [==================================================>] 10/10: running [==================================================>] verify: Service converged
查看扩容是否成功
[root@localhost /]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS lnhsiqaadct5 xiao-nginx replicated 10/10 nginx:latest *:9999->80/tcp # 成功
查看分配到哪个机器
-
测试访问
-
动态缩容 回滚到1个
[root@localhost /]# docker service scale xiao-nginx=1 xiao-nginx scaled to 1 overall progress: 1 out of 1 tasks 1/1: error creating external connectivity network: Failed to Setup IP tables: U… verify: Service converged
查看缩容是否成功
[root@localhost /]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS lnhsiqaadct5 xiao-nginx replicated 1/1 nginx:latest *:9999->80/tcp # 成功
Swarm概念总结
- swarm
集群的管理和编号 docker可以初始化一个swarm集群 其他节点可以加入 (管理、工作者) - Node
就是一个docker节点 多个节点就组成了一个网络集群 (管理、工作者) - Service
任务,可以在管理节点或者工作节点来运行 核心 用户访问 - Task
容器内的命令 细节任务