1、安装Docker
# 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 \
http://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、启动decker
systemctl start docker
# 6、查看是否启动成功
docker version
# 7、下载镜像如:hello-world
docker run hello-world
# 8、查看一下下载的这个hello-world 镜像
了解:卸载docker
# 1、 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2、删除资源
rm -rf /var/lib/docker
# /var/lib/docker docker的默认工作路径!
2、阿里云镜像加速
1、登录阿里云找到容器服务
登录之后在搜索栏输入容器镜像服务 ,第一次进入需要开启服务
2、找到镜像加速地址
# 下图是我的镜像服务
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://pqp40fmp.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
3、Docker的常用命令
3.1、帮助命令
docker version # 显示docker的版本信息
docker indo # 显示docker的系统信息,包括镜像和容器的数量
docker --help # 帮助命令
3.2、镜像命令
docker images 查看所有本地的主机上的镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 12 months ago 13.3kB
# 解释
REPOSITORY # 镜像的仓库源
TAG # 镜像的标签
IMAGE ID # 镜像的id
CREATED # 镜像的创建时间
SIZE # 镜像的大小
# 可选项
-a, --all # 显示所有镜像
-q, --quiet # 只显示镜像id
docker search 搜索镜像
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10326 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3825 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 754 [OK]
percona Percona Server is a fork of the MySQL relati… 518 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 86
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 79
centurylink/mysql Image containing mysql. Optimized to be link… 60 [OK]
bitnami/mysql Bitnami MySQL Docker Image 47 [OK]
deitch/mysql-backup REPLACED! Please use http://hub.docker.com/r… 41 [OK]
tutum/mysql Base docker image to run a MySQL database se… 35
...
# 可选项 , 通过搜藏来过滤
--filter=STARS=3000
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
[root@localhost ~]# docker pull mysql
Using default tag: latest # 如果不写 tag, 默认就是latest
latest: Pulling from library/mysql
6ec7b7d162b2: Pull complete # 分层下载,docker iamge的核心 联合文件系统
fedd960d3481: Pull complete
7ab947313861: Pull complete
64f92f19e638: Pull complete
3e80b17bff96: Pull complete
014e976799f9: Pull complete
59ae84fee1b3: Pull complete
ffe10de703ea: Pull complete
657af6d90c83: Pull complete
98bfb480322c: Pull complete
6aa3859c4789: Pull complete
1ed875d851ef: Pull complete
Digest: sha256:78800e6d3f1b230e35275145e657b82c3fb02a27b2d8e76aac2f5e90c1c30873
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
6ec7b7d162b2: Already exists
fedd960d3481: Already exists
7ab947313861: Already exists
64f92f19e638: Already exists
3e80b17bff96: Already exists
014e976799f9: Already exists
59ae84fee1b3: Already exists
7d1da2a18e2e: Pull complete
301a28b700b9: Pull complete
529dc8dbeaf3: Pull complete
bc9d021dc13f: Pull complete
Digest: sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
[root@localhost ~]# docker rmi -f 镜像id # 删除指定的镜像
[root@localhost ~]# docker rmi -f 镜像id 镜像id 镜像id 镜像id 镜像id # 删除多个容器
[root@localhost ~]# docker rmi -f $(docker images -aq) # 删除全部的镜像
3.3、容器命令
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" # 容器名字 tomcat01 tomcat02, 用来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看类容
-p # 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
容器端口
-p # 随机指定端口
# 测试,启动并进入容器
[root@localhost ~]# docker run -it centos /bin/bash
[root@cf725551c40c /]# ls # 查看容器内的centos,基础版本,很多命令都是不完善的!
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
# 从容其中退回主机
[root@cf725551c40c /]# exit
exit
[root@localhost ~]# ls
anaconda-ks.cfg logs store 模板 图片 下载 桌面
initial-setup-ks.cfg nohup.out 公共 视频 文档 音乐
列出所有运行的容器
# docker ps 命令
# 列出当前正在运行的命令
-a # 列出当前正在运行的命令+带出历史运行过的容器
-n=? # 显示最近创建的容器
-q # 只显示容器的编号
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf725551c40c centos "/bin/bash" 5 minutes ago Exited (130) About a minute ago zen_franklin
4588b275660d bf756fb1ae65 "/hello" 2 hours ago Exited (0) 2 hours ago hopeful_hermann
退出容器
exit # 直接容器退出并退出
Ctrl + P + Q # 容器不停止退出
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q|xargs docker rm # 删除所有的容器
启动和停止容器的
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前容器
3.4、常用其他命令
后台启动容器
# 命令 docker run -d 镜像名
[root@localhost ~]# docker run -d centos
# 问题docker ps, 发现 centos 停止了
# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了
查看日志
docker logs -f -t --tail 容器,没有日志
# 自己编写一段shell脚本
[root@localhost /]# docker run -d centos /bin/sh -c "while true;do echo FlamingYouth; sleep 1;done"
# 显示id
[root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b4b7dca27aec centos "/bin/sh -c 'while t…" 8 seconds ago Up 7 seconds hardcore_kalam
# 显示日志
-tf # 显示日子
--tail # 要显示日志
[root@localhost /]# docker logs -tf --tail 10 b4b7dca27aec
查看容器中进程信息
# top命令
[root@localhost ~]# docker top b4b7dca27aec
UID PID PPID C STIME TTY TIME CMD
root 10809 10789 0 07:50 ? 00:00:01 /bin/sh -c while true;do echo FlamingYouth; sleep 1;done
root 16461 10809 0 08:57 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
# 命令
docker inspect 容器id
# 测试
[root@localhost ~]# docker inspect b4b7dca27aec
[
{
"Id": "b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529",
"Created": "2020-12-29T09:40:40.771199842Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo FlamingYouth; sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 10809,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-12-29T09:40:41.156505681Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529/hostname",
"HostsPath": "/var/lib/docker/containers/b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529/hosts",
"LogPath": "/var/lib/docker/containers/b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529/b4b7dca27aec2376338cbfd5656661fdf2cbc549635e2444eb6d6f1b3d630529-json.log",
"Name": "/hardcore_kalam",
"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/6ac692e899a9a6433423beb2cda55efb6589a7e590d38d6eafebc4cc6cc77fd6-init/diff:/var/lib/docker/overlay2/602b32ecf8fdc2ac30f177eae6e59852d1fad4ba4af81893ac8760c7ee806d53/diff",
"MergedDir": "/var/lib/docker/overlay2/6ac692e899a9a6433423beb2cda55efb6589a7e590d38d6eafebc4cc6cc77fd6/merged",
"UpperDir": "/var/lib/docker/overlay2/6ac692e899a9a6433423beb2cda55efb6589a7e590d38d6eafebc4cc6cc77fd6/diff",
"WorkDir": "/var/lib/docker/overlay2/6ac692e899a9a6433423beb2cda55efb6589a7e590d38d6eafebc4cc6cc77fd6/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "b4b7dca27aec",
"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 FlamingYouth; sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "f68852780deafa92a15e40851bbf4b8136a46a824bc10a1f0d10e1a0de66cefb",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/f68852780dea",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "d7025b7caff9b7fcec1f0e2e9e4205159db66224bcb08dfc4fccf14dce3e6920",
"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": "dfe4906e819a50a04f6bab4d013f712b90b0f1b1347794f978939fd20863605e",
"EndpointID": "d7025b7caff9b7fcec1f0e2e9e4205159db66224bcb08dfc4fccf14dce3e6920",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
进入当前正在运行的容器
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id bashShell
# 测试
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b4b7dca27aec centos "/bin/sh -c 'while t…" 15 hours ago Up 15 hours hardcore_kalam
[root@localhost ~]# docker exec -it b4b7dca27aec /bin/bash
[root@b4b7dca27aec /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Dec29 ? 00:00:01 /bin/sh -c while true;do echo FlamingYouth; s
root 4462 0 0 01:05 pts/0 00:00:00 /bin/bash
root 4486 1 0 01:05 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=s
root 4487 4462 0 01:05 pts/0 00:00:00 ps -ef
# 方式二
docker attach 容器id
#测试
[root@localhost ~]# docker attach b4b7dca27aec
正在执行当前的代码...
# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
# 查看当前主机目录下文件
[root@localhost home]# ls
flamingyouth FlamingYouth.java
[root@localhost home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8edc051860a centos "/bin/bash" About a minute ago Up About a minute youthful_wu
# 进入docker 容器内部
[root@localhost home]# docker attach d8edc051860a
[root@d8edc051860a /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@d8edc051860a /]# cd /home
[root@d8edc051860a home]# ls
# 在容器内新建一个文件
[root@d8edc051860a home]# touch test.java
[root@d8edc051860a home]# exit
exit
[root@localhost home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8edc051860a centos "/bin/bash" 2 minutes ago Exited (0) 8 seconds ago youthful_wu
# 将这文件拷贝出来到主机上
[root@localhost home]# docker cp d8edc051860a:/home/test.java /home
[root@localhost home]# ls
flamingyouth FlamingYouth.java test.java
# 拷贝是一个手动过程,未来我们使用-v 卷的技术,可以实现,自动同步 / home /home
3.5、小结
attach # 当前 shell 下 attach 连接指定运行镜像
build # 通过 Dockerfile 定制镜像
commit # 提交当前容器为新的镜像
cp # 从容期中考被指定文件或目录到宿主机中
create # 创建一个新的容器,同run,但不启动容器
difff # 查看 docker 容器变化
events # 从 docker 服务获取容器实时事件
exec # 在已存在的容器上运行命令
export # 导出容器的内容流作为一个 tar 归档文件[对应 import]
history # 展示一个镜像形成的历史
images # 列出系统当前镜像
import # 从 tar 包中的内容创建一个新的文件系统映像[对应export]
info # 显示系统相关信息
inspect # 查看容器详细信息
kill # kill 指定 docker 容器
load # 从一个 tar 包中加载一个镜像[对应 save]
login # 注册或登录一个 docker 源服务器
logout # 从当前 Docker registry 退出
logs # 输出当前容器日志信息
port # 查看映射端口对应的容器内部源端口
pause # 暂停容器
ps # 列出容器列表
pull # 从 docker 镜像源服务器拉取指定镜像或者库镜像
restart # 重启运行的容器
rm # 移除一个或者多个容器
rmi # 移除一个或者多个镜像[无容器使用该镜像才可以删除,否则需删除相关容器才可继续或 -f 强制删除]
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个 tar 包[对应 load]
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看 docker 版本号
wait # 截取容器停止时的退出状态值
3.6、作业练习
Docker 安装 Nginx
# 1、搜索镜像 search 建议大家去docker搜索,可以看到帮助文档
# 2、下载镜像 pull
# 3、运行测试
[root@localhost home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest ae2feff98a0c 2 weeks ago 133MB
centos latest 300e315adb2f 3 weeks ago 209MB
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
[root@localhost home]# docker run -d --name nginx01 -p 3344:80 nginx
WARNING: IPv4 forwarding is disabled. Networking will not work.
b462b3118b7f981cd5f731bafd71e952723c3763239e13ab9294da2b0dbd0758
[root@localhost home]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#进入容器
[root@localhost ~]# docker exec -it nginx02 /bin/bash
root@44e75fe5b85b:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@44e75fe5b85b:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@44e75fe5b85b:/# cd /etc/nginx
root@44e75fe5b85b:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
Docker 安装 tomcat
# 官方的使用
docker run -it -- rm tomcat:9.0
# 我们之前的启动都是后台,停止了容器之后,容器还是可以查到 docker run -it --rm, 一般用来测试,用完就删除
# 下载在启动
docker pull tomcat
# 启动运行
docker run -d -p 3344:8080 --name tomcat01 tomcat
# 测试访问没有问题
# 进入容器
[root@localhost ~]# docker exec -it tomcat01 /bin/bash
# 发现问题:1、liunx命令少了, 2、没有webapps 阿里云镜像原因,默认是最小的镜像
4、Docker镜像讲解
如何提交一个自己的镜像
4.1、commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名: [TAG]
4.2、实战测试
# 1、启动一个默认的tomcat
docker run -d --name=tomcat -p 8099:8080 tomcat
# 2、发现这个默认的tomcat 是没有webapps应用,镜像的原因,官方的镜像默认 webapps 下面是没有文件的!
# 3、我自己拷贝进去了基本的文件
cp -f webapps.sart/* webapps
# 4、将我们操作的容器通过commit提交为一个镜像! 我们以后就使用我们修改过的镜像即可
docker commit -m="提交者姓名" -a="作者" 容器id 目标镜像名:[TAG]
5、容器数据卷
5、1 什么是容器数据卷
总结一句话:容器的持久化和同步操作!荣期间也是可以数据共享的!
5.2、使用数据卷
方式一:直接使用命令来挂载
docker run -it -v 主机目录:容器内目录
# 测试
[root@localhost ~]# docker run -it -v /home/Test:/home centos /bin/bash
# 启动起来时候我们可以通过 docker inspect 容器id
"Mounts": [
{
"Type": "bind",
"Source": "/home/test",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
好处:以后修改只需要在本地修改即可,容器内会自动同步!
5.3、实战:安装MySQL
思考:MySQL的数据持久化的问题
# 获取镜像
[root@localhost test]# docker pull mysql:5.7
# 运行容器,需要做数据挂载!
# 安装启动mysql , 需要配置密码,这是要注意点!
# 官方测试: 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 3340:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysq -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功之后,我们在本地使用 sqlyog 来接测试一下
# sqlyog-连接到服务器端3340 --- 3340 和容器内的 3306映射 连接成功
发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能
具名和匿名挂载
# 匿名挂载
-v 容器内路径!
docker run -d -P --name nginx01 -v /ect/nginx nginx
# 查看所有的 volume 的情况
[root@localhost ~]# docker run -d -P --name nginx03 -v /ect/nginx nginx
ca140c2539fa4d04b1f1ddd72c496237d863f21cd3054b0e9d64a1b815009805
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local 7a4e8691e5158cde8519a78809da1984d414149a198f2f387e277ae46e7062cb
# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
# 具名挂载
[root@localhost ~]# docker run -d -P --name nginx04 -v juming-nginx:/ect/nginx nginx
8e1f5fe09c1655314d6fdf1a2117baa0ef012d35ed141d285756dbc33e026123
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local 7a4e8691e5158cde8519a78809da1984d414149a198f2f387e277ae46e7062cb
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷
[root@localhost ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-12-31T15:51:20+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径::容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
ro redonly # 只读
rw readwrite # 可读可写
# 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -p --name nginx01 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的!
5.4、初始Dockerfile
Dockerfile 就是用来构建docker 镜像的构建文件!
通过如下脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,没一个命令都是一层
# 创建一个dockerfile文件 , 名字可以随机 建议 Dockerfile
# 文件中的内容 指令(大写) 参数
FORM centos
VOLUME ["volume01","volume02"] // 匿名挂载
CMD echo "----end------"
CMD /bin/bash
# 这里的每一个命令,就是镜像的一层
[root@localhost docker-test-volume]# docker build -f dockerfile1 -t flamingyouth/centos .
# 启动自己写的容器
[root@localhost docker-test-volume]# docker run -it 349e0438a482 /bin/bash
[root@d8eb91613a84 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x. 5 root root 360 Dec 31 08:40 dev
drwxr-xr-x. 1 root root 66 Dec 31 08:40 etc
drwxr-xr-x. 2 root root 6 Nov 3 15:22 home
lrwxrwxrwx. 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 15:22 media
drwxr-xr-x. 2 root root 6 Nov 3 15:22 mnt
drwxr-xr-x. 2 root root 6 Nov 3 15:22 opt
dr-xr-xr-x. 263 root root 0 Dec 31 08:40 proc
dr-xr-x---. 2 root root 162 Dec 4 17:37 root
drwxr-xr-x. 11 root root 163 Dec 4 17:37 run
lrwxrwxrwx. 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 15:22 srv
dr-xr-xr-x. 13 root root 0 Dec 31 01:03 sys
drwxrwxrwt. 7 root root 145 Dec 4 17:37 tmp
drwxr-xr-x. 12 root root 144 Dec 4 17:37 usr
drwxr-xr-x. 20 root root 262 Dec 4 17:37 var
# 这个目录就是我们生成镜像的时候自动挂载的,数据卷目录
drwxr-xr-x. 2 root root 6 Dec 31 08:40 volume01
drwxr-xr-x. 2 root root 6 Dec 31 08:40 volume02
这个卷和外部一定有同步目录
[root@localhost ~]# docker inspect d8eb91613a84
"Mounts": [
{
"Type": "volume",
"Name": "87e428701abb15e7078e477e9347e3efd6972b5607b7dec32948999e29dd3e68",
"Source": "/var/lib/docker/volumes/87e428701abb15e7078e477e9347e3efd6972b5607b7dec32948999e29dd3e68/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "dab549523735a7b0a3c334d1985ed1f67684b99d2eaccea2ec9085f732934699",
"Source": "/var/lib/docker/volumes/dab549523735a7b0a3c334d1985ed1f67684b99d2eaccea2ec9085f732934699/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
测试一下刚才的文件是否同步出去
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径
5.5、数据卷容器
多个主机同步数据
# 测试
# 启动docker01
docker run -it --name docker01 flamingyouth/centos
# 启动docker02,设置共享卷docker1
docker run -it --name docker02 --volumes-from docker01 flamingyouth/centos
# 启动docker03,设置共享卷docker1
docker run -it --name docker03 --volumes-from docker01 flamingyouth/centos
多个mysql实现数据共享
# 启动mysql01
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动mysql02
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
6、DockerFile
dockerfile是用来构建docker镜像文件,命令参数脚本
6.1、DockerFile介绍
构建步骤:
编写一个dockerfile文件
docker build 构建成为一个镜像
docker run 运行镜像
docker push 发布镜像(DockerHub、阿里云镜像仓库)
查看了很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像
官方既然可以制作镜像,那我们也可以
6.2、DockerFile构建过程
基础知识
每个保留关键字(指令)都是必须是大写字母
从上到下顺序执行
表示注释
每一个指令都会创建提交一个新的镜像层。并提交
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单
Docker镜像逐渐成为企业交付的标准,必须要掌握
步骤:开发,部署,运维 ———— 缺一不可
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务器
DockerFile的指令
以前的话我们就是使用别人的,现在我们知道了这些命令后,我们来联系自己写一个镜像
FROM # 基础镜像,一切这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像。这个tomcat压缩包。添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可以被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战测试
Docker Hub 中99%镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行的构建
# 官方镜像
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
创建一个自己的centos
# 1.编写Dockerfile的文件
FROM centos
MAINTAINER andy<935917439@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、通过这个文件构建镜像
[root@localhost dockerfile]# docker build -f FlamingYouth-centos -t mycentos:0.1 .
Successfully built cd544b1d0975
Successfully tagged mycentos:0.1
查看镜像的变更历史
[root@localhost ~]# docker history cd544b1d0975
IMAGE CREATED CREATED BY SIZE COMMENT
cd544b1d0975 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
9b1f63f5b88c 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
56c158222b2f 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
4224dc236602 6 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
7241dc25315f 6 minutes ago /bin/sh -c yum -y install net-tools 23.3MB
8d3cae6b12e4 6 minutes ago /bin/sh -c yum -y install vim 58MB
ad9c6232f124 10 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
a4ab64bac79f 10 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
cab126eb88eb 10 minutes ago /bin/sh -c #(nop) MAINTAINER andy<935917439… 0B
300e315adb2f 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 4 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB
我们平时拿到一个镜像,可以研究一下她是怎么做的
CMD 和 ENTRYPOINT区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可以被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
测试 CMD
# 构建镜像
[root@localhost dockerfile]# docker build -f centos-test -t centos-test:0.1 .
# run运行 , 发现我们的ls -a 命令生效
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
---> Running in d851535e5308
Removing intermediate container d851535e5308
---> 989c713f99f7
Successfully built 989c713f99f7
Successfully tagged centos-test:0.1
[root@localhost dockerfile]# docker run centos-test:0.1
.
..
.dockerenv
bin
dev
....
var
# 项追加一个命令 -l ls -al
[root@localhost dockerfile]# docker run centos-test:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
#cmd的清理下 -l 替换了CMD["ls","-a"]命令,-l 不是命令才报错
测试 ENTRYPOINT
[root@localhost dockerfile]# docker run centos-test:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
[root@localhost dockerfile]# vim centos-test
[root@localhost dockerfile]# docker build -f centos-test -t centos-test:0.2 .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in bf83c407087e
Removing intermediate container bf83c407087e
---> 8440c08af5bb
Successfully built 8440c08af5bb
Successfully tagged centos-test:0.2
# 我们的追加命令,是直接拼接在我们的 ENTRYPOINT 命令的后面
[root@localhost dockerfile]# docker run centos-test:0.2
.
..
.dockerenv
bin
dev
etc
...
var
[root@localhost dockerfile]# docker run centos-test:0.2 -l
total 0
drwxr-xr-x. 1 root root 6 Jan 6 07:06 .
drwxr-xr-x. 1 root root 6 Jan 6 07:06 ..
-rwxr-xr-x. 1 root root 0 Jan 6 07:06 .dockerenv
lrwxrwxrwx. 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x. 5 root root 340 Jan 6 07:06 dev
drwxr-xr-x. 1 root root 66 Jan 6 07:06 etc
...
drwxr-xr-x. 20 root root 262 Dec 4 17:37 var
Dockerfile中很多命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果
实战:Tomcat镜像
1、准备镜像文件 tomcat压缩包,jdk的压缩包
2、编写Dockerfile文件,官方命名Dockerfile, build 会自动寻找这个文件,就不需要 -f 指定了
FROM centos
MAINTAINER andy<935917439@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u144-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.61.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_144
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.61
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.61
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.5.61/bin/startup.sh && tail -F /url/local/apache-tomcat-8.5.61/bin/logs/catalina.out
3、构建镜像
# docker build -t diytomcat .
4、启动镜像
docker run -d -p 9090:8080 --name yangfutomcat -v /home/flamingyouth/soft/tomcat/test:/usr/local/apache-tomcat-8.5.61/webapps/test -v /home/flamingyouth/soft/tomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.61/logs diytomcat
5、访问测试
http://192.168.3.18:9998
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了)
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>Tomcat Documentation</display-name>
<description>
Tomcat Documentation.
</description>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
Hello World!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>
发现:项目部署成功,可以直接访问
我们以后开发的步骤:需要掌握Dockerfile的编写!我们之后的一切都是使用docker镜像来发布运行
发布自己的镜像
DockerHub
地址 https://hub.docker.com/ 注册自己的账号
确定这个账号可以登录
在我们服务器上提交自己的镜像
[root@rocketmq-nameserver2 WEB-INF]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
[root@rocketmq-nameserver2 WEB-INF]# docker login -u flamingyouth
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
4、登陆完毕后提交镜像,就是一步 docker push
# push自己的镜像到服务器上
[root@rocketmq-nameserver2 soft]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
97b2c47cba0a: Preparing
b5d7ec691879: Preparing
424509e86482: Preparing
c965c79abae3: Preparing
2653d992f4ef: Preparing
denied: requested access to the resource is denied # 拒绝
# push镜像的问题
[root@rocketmq-nameserver2 soft]# docker push flamingyouth/diytomcat:1.0
The push refers to repository [docker.io/flamingyouth/diytomcat]
An image does not exist locally with the tag: flamingyouth/diytomcat
# 解决,增加一个 tag
[root@rocketmq-nameserver2 soft]# docker tag 339a12b89473 flamingyouth/diytomcat:1.0
# docker 成功 push
[root@rocketmq-nameserver2 soft]# docker push flamingyouth/diytomcat:1.0
The push refers to repository [docker.io/flamingyouth/diytomcat]
97b2c47cba0a: Pushed
b5d7ec691879: Pushed
424509e86482: Pushed
c965c79abae3: Pushed
2653d992f4ef: Pushed
1.0: digest: sha256:562e3024de1459efb78271842579d95d0bf28251b3e208af8e9f32bfe59c2700 size: 1373
提交的时候也是按照镜像的层级来进行提交的
阿里云镜像服务
登录阿里云
找到容器镜像服务
创建命名空间
创建镜像空间
浏览阿里云
小结
Docker网络
理解Docker0
测试
三个网络
# 问题:docker 是如何处理容器网络访问的?
# [root@rocketmq-nameserver2 ~]# docker run -d -p --name tomcat01 tomcat
[root@rocketmq-nameserver2 ~]# docker exec -it 91ed759e7732 /bin/bash
# 查看容器的内部网络地址 ip addr ,发现容器启动的时候会得到一个 eth0@if27 ip 地址,docker分配到
[root@91ed759e7732 local]# 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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 思考 linux 能不能 ping 通容器内部
[root@rocketmq-nameserver2 ~]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.041 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.069 ms
64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.040 ms
# linux 可以ping 通 docker 容器内部
原理
1、我们每启动一个docker容器,docker 就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术
2、测试ip addr(外面)
[root@rocketmq-nameserver2 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
.....
27: veth4284a7f@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 2e:f1:01:0f:35:ba brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::2cf1:1ff:fe0f:35ba/64 scope link
valid_lft forever preferred_lft forever
再次测试ip addr(容器内)
[root@91ed759e7732 local]# 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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 我们发现这个容器带来网卡,都是一对对的
# evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# OpenStac,Docker容器之间的连接,OVS的连接,都是使用 evth-pair 技术
3、测试两个容器是否可以相互ping通
# 结论:容器和容器之间是可以相互ping通的
网络模型:
结论:tomcat01 和 tomcat02 是公用的一个路由器 , docker0
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
小结
Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0
Docker 中的所有的网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
只要容器删除,对应网桥一对就没了
--link
思考一个场景,我们编写了一个微服务,database url = ip , 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可用名字来进行访问容器?
[root@rocketmq-nameserver2 ~]# docker exec -it yangfutomcat ping hungry_perlman
ping: hungry_perlman: Name or service not known
# 如何可以解决呢?
# 通过--link 既可以解决了网络连通问题
[root@rocketmq-nameserver2 ~]# docker exec -it tomcat ping yangfutomcat
PING yangfutomcat (172.17.0.3) 56(84) bytes of data.
64 bytes from yangfutomcat (172.17.0.3): icmp_seq=1 ttl=64 time=0.297 ms
64 bytes from yangfutomcat (172.17.0.3): icmp_seq=2 ttl=64 time=0.105 ms
64 bytes from yangfutomcat (172.17.0.3): icmp_seq=3 ttl=64 time=0.086 ms
# 反向可以ping通吗?
[root@rocketmq-nameserver2 ~]# docker exec -it yangfutomcat ping tomcat
ping: tomcat: Name or service not known
探究:inspect
其实这个tomcat03就是在本地配置了tomcat02的配置?
查看 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 91ed759e7732
172.17.0.4 e10ee272252e
本质探究:--link就是我们在hosts配置中增加了一个172.17.0.3 tomcat02 91ed759e7732
目前dokcer已经不建议使用 --likn 了!这种方法太笨了
自定义网络!不适合docker0
docker0问题:它不支持容器名连接访问
自定义网络
查看所有的docker 网络
网络模式
bridge : 桥接 docker(默认,自己搭建也使用桥接)
none : 不配置网络
host : 和宿主机共享网络
comtainer : 容器网络连通(用的少,局限性大)
测试
# 我们直接启动的命令 --net bridge, 而这个就是我们的docker0
docker run -d -P --name tomcat01 tamcat
docker run -d -P --name tomcat01 --net bridge tamcat
# docker0特点:默认,域名不能访问,--link可以打通
# 我们自定义一个网络
# --driver bridge 桥接模式
# --subnet 192.168.0.0/16 子网地址 192.168.0.2 ---- 192.168.255.255
# --gateway 192.168.0.1 网关地址
[root@rocketmq-nameserver2 ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
fc799d19ddbfcd721bf00a1cb47d4f20fb1cd2578d69cd371c7f18a169b25ae6
[root@rocketmq-nameserver2 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6463312dfabb bridge bridge local
de0b45f94c2c host host local
fc799d19ddbf mynet bridge local
e048e6b8ddef none null local
查看网络
[root@rocketmq-nameserver2 ~]# docker run -d -P --name tomcat01 --net mynet tomcat
WARNING: IPv4 forwarding is disabled. Networking will not work.
1dac1d57d5283e318d5ecd28ab8de91d5a822ff2937f2da25f5484b7e8d094c4
[root@rocketmq-nameserver2 ~]# docker run -d -P --name tomcat02 --net mynet tomcat
WARNING: IPv4 forwarding is disabled. Networking will not work.
d3922d8e504a4f986a63af6e41824f655243116ff2686e7b5c23eb18a8d1b788
[root@rocketmq-nameserver2 ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "fc799d19ddbfcd721bf00a1cb47d4f20fb1cd2578d69cd371c7f18a169b25ae6",
"Created": "2021-01-08T13:15:17.882808087+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"1dac1d57d5283e318d5ecd28ab8de91d5a822ff2937f2da25f5484b7e8d094c4": {
"Name": "tomcat01",
"EndpointID": "80d9d6c30a88dc92418df4645f5f1207eb5424cb585f6b9e434c7b7944e47fcb",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"d3922d8e504a4f986a63af6e41824f655243116ff2686e7b5c23eb18a8d1b788": {
"Name": "tomcat02",
"EndpointID": "a6ae73a7e99a3dcac133408b9f37086de43378ed64a6823f230cb38c0280126e",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 再次测试ping连接
[root@rocketmq-nameserver2 ~]# docker exec -it tomcat01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.151 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.081 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.083 ms
# 现在不使用 --link 也可以 ping 名字
[root@rocketmq-nameserver2 ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.105 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.095 ms
我们自定义的网络 docker 都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
好处
redis - 不同的集群使用不同的网络,保证集群是安全和健康的
mysql - 不同的集群使用不同的网络,保证集群是安全和健康的
网络连通
# 核心
connect Connect a container to a network
# 测试打通 tomcat03 - mynet
[root@rocketmq-nameserver2 ~]# docker network connect mynet tomcat03
# 连通之后就是将 tomcat03 放到了 mynet 网络下
[root@rocketmq-nameserver2 ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "fc799d19ddbfcd721bf00a1cb47d4f20fb1cd2578d69cd371c7f18a169b25ae6",
"Created": "2021-01-08T13:15:17.882808087+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"1dac1d57d5283e318d5ecd28ab8de91d5a822ff2937f2da25f5484b7e8d094c4": {
"Name": "tomcat01",
"EndpointID": "80d9d6c30a88dc92418df4645f5f1207eb5424cb585f6b9e434c7b7944e47fcb",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"c8d76c29c384a5c5063a970e470d9a681f16236b3823a034892811459ef6777b": {
"Name": "tomcat03",
"EndpointID": "da8567ad238353c5f8e3cdbeed0fd2776cc4f0a6ffa074ad8af354ca72b16700",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"d3922d8e504a4f986a63af6e41824f655243116ff2686e7b5c23eb18a8d1b788": {
"Name": "tomcat02",
"EndpointID": "a6ae73a7e99a3dcac133408b9f37086de43378ed64a6823f230cb38c0280126e",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 一个容器两个ip地址
# 例如:阿里云服务器,一个内网ip 一个外网ip
# 01 连通
[root@rocketmq-nameserver2 ~]# docker exec -it tomcat01 ping tomcat03
PING tomcat03 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat03.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.198 ms
64 bytes from tomcat03.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.109 ms
64 bytes from tomcat03.mynet (192.168.0.4): icmp_seq=3 ttl=64 time=0.080 ms
# 02 是依旧打不通的
[root@rocketmq-nameserver2 ~]# docker exec -it tomcat01 ping tomcat04
ping: tomcat04: Temporary failure in name resolution
结论:假设要跨网络操作别人,就需要使用docker network connect 连通
实战:部署Redis集群
# 创建网卡
docker network create redis --subnet 172.38.0.0/2+
# 通过脚本创建六个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
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
# 创建集群配置
/data # redis-cli --cluster create 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 172.38.0.11: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.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.11:6379 to 172.38.0.13:6379
Adding replica 172.38.0.15:6379 to 172.38.0.14:6379
M: f3262337926635ae969ac26df93c5c9bcac96eeb 172.38.0.12:6379
slots:[0-5460] (5461 slots) master
M: 97a7ff7d4c4e9df7ddc496770266835d0921eeaf 172.38.0.13:6379
slots:[5461-10922] (5462 slots) master
M: 2e8d580e90f4d85f0aeff67444d4d85fa0587e90 172.38.0.14:6379
slots:[10923-16383] (5461 slots) master
S: f2804bd2d07077648dbea87914177fd1766a7056 172.38.0.15:6379
replicates 2e8d580e90f4d85f0aeff67444d4d85fa0587e90
S: 38228eb3addbc742c46ebe61ba81f299ba8ffdbe 172.38.0.16:6379
replicates f3262337926635ae969ac26df93c5c9bcac96eeb
S: ee8db8e737a9e7d827b23fb07869fc72cbf18e7a 172.38.0.11:6379
replicates 97a7ff7d4c4e9df7ddc496770266835d0921eeaf
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.12:6379)
M: f3262337926635ae969ac26df93c5c9bcac96eeb 172.38.0.12:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: ee8db8e737a9e7d827b23fb07869fc72cbf18e7a 172.38.0.11:6379
slots: (0 slots) slave
replicates 97a7ff7d4c4e9df7ddc496770266835d0921eeaf
M: 2e8d580e90f4d85f0aeff67444d4d85fa0587e90 172.38.0.14:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 38228eb3addbc742c46ebe61ba81f299ba8ffdbe 172.38.0.16:6379
slots: (0 slots) slave
replicates f3262337926635ae969ac26df93c5c9bcac96eeb
S: f2804bd2d07077648dbea87914177fd1766a7056 172.38.0.15:6379
slots: (0 slots) slave
replicates 2e8d580e90f4d85f0aeff67444d4d85fa0587e90
M: 97a7ff7d4c4e9df7ddc496770266835d0921eeaf 172.38.0.13: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集群完成
172.38.0.15:6379> cluster nodes
f2804bd2d07077648dbea87914177fd1766a7056 172.38.0.15:6379@16379 myself,master - 0 1610089016000 7 connected 10923-16383
97a7ff7d4c4e9df7ddc496770266835d0921eeaf 172.38.0.13:6379@16379 master - 0 1610089017034 2 connected 5461-10922
38228eb3addbc742c46ebe61ba81f299ba8ffdbe 172.38.0.16:6379@16379 slave f3262337926635ae969ac26df93c5c9bcac96eeb 0 1610089016530 5 connected
2e8d580e90f4d85f0aeff67444d4d85fa0587e90 172.38.0.14:6379@16379 master,fail - 1610088806354 1610088805141 3 connected
ee8db8e737a9e7d827b23fb07869fc72cbf18e7a 172.38.0.11:6379@16379 slave 97a7ff7d4c4e9df7ddc496770266835d0921eeaf 0 1610089016000 6 connected
f3262337926635ae969ac26df93c5c9bcac96eeb 172.38.0.12:6379@16379 master - 0 1610089016933 1 connected 0-5460
SpringBoot微服务打包Docker镜像
构架springboot项目
打包应用
编写dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.[port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
构建镜像
[root@rocketmq-nameserver2 idea]# ls demo-0.0.1-SNAPSHOT.jar Dockerfile [root@rocketmq-nameserver2 idea]# docker build -t idea . Sending build context to Docker daemon 17MB Step 1/5 : FROM java:8 .... Successfully built 78150404575e Successfully tagged idea:latest
发布运行
[root@rocketmq-nameserver2 idea]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE idea latest 78150404575e 4 seconds ago 660MB [root@rocketmq-nameserver2 idea]# docker run -d -P --name SpringBoot-web idea WARNING: IPv4 forwarding is disabled. Networking will not work. e05da3bb73e029168915f5197166468d4ebbc824eb9d9bf7c10aedebe5327f84 [root@rocketmq-nameserver2 idea]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e05da3bb73e0 idea "java -jar /app.jar …" About a minute ago Up 58 seconds 0.0.0.0:49159->8080/tcp SpringBoot-web
以后我们使用了Docker之后,给别人交付的就是一个镜像即可
评论区