Docker安装
环境准备
- 操作系统:centOS 7
安装命令
# 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 \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #阿里云的镜像
# 4.更新yum软件包的索引
yum makecache fast
# 如出现错误:yum makecache: error: argument timer: invalid choice: 'fast' (choose from 'timer')
# 是centos 7 以上的无需fast,将最后的fast去掉,即 yum makecache
#如出现如下报错
# https://mirrors.aliyun.com/docker-ce/linux/centos/2.1903/x86_64/stable/repodata/repomd.xml: [Errno 14] HTTPS Error 404 - Not Found
# Trying other mirror.
# 经过排查发现是仓库配置中的 $releasever 找不到导致
# 解决方案
# 1. 打开仓库配置文件 vim /etc/yum.repos.d/docker-ce.repo
# 2. 编辑 docker-ce-stable 的baseurl值
# [docker-ce-stable]
# name=Docker CE Stable - $basearch
# #baseurl=https://download.docker.com/linux/centos/$releasever/$basearch/stable
# baseurl=https://download.docker.com/linux/centos/7/$basearch/stable
# 5.安装docker相关的 docker-ce 社区 docker-ee 企业版
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 6.启动docker
systemctl start docker
# 7.查看docker版本信息
docker version
# 8.运行hello word程序
docker run hello-world
# 9.查看hello word镜像
docker images
# 显示镜像列表中包含了hello-word
# REPOSITORY TAG IMAGE ID CREATED SIZE
# hello-world latest feb5d9fea6a5 12 months ago 13.3kB
# 10.卸载docker
yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin #卸载docker
rm -rf /var/lib/docker #删除docker文件
# /var/lib/docker docker的默认工作路径
rm -rf /var/lib/containerd #删除容器
阿里云镜像加速
- 1.登录阿里云找到容器服务
- 2.镜像工具 -> 镜像加速器
- 3.配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://pj8wvy6x.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker的常用命令
帮助命令
docker version #显示docker的版本信息
docker info #显示docker的系统信息,镜像和容器的信息
docker --help
帮助文档地址
镜像命令
docker images 查看所有本地的主机上的镜像
- 语法:$ docker images [OPTIONS] [REPOSITORY[:TAG]]
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 12 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
--all , -a # 列出所有镜像
--quiet , -q #只显示镜像的id
docker search 搜索镜像
- 语法:docker search [OPTIONS] TERM
docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13234 [OK]
mariadb MariaDB Server is a high performing open sou… 5062 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 640 [OK]
# 可选项,通过收藏来过滤
--filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13234 [OK]
mariadb MariaDB Server is a high performing open sou… 5062 [OK]
docker pull 下载镜像
- 语法:docker pull [OPTIONS] NAME[:TAG|@DIGEST]
docker pull mysql
Using default tag: latest # 如果不写tag,默认是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载,docker images的核心 联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: 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
# 指定版本
docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: 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 通过id删除镜像
- 语法1:docker rm [OPTIONS] CONTAINER [CONTAINER…]
- 语法2:docker rmi [OPTIONS] IMAGE [IMAGE…]
docker rmi -f [镜像id] # 删除指定的镜像
docker rmi -f [镜像id] [镜像id] [镜像id] # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部的镜像
容器命令
- 说明:我们有了镜像才可以创建容器,liunx,下载一个centos来学习
docker pull centos
- 新建容器并启动
docker run 启动命令
- 语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
docker run [可选参数] [imageid]
# 参数说明
-- name="容器名字" # tomcat01、tomcat02来区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-P # 指定容器的端口 -P 8080:8080
-P 主机端口:容器端口(常用)
-P ip:主机端口:容器端口
-P 容器端口
-p # 随机指定端口
# 测试,启动并进入容器
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -it centos /bin/bash
[root@ee4c5e37df22 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 退出容器的命令 exit
[root@ee4c5e37df22 /]# exit
exit
[root@iZwz9a69mvjujb826ezp71Z ~]#
codker ps 列出所有运行的容器
- 语法:docker ps [OPTIONS]
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的?个容器
-q #只显示容器的编号
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps # 列出正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps -a # 列出曾经运行过的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e772dac215d centos "/bin/bash" About a minute ago Exited (0) About a minute ago infallible_dhawan
ee4c5e37df22 centos "/bin/bash" 10 minutes ago Exited (130) 5 minutes ago compassionate_fermat
ac9ea78776d8 feb5d9fea6a5 "/hello" 9 hours ago Exited (0) 9 hours ago awesome_carver
退出容器
exit # 容器停止并退出
ctrl + p + q # 容器不停止退出
删除容器
- 语法:docker rm [OPTIONS] CONTAINER [CONTAINER…]
docker rm [容器id] # 删除一个容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm [容器id] [容器id] [容器id] # 删除多个容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有的容器
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e27783028c25 centos "/bin/bash" 6 minutes ago Up 6 minutes practical_brahmagupta
9e772dac215d centos "/bin/bash" 17 minutes ago Exited (0) 17 minutes ago infallible_dhawan
ee4c5e37df22 centos "/bin/bash" 26 minutes ago Exited (130) 21 minutes ago compassionate_fermat
ac9ea78776d8 feb5d9fea6a5 "/hello" 9 hours ago Exited (0) 9 hours ago awesome_carver
[root@iZwz9a69mvjujb826ezp71Z ~]# docker rm ee4c5e37df22
ee4c5e37df22
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e27783028c25 centos "/bin/bash" 6 minutes ago Up 6 minutes practical_brahmagupta
9e772dac215d centos "/bin/bash" 17 minutes ago Exited (0) 17 minutes ago infallible_dhawan
ac9ea78776d8 feb5d9fea6a5 "/hello" 9 hours ago Exited (0) 9 hours ago awesome_carver
[root@iZwz9a69mvjujb826ezp71Z ~]# docker rm -f $(docker ps -aq)
e27783028c25
9e772dac215d
ac9ea78776d8
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps -aq
[root@iZwz9a69mvjujb826ezp71Z ~]#
启动和停止容器的操作
docker start [容器id] # 启动容器
docker restart [容器id] # 重启容器
docker stop [容器id] # 停止当前正在运行的容器
docker kill [容器id] # 强制停止当前容器
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -it centos
[root@bfa228de9ca5 /]# exit
exit
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bfa228de9ca5 centos "/bin/bash" 14 seconds ago Exited (0) 7 seconds ago kind_ride
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZwz9a69mvjujb826ezp71Z ~]# docker start bfa228de9ca5
bfa228de9ca5
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bfa228de9ca5 centos "/bin/bash" 59 seconds ago Up 6 seconds kind_ride
[root@iZwz9a69mvjujb826ezp71Z ~]# docker stop bfa228de9ca5
bfa228de9ca5
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZwz9a69mvjujb826ezp71Z ~]#
常用其他命令
后台启动容器
# 命令 docker run -d [镜像名]
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -d centos
a6137fec75259a89159bb54a402cd74758800283f2507fc59a5c259661a313f2
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS N
[root@iZwz9a69mvjujb826ezp71Z ~]#
# 问题docker ps发现centos停止了
# 常见的坑,docker容器使用后台运行,就必须要有一个前台进程,容器发现没有前台应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
docker logs 查看日志
- 语法:docker logs [OPTIONS] CONTAINER
docker logs -f -t --tail # 容器,没有日志
# 自己写一段shell脚本
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done"
311b1004f82c57e146cb134050580a9babe93ad47de1232e8641ae88f50c1af4
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
311b1004f82c centos "/bin/sh -c 'while t…" 6 seconds ago Up 4 seconds brave_aryabhata
[root@iZwz9a69mvjujb826ezp71Z ~]# docker logs -tf --tail 10 311b1004f82c
2022-10-17T11:44:53.314645253Z kuangshen:sleep 1
2022-10-17T11:44:54.314647364Z kuangshen:sleep 1
2022-10-17T11:44:55.314649446Z kuangshen:sleep 1
2022-10-17T11:44:56.314651539Z kuangshen:sleep 1
2022-10-17T11:44:57.314653625Z kuangshen:sleep 1
2022-10-17T11:44:58.314655737Z kuangshen:sleep 1
2022-10-17T11:44:59.314657820Z kuangshen:sleep 1
docker top 查看容器中进程信息 ps
- 语法:docker top CONTAINER [ps OPTIONS]
[root@iZwz9a69mvjujb826ezp71Z ~]# docker top 293a96e9f8c2
UID PID PPID C STIME TTY TIME CMD
root 13280 13259 0 19:46 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done
root 13993 13280 0 19:50 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
[root@iZwz9a69mvjujb826ezp71Z ~]#
docker inspect 查看镜像的元数据
- 语法:docker inspect [OPTIONS] NAME|ID [NAME|ID…]
[root@iZwz9a69mvjujb826ezp71Z ~]# docker inspect 293a96e9f8c2
[
{
"Id": "293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc",
"Created": "2022-10-17T11:46:19.886068959Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo kuangshen;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 13280,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-10-17T11:46:22.799044097Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc/hostname",
"HostsPath": "/var/lib/docker/containers/293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc/hosts",
"LogPath": "/var/lib/docker/containers/293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc/293a96e9f8c2b38205bf02d6b7ba48d36c69d2cdd84cb02d2bb7099440b662fc-json.log",
"Name": "/elegant_hofstadter",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/00950fc7f4e96b8f224253b2aa70861e47ae6a73a46dedc435014098484513e7-init/diff:/var/lib/docker/overlay2/14b861549be01547ba5a8225e3d9c9d0f936056dae663f0fd64ebc5a8538ef99/diff",
"MergedDir": "/var/lib/docker/overlay2/00950fc7f4e96b8f224253b2aa70861e47ae6a73a46dedc435014098484513e7/merged",
"UpperDir": "/var/lib/docker/overlay2/00950fc7f4e96b8f224253b2aa70861e47ae6a73a46dedc435014098484513e7/diff",
"WorkDir": "/var/lib/docker/overlay2/00950fc7f4e96b8f224253b2aa70861e47ae6a73a46dedc435014098484513e7/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "293a96e9f8c2",
"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 kuangshen;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": "57e976e4fde44487e008790f4d8a9634d285f54162f93b12aa6e0410bb36e7fa",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/57e976e4fde4",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "3dcdb7a50f5b812b8460d8be69d9159c9e12bd040210c28086f3b418bd4b8005",
"Gateway": "172.18.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.18.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:12:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "d95ae4c3110aefeea49c8706646a4f1bda55dd0ed67bb191a18ed06abbf33192",
"EndpointID": "3dcdb7a50f5b812b8460d8be69d9159c9e12bd040210c28086f3b418bd4b8005",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:12:00:03",
"DriverOpts": null
}
}
}
}
]
[root@iZwz9a69mvjujb826ezp71Z ~]#
docker exec|docker attach 进入当前正在运行的容器
- 语法1:docker exec [OPTIONS] CONTAINER COMMAND [ARG…]
- 语法2:docker attach [OPTIONS] CONTAINER
# 方式一
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
293a96e9f8c2 centos "/bin/sh -c 'while t…" 17 minutes ago Up 17 minutes elegant_hofstadter
[root@iZwz9a69mvjujb826ezp71Z ~]# docker exec -it 293a96e9f8c2 /bin/bash
[root@293a96e9f8c2 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@293a96e9f8c2 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:46 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done
root 1099 0 0 12:04 pts/0 00:00:00 /bin/bash
root 1132 1 0 12:04 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 1133 1099 0 12:04 pts/0 00:00:00 ps -ef
[root@293a96e9f8c2 /]#
# 方式二
[root@iZwz9a69mvjujb826ezp71Z ~]# docker attach 293a96e9f8c2
# 这里会执行当前的代码
# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入当前正在执行的终端,不会启动新的进程
docker cp 从容器内拷贝文件到主机上
- 语法:docker cp [OPTIONS] CONTAINER:[容器内文件路径] [主机内文件路径]
# 创建并运行一个容器
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -it centos /bin/bash
[root@a68ad0f27ce1 /]# cd /home
[root@a68ad0f27ce1 home]# ls
# 容器内创建文件夹
[root@a68ad0f27ce1 home]# touch test.java
[root@a68ad0f27ce1 home]# ls
test.java
[root@a68ad0f27ce1 home]# exit
exit
# 到主机home目录下
[root@iZwz9a69mvjujb826ezp71Z ~]# cd /home
[root@iZwz9a69mvjujb826ezp71Z home]# ls
admin kuangshen.java
# 拷贝容器内的文件到主机home目录下
[root@iZwz9a69mvjujb826ezp71Z home]# docker cp a68ad0f27ce1:/home/test.java /home
[root@iZwz9a69mvjujb826ezp71Z home]# ls
admin home kuangshen.java test.java
# 拷贝是一个手动过程,未来我们使用 -v 卷技术,可以实现自动同步
docker commit 提交自己的镜像
- 语法:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
# 命令和git原理类似
docker commit -m="提交者的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
# 启动tomcat
[root@iZwz9a69mvjujb826ezp71Z ~]# docker run -it -p 3344:8080 tomcat
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/openjdk-11
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
......
22-Oct-2022 08:53:11.398 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
22-Oct-2022 08:53:11.435 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [214] milliseconds
# 进入tomcat
[root@iZwz9a69mvjujb826ezp71Z ~]# docker exec -it 03f310b60c99 /bin/bash
# 拷贝webapps.dist/* 到 webapps文件夹下
root@03f310b60c99:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@03f310b60c99:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
# 退出tomcat
root@03f310b60c99:/usr/local/tomcat/webapps# exit
exit
[root@iZwz9a69mvjujb826ezp71Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03f310b60c99 tomcat "catalina.sh run" 12 minutes ago Up 12 minutes 0.0.0.0:3344->8080/tcp flamboyant_gauss
# 提交镜像
[root@iZwz9a69mvjujb826ezp71Z ~]# docker commit -a="Sun白" -m="add webapps app" 03f310b60c99 tomcat_sunbai:1.0
sha256:3980d733befce7e12ec98c58e6b3780ef95d831e7f518ba6a917d071f1c129d8
[root@iZwz9a69mvjujb826ezp71Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat_sunbai 1.0 3980d733befc 7 seconds ago 684MB
nginx latest 605c77e624dd 9 months ago 141MB
tomcat 9.0 b8e65a4d736d 10 months ago 680MB
tomcat latest fb5657adc892 10 months ago 680MB
centos latest 5d0da3dc9764 13 months ago 231MB
- 实战步骤
- 启动一个tomcat
- 发现这个默认的tomcat是没有webapps应用。镜像的原因,官方的镜像默认webapps下面是没有文件的
- 我们自己拷贝进去了基本的文件
- 将我们操作过的容器commit提交为一个镜像。我们以后就使用我们修改过的镜像即可,这就是我们自己修改的一个镜像
docker history 查看本地镜像的变更历史
- 语法:docker history [OPTIONS] IMAGE
[root@VM-0-10-centos dockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 0.1 13db9c2c8947 13 minutes ago 625MB
<none> <none> e2287f1dc69e 38 minutes ago 231MB
sunbai/centos 1.0 5571c282f543 8 hours ago 231MB
nginx latest 605c77e624dd 9 months ago 141MB
mysql 5.7 c20987f18b13 10 months ago 448MB
centos 7 eeb6ee3f44bd 13 months ago 204MB
centos latest 5d0da3dc9764 13 months ago 231MB
# 查看centos最新版本是怎么做起来的
[root@VM-0-10-centos dockerfile]# docker history 5d0da3dc9764
IMAGE CREATED CREATED BY SIZE COMMENT
5d0da3dc9764 13 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 13 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 13 months ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB
容器数据卷
什么是容器数据卷
- docker的理念回顾
将应用和环境打包成一个镜像 - 如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL:容器删了——删库跑路!需求:MySQL数据可以存储在本地 - 容器之间可以有一个数据共享技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面! - 总结:容器的持久化和同步操作,容器间也是可以数据共享的
使用数据卷
- 方式一:直接使用命令来挂载 -v
# docker run -it -v [主机目录]:[容器目录]
[root@iZwz9a69mvjujb826ezp71Z ~]# cd /home
[root@iZwz9a69mvjujb826ezp71Z home]# ls
admin home kuangshen.java test.java
[root@iZwz9a69mvjujb826ezp71Z home]# docker run -it -v /home/ceshi://home centos /bin/bash
[root@83072b3d9925 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 这里在新开的linux端口查看容器信息(主机内,容器外)
# 可以看到Mounts,这就是挂载的信息
[root@iZwz9a69mvjujb826ezp71Z home]# docker inspect 83072b3d9925
[
{
......
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
......
}
]
测试:在容器内加test.java文件
# 容器内
[root@83072b3d9925 home]# touch test.java
[root@83072b3d9925 home]# ls
test.java
# 容器外
[root@iZwz9a69mvjujb826ezp71Z home]# ls
admin ceshi home kuangshen.java test.java
[root@iZwz9a69mvjujb826ezp71Z home]# cd ceshi
[root@iZwz9a69mvjujb826ezp71Z ceshi]# ls
test.java
测试:在容器外加test2.java文件
# 容器外
[root@iZwz9a69mvjujb826ezp71Z ceshi]# touch test2.java
[root@iZwz9a69mvjujb826ezp71Z ceshi]# ls
test2.java test.java
# 容器内
[root@83072b3d9925 home]# ls
test.java test2.java
具名挂载和匿名挂载
# 匿名挂载
# -v 容器内路径
[root@VM-0-10-centos ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
3d0332f678c31bc1ae038f379837e8fe2b616693ddad2461d2a581e818ce291e
[root@VM-0-10-centos ~]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
[root@VM-0-10-centos ~]# docker ls
docker: 'ls' is not a docker command.
See 'docker --help'
# 查看所有卷的情况
[root@VM-0-10-centos ~]# docker volume ls
DRIVER VOLUME NAME
local ac30eb2ac205f0c8a05de3e432275696456c5cb09b4a191cfd6698a64081f75e
# 具名挂载
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx nginx
[root@VM-0-10-centos ~]# docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx nginx
bb042de99b8686972ad252070e144f8104dc0edafaf062855ef28e426fb9502d
[root@VM-0-10-centos ~]# docker volume ls
DRIVER VOLUME NAME
local ac30eb2ac205f0c8a05de3e432275696456c5cb09b4a191cfd6698a64081f75e
local jvming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷
[root@VM-0-10-centos ~]# docker volume inspect jvming-nginx
[
{
"CreatedAt": "2022-10-23T14:19:22+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/jvming-nginx/_data",
"Name": "jvming-nginx",
"Options": null,
"Scope": "local"
}
]
- 所有的docker容器内的卷,没有指定目录的情况下都是在
/var/lib/docker/volumes/xxx/_data
下
[root@VM-0-10-centos ~]# cd /var/lib/docker
[root@VM-0-10-centos docker]# ls
buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
[root@VM-0-10-centos docker]# cd volumes/
[root@VM-0-10-centos volumes]# ls
ac30eb2ac205f0c8a05de3e432275696456c5cb09b4a191cfd6698a64081f75e backingFsBlockDev jvming-nginx metadata.db
[root@VM-0-10-centos volumes]# cd jvming-nginx/
[root@VM-0-10-centos jvming-nginx]# ls
_data
[root@VM-0-10-centos jvming-nginx]# cd _data
[root@VM-0-10-centos _data]# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
[root@VM-0-10-centos _data]# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
- 我们通过具名挂载,可以方便的找到一个卷,大多数情况都使用具名挂载
- 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
- 拓展
# 通过 -v 容器内路径:ro rw 改变若其对指定的文件的读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦这个设置了容器的权限,容器对我们挂载的出来的内容就有限定了
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx:ro nginx # 这时/etc/nginx只能在主机上改变,不能在容器内改变
docker run -d -P --name nginx02 -v jvming-nginx:/etc/nginx:rw nginx # 这时/etc/nginx能在主机上改变,也能在容器内改变
Docker File
初识Dockerfile
- Dockerfile就是用来构建docker镜像的构建文件!
- 体验Dockerfile
# 创建一个脚本文件,名字可以随机,但是建议Dockerfile
[root@VM-0-10-centos docker-test-volume]# pwd
/home/docker-test-volume
[root@VM-0-10-centos docker-test-volume]# vim dockerfile1
# 通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层
# 指令都是大写的
# 这里的每个命令就是镜像的一层
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash
# 用刚才创建的文件生成镜像
[root@VM-0-10-centos docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t sunbai/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
a1d0c7532777: Pull complete
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in da9fe40b6f79
Removing intermediate container da9fe40b6f79
---> dbfe9007bd2b
Step 3/4 : CMD echo "---end---"
---> Running in e35903966441
Removing intermediate container e35903966441
---> 49330afa627a
Step 4/4 : CMD /bin/bash
---> Running in 3fdf8b1a1a45
Removing intermediate container 3fdf8b1a1a45
---> 5571c282f543
Successfully built 5571c282f543
Successfully tagged sunbai/centos:1.0
[root@VM-0-10-centos docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sunbai/centos 1.0 5571c282f543 38 seconds ago 231MB
nginx latest 605c77e624dd 9 months ago 141MB
mysql 5.7 c20987f18b13 10 months ago 448MB
centos latest 5d0da3dc9764 13 months ago 231MB
- 启动自己写的容器
[root@VM-0-10-centos docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sunbai/centos 1.0 5571c282f543 38 seconds ago 231MB
nginx latest 605c77e624dd 9 months ago 141MB
mysql 5.7 c20987f18b13 10 months ago 448MB
centos latest 5d0da3dc9764 13 months ago 231MB
[root@VM-0-10-centos docker-test-volume]# docker run -it 5571c282f543 /bin/bash
[root@bb2dad1e2c5a /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@bb2dad1e2c5a /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Oct 23 08:05 dev
drwxr-xr-x 1 root root 4096 Oct 23 08:05 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 182 root root 0 Oct 23 08:05 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Oct 23 08:05 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
drwxr-xr-x 2 root root 4096 Oct 23 08:05 volume01
drwxr-xr-x 2 root root 4096 Oct 23 08:05 volume02
- 在容器内创建一个文件,生成并启动镜像
# 创建文件
[root@afc3694e422f /]# cd volume01
[root@afc3694e422f volume01]# ls
[root@afc3694e422f volume01]# touch container.txt
# 退出容器并查看下容器卷挂载位置
[root@afc3694e422f volume01]# exit
exit
[root@VM-0-10-centos docker-test-volume]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afc3694e422f 5571c282f543 "/bin/bash" 3 minutes ago Exited (0) 52 seconds ago beautiful_taussig
bb2dad1e2c5a 5571c282f543 "/bin/bash" 9 minutes ago Exited (127) 4 minutes ago vibrant_gould
bb042de99b86 nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:49154->80/tcp, :::49154->80/tcp nginx02
3d0332f678c3 nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:49153->80/tcp, :::49153->80/tcp nginx01
[root@VM-0-10-centos docker-test-volume]# docker inspect afc3694e422f
[
{
......
"Mounts": [
{
"Type": "volume",
"Name": "e0f6fcdfae4012a236c75f5fd9207cc95075e6e726a6fbad387379d3a9e16ac8",
"Source": "/var/lib/docker/volumes/e0f6fcdfae4012a236c75f5fd9207cc95075e6e726a6fbad387379d3a9e16ac8/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "e60f47c835ac91e07b571194edb69eb170f7c7af32e576f27ad25d2e6719a5f2",
"Source": "/var/lib/docker/volumes/e60f47c835ac91e07b571194edb69eb170f7c7af32e576f27ad25d2e6719a5f2/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
}
]
# 查看下宿主机对应的目录
[root@VM-0-10-centos docker-test-volume]# cd /var/lib/docker/volumes/e0f6fcdfae4012a236c75f5fd9207cc95075e6e726a6fbad387379d3a9e16ac8/_data
[root@VM-0-10-centos _data]# ls
container.txt
- 这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
- 假如构建镜像的时候没有挂载卷,要手动镜像挂载 -v [卷名]:[容器内路径]
数据卷容器
- 启动第一个容器
[root@VM-0-10-centos ~]# docker run -it --name docker01 sunbai/centos:1.0
[root@e50ac9d277f8 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@e50ac9d277f8 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Oct 23 10:40 dev
drwxr-xr-x 1 root root 4096 Oct 23 10:40 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 181 root root 0 Oct 23 10:40 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Oct 23 10:40 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
drwxr-xr-x 2 root root 4096 Oct 23 10:40 volume01
drwxr-xr-x 2 root root 4096 Oct 23 10:40 volume02
- –volumes-from继承docker01启动docker02容器
[root@VM-0-10-centos ~]# docker run -it --name docker02 --volumes-from docker01 sunbai/centos:1.0
[root@5e097942f0c5 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@5e097942f0c5 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Oct 23 10:44 dev
drwxr-xr-x 1 root root 4096 Oct 23 10:44 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 183 root root 0 Oct 23 10:44 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Oct 23 10:44 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
drwxr-xr-x 2 root root 4096 Oct 23 10:40 volume01
drwxr-xr-x 2 root root 4096 Oct 23 10:40 volume02
- 进入到docker01的容器中在volume01中创建docker01文件
[root@VM-0-10-centos ~]# docker attach e50ac9d277f8
[root@e50ac9d277f8 /]# cd volume01
[root@e50ac9d277f8 volume01]# ls
[root@e50ac9d277f8 volume01]# touch docker01
[root@e50ac9d277f8 volume01]# ls
docker01
- 回到docker02容器中查看volume01下的文件,多了docker01文件
[root@5e097942f0c5 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@5e097942f0c5 /]# cd volume01
[root@5e097942f0c5 volume01]# ls
docker01
- 原理:docker01将数据卷挂载到宿主机上,docker02将数据挂载到和docker01相同的数据卷上,其实都指向了宿主机的同一个文件上
# 查看docker01的挂载目录
[root@VM-0-10-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5e097942f0c5 sunbai/centos:1.0 "/bin/sh -c /bin/bash" 11 minutes ago Up 11 minutes docker02
e50ac9d277f8 sunbai/centos:1.0 "/bin/sh -c /bin/bash" 15 minutes ago Up 15 minutes docker01
bb042de99b86 nginx "/docker-entrypoint.…" 5 hours ago Up 5 hours 0.0.0.0:49154->80/tcp, :::49154->80/tcp nginx02
3d0332f678c3 nginx "/docker-entrypoint.…" 5 hours ago Up 5 hours 0.0.0.0:49153->80/tcp, :::49153->80/tcp nginx01
[root@VM-0-10-centos ~]# docker inspect e50ac9d277f8
[
{
......
"Mounts": [
{
"Type": "volume",
"Name": "78651533950a0e7c368aa3a02131c7195dc17da50339105868de0ee2f04b3982",
"Source": "/var/lib/docker/volumes/78651533950a0e7c368aa3a02131c7195dc17da50339105868de0ee2f04b3982/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "af488699ba4e67e4e5f311ee85052ba442528b63f5e1ae827578a15d1b54f6fe",
"Source": "/var/lib/docker/volumes/af488699ba4e67e4e5f311ee85052ba442528b63f5e1ae827578a15d1b54f6fe/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
}
]
# 查看docker02的挂载目录
[root@VM-0-10-centos ~]# docker inspect 5e097942f0c5
[
{
......
"Mounts": [
{
"Type": "volume",
"Name": "78651533950a0e7c368aa3a02131c7195dc17da50339105868de0ee2f04b3982",
"Source": "/var/lib/docker/volumes/78651533950a0e7c368aa3a02131c7195dc17da50339105868de0ee2f04b3982/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "af488699ba4e67e4e5f311ee85052ba442528b63f5e1ae827578a15d1b54f6fe",
"Source": "/var/lib/docker/volumes/af488699ba4e67e4e5f311ee85052ba442528b63f5e1ae827578a15d1b54f6fe/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
}
]
DockerFile概念
- dockerfile是用来构建docker镜像的文件,实质上是命令参数脚本
- 构建步骤
- 编写dockerfile文件
- docker bulid 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockrHub,阿里云镜像仓库)
- 查看官方是怎么做的
登录docker hub,搜索centos,看到centos7的链接
点进去,是一个github地址,可以看到dockerfile,里面是命令脚本
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像
官方既然可以制作镜像,那我们也可以
DockerFile构建过程
- 基础知识
- 每个保留关键字(指令)都建议是大写字母
- 执行从上到i下顺序执行
- #表示注释
- 每一个指令都会创建一个新的镜像层,并提交
- dockerfile是面向开发的,我们以后要发布项目,做镜像就需要编写dockerfile文件,这个文件十分简单!
- Docker镜像逐渐成为企业交付的标准,必须要掌握!
- 步骤:开发,部署,运维…缺一不可
- DockerFile:构建文件,定义了一切的步骤,源代码
- DocmerImages(镜像):通过DockerFile构建生成的镜像,最终发布和运行的产品
- DockerContiner(容器):容器就是镜像运行起来提供服务的
DockerFile的指令
命令 | 含义 |
---|---|
FROM | 基础镜像,一切从这里开始构建 |
MAINTAINER | 镜像是谁写的,姓名+邮箱 |
RUN | 镜像构建的时候需要运行的命令 |
ADD | 步骤:添加的镜像或文件,会自动解压 |
WORKDIR | 镜像的工作目录 |
VOLUME | 设置挂载的目录 |
EXPOSE | 对外暴露的端口配置 |
ENTRYPOINT | 容器的启动命令,可以直接追加命令 |
CMD | CMD为ENTRYPOINT提供默认参数,也可以单独使用CMD指定容器启动参数,只有最后一个会生效,可被替代 |
ONBUILD | 当构建一个被继承的DockerFile,这个时候就会运行ONBUILD的指令。触发指令 |
COPY | 类似ADD,将文件拷贝到镜像中 |
ENV | 构建的时候设置环境变量 |
- ENTRYPOINT和CMD 命令的区别
- ENTRYPOINT命令在build的时候生效,CMD在run的时候生效
- 在一个DockerFile中只有最后一个CMD会生效(不可追加,会被覆盖),ENTRYPOINT是可以生效多个的(可追加,不会被覆盖)
- Dockerfile中很多命令的都十分的相似,我们需要了解它们的区别,最好的学习就是对比它们然后测试效果
发布自己的镜像
- 发布到Docker Hub
- 地址https://hub.docker.com/注册自己的账号
- 确定这个账号可以登录
- 在我们服务器上提交自己的镜像
[root@VM-0-10-centos ~]# docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username # 登录docker hub [root@VM-0-10-centos ~]# docker login -u onlysunbai Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded # 查看本地镜像 [root@VM-0-10-centos ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE diytomcat latest c80000b9b2d3 23 hours ago 834MB mycentos 0.1 13db9c2c8947 45 hours ago 625MB <none> <none> e2287f1dc69e 46 hours ago 231MB sunbai/centos 1.0 5571c282f543 2 days ago 231MB nginx latest 605c77e624dd 9 months ago 141MB mysql 5.7 c20987f18b13 10 months ago 448MB centos 7 eeb6ee3f44bd 13 months ago 204MB centos latest 5d0da3dc9764 13 months ago 231MB # 提交镜像,本地没有这个镜像所以报错(这个镜像没有tag) [root@VM-0-10-centos ~]# docker push onlysunbai/diytomcat:1.0 The push refers to repository [docker.io/onlysunbai/diytomcat] An image does not exist locally with the tag: onlysunbai/diytomcat # 不指定版本直接提交,因为重名被拒绝 [root@VM-0-10-centos ~]# docker push diytomcat Using default tag: latest The push refers to repository [docker.io/library/diytomcat] f4cc785f73e8: Preparing 06e36413256e: Preparing 54ea0564acf3: Preparing 174f56854903: Preparing denied: requested access to the resource is denied # 拒绝 # 解决方法,为当前需要提交的镜像增加tag [root@VM-0-10-centos ~]# docker tag c80000b9b2d3 onlysunbai/tomcat:1.0 [root@VM-0-10-centos ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE diytomcat latest c80000b9b2d3 23 hours ago 834MB onlysunbai/tomcat 1.0 c80000b9b2d3 23 hours ago 834MB mycentos 0.1 13db9c2c8947 46 hours ago 625MB <none> <none> e2287f1dc69e 46 hours ago 231MB sunbai/centos 1.0 5571c282f543 2 days ago 231MB nginx latest 605c77e624dd 9 months ago 141MB mysql 5.7 c20987f18b13 10 months ago 448MB centos 7 eeb6ee3f44bd 13 months ago 204MB centos latest 5d0da3dc9764 13 months ago 231MB # 再次提交镜像,就可以成功了(由于是国外的网站,比较慢) [root@VM-0-10-centos ~]# docker push onlysunbai/tomcat:1.0 The push refers to repository [docker.io/onlysunbai/tomcat] f4cc785f73e8: Pushing [==========> ] 52.02MB/238.2MB 06e36413256e: Pushed 54ea0564acf3: Pushing [====> ] 35.91MB/375.5MB 174f56854903: Pushing [====> ] 16.87MB/203.9MB
- 发布到阿里云镜像上
-
登录阿里云
-
找到镜像容器服务
-
创建命名空间及仓库(初次使用需要先创建实例)
-
创建容器镜像
-
浏览仓库信息,查看操作指南
-
在服务器上登录阿里云并上传镜像
# 登录阿里云 [root@iZwz9a69mvjujb826ezp71Z ~]# docker logout Removing login credentials for https://index.docker.io/v1/ [root@iZwz9a69mvjujb826ezp71Z ~]# docker login --username=onlysunbai registry.cn-shenzhen.aliyuncs.com Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded # 为镜像重命名 [root@VM-0-10-centos ~]# docker tag c80000b9b2d3 registry.cn-shenzhen.aliyuncs.com/sunbai-test/diytomcat:1.0 [root@VM-0-10-centos ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE onlysunbai/tomcat 1.0 c80000b9b2d3 24 hours ago 834MB registry.cn-shenzhen.aliyuncs.com/sunbai-test/diytomcat 1.0 c80000b9b2d3 24 hours ago 834MB diytomcat latest c80000b9b2d3 24 hours ago 834MB mycentos 0.1 13db9c2c8947 47 hours ago 625MB <none> <none> e2287f1dc69e 47 hours ago 231MB sunbai/centos 1.0 5571c282f543 2 days ago 231MB nginx latest 605c77e624dd 9 months ago 141MB mysql 5.7 c20987f18b13 10 months ago 448MB centos 7 eeb6ee3f44bd 13 months ago 204MB centos latest 5d0da3dc9764 13 months ago 231MB # 推送镜像到阿里云(这里需要一点时间) [root@VM-0-10-centos ~]# docker push registry.cn-shenzhen.aliyuncs.com/sunbai-test/diytomcat:1.0 The push refers to repository [registry.cn-shenzhen.aliyuncs.com/sunbai-test/diytomcat] f4cc785f73e8: Pushing [==> ] 10.35MB/238.2MB 06e36413256e: Pushing [==============> ] 4.695MB/16.11MB 54ea0564acf3: Pushing [> ] 4.979MB/375.5MB 174f56854903: Pushing [==> ] 10.34MB/203.9MB
-
Docker镜像加载原理
联合文件系统
- UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于继承(没有父镜像),可以制作各种具体的应用镜像。
- 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
我们下载的时候看到的一层层就是这个!
Docker镜像加载原理
- docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
- bootfs(boot file system):主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就在内存中了,此时内存的使用已由bootfs转交给内核,此时系统也会卸载bootfs。
- rootfs(root file system):在bootfs之上,包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,如Ubuntu,Centos等等。
平时我们安装虚拟机的Centos都是好几个G,为什么Docker这里才200M?
- 对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kermel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
- 虚拟机是分钟级别,容器是秒级!
分层理解
- 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
- 思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处就是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有容器服务了,而且镜像的每一层都可以被共享。 - 理解:所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux 16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,该镜像就会在基础镜像之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
下图镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像必须始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版。
这种情况下,上层镜像层中的文件覆盖了底层镜像中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。 - Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
- Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS,顾名思义,每种引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
- Docker在Windows上仅支持windosfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像堆叠合并,对外提供统一的视图。
特点
- Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是我们通常说的容器层,容器之下的都叫镜像层。
Docker 小结
Docker 网络
理解Docker0
- 测试
[root@VM-0-10-centos ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:18:6c:7d brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 172.16.0.10/20 brd 172.16.15.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe18:6c7d/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:3c:bb:23:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:3cff:febb:2306/64 scope link
valid_lft forever preferred_lft forever
三个网络
- 问题:docker是如何处理容器网络访问的?
- 运行tomcat容器
[root@VM-0-10-centos ~]# docker run -d -P --name tomcat01 tomcat:7.0
...
538a1e2d12c6850795508daa9aa51c3ab54ac859daf121f9d694ff5a2309edee
- 查看下容器内IP
[root@VM-0-10-centos ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
38: eth0@if39: <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通容器内部?
- 尝试ping容器内网地址
[root@VM-0-10-centos ~]# 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.057 ms
....
64 bytes from 172.17.0.2: icmp_seq=36 ttl=64 time=0.052 ms
--- 172.17.0.2 ping statistics ---
36 packets transmitted, 36 received, 0% packet loss, time 35841ms
rtt min/avg/max/mdev = 0.027/0.042/0.057/0.007 ms
- linux可以ping通容器内部
原理
- 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0
- docker使用桥接模式,使用的是veth-pair技术
- 再次用ip addr测试,发现多了一个网卡39
[root@VM-0-10-centos ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:18:6c:7d brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 172.16.0.10/20 brd 172.16.15.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe18:6c7d/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:3c:bb:23:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:3cff:febb:2306/64 scope link
valid_lft forever preferred_lft forever
39: veth459982b@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 86:fc:f5:6a:be:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::84fc:f5ff:fe6a:bebc/64 scope link
valid_lft forever preferred_lft forever
- 对比容器内ip和容器外ip,发现正好是配对的
我们发现这个容器带来网卡,都是一对对的
evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连
正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟网络设备的
OpenStack,Docker容器之间的连接,OVS的链接,都是使用veth-pair技术
- 再启动一个tomcat02,查看ip
# 启动tomcat02
[root@VM-0-10-centos ~]# docker run -d --name tomcat02 tomcat:7.0
4f7e4ff8d23f69212768cb5889067f53fbd3fc9ccf010555dc8883a05ee4923b
# 查看ip
[root@VM-0-10-centos ~]# docker exec -it tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
40: eth0@if41: <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
- 查看容器内ip,再查看linux的ip,果然是成对出现了40和41
# 查看容器内ip
[root@VM-0-10-centos ~]# docker exec -it tomcat02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
40: eth0@if41: <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 ip
[root@VM-0-10-centos ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:18:6c:7d brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 172.16.0.10/20 brd 172.16.15.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe18:6c7d/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:3c:bb:23:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:3cff:febb:2306/64 scope link
valid_lft forever preferred_lft forever
39: veth459982b@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 86:fc:f5:6a:be:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::84fc:f5ff:fe6a:bebc/64 scope link
valid_lft forever preferred_lft forever
41: vetha7ec6f6@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether be:ad:08:37:d3:1b brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::bcad:8ff:fe37:d31b/64 scope link
valid_lft forever preferred_lft forever
问题:两个容器内能否互相ping通呢?
- 测试,发现两个容器之间可以互相ping通
[root@VM-0-10-centos ~]# 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.096 ms
...
64 bytes from 172.17.0.2: icmp_seq=38 ttl=64 time=0.079 ms
--- 172.17.0.2 ping statistics ---
38 packets transmitted, 38 received, 0% packet loss, time 953ms
rtt min/avg/max/mdev = 0.050/0.067/0.096/0.013 ms
原理:docker0充当网桥,所有容器最终通过docker0联系在一起,所有可以互相ping通
- tomcat01和tomcat02是共用一个路由器,docker0
- 所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
- 网络模型图
注意:
- Docker中所有的网络接口都是虚拟的。虚拟的转发效率高。
- 只要容器停止了,对应的网桥对就没了。
- 停止tomcat02,41的veth-pair没了
[root@VM-0-10-centos ~]# docker stop tomcat02
tomcat02
[root@VM-0-10-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
538a1e2d12c6 tomcat:7.0 "catalina.sh run" 2 hours ago Up 2 hours 0.0.0.0:49156->8080/tcp, :::49156->8080/tcp tomcat01
[root@VM-0-10-centos ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:18:6c:7d brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 172.16.0.10/20 brd 172.16.15.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe18:6c7d/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:3c:bb:23:06 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:3cff:febb:2306/64 scope link
valid_lft forever preferred_lft forever
39: veth459982b@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 86:fc:f5:6a:be:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::84fc:f5ff:fe6a:bebc/64 scope link
valid_lft forever preferred_lft forever
思考一个场景:我们编写了一个微服务,database url=ip,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器。(达到高可用)
- 方案1:在容器的/etc/hosts文件下配置静态路由映射 [目标IP地址] [名字]即可实现通过名字访问容器(不推荐,不好维护,实际上–link命令就是这么做的)
- 方案2:自定义网络
docker network 管理docker网络
- 查看docker网卡列表
[root@VM-0-10-centos java]# docker network ls
NETWORK ID NAME DRIVER SCOPE
72b5fd5f989d bridge bridge local
ea4002e14ec1 host host local
221aaac7ba29 none null local
- 查看网桥bridge
[root@VM-0-10-centos java]# docker network ls
NETWORK ID NAME DRIVER SCOPE
72b5fd5f989d bridge bridge local
ea4002e14ec1 host host local
221aaac7ba29 none null local
[root@VM-0-10-centos java]# docker network inspect --help
Usage: docker network inspect [OPTIONS] NETWORK [NETWORK...]
Display detailed information on one or more networks
Options:
-f, --format string Format the output using the given Go template
-v, --verbose Verbose output for diagnostics
[root@VM-0-10-centos java]# docker network inspect 72b5fd5f989d
[
{
"Name": "bridge",
"Id": "72b5fd5f989d250b048ae24b0e3ebe3aa6b0d9fce64ceafd7dd2fe747593811a",
"Created": "2022-10-27T19:47:33.826787817+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default", # 默认网卡,docker0
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16", # 子网络可用16位分配
"Gateway": "172.17.0.1" # docker0地址
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": { # 容器的网桥
"4f7e4ff8d23f69212768cb5889067f53fbd3fc9ccf010555dc8883a05ee4923b": { # 容器的id
"Name": "tomcat02", # tomcat02
"EndpointID": "21edb21579c1682e228b9551c72c78ce44b1d4852e3d16419ff48f9e63531892",
"MacAddress": "02:42:ac:11:00:03", # tomcat02的Mac地址
"IPv4Address": "172.17.0.3/16", # tomcat02的内网ip
"IPv6Address": ""
},
"538a1e2d12c6850795508daa9aa51c3ab54ac859daf121f9d694ff5a2309edee": {
"Name": "tomcat01",
"EndpointID": "098754bd7f908a1de5cbad1cf84e81f5eca898a588a4c612ee450e94fd7c0656",
"MacAddress": "02:42:ac:11:00:02", # tomcat01的Mac地址
"IPv4Address": "172.17.0.2/16", # tomcat01的内网ip
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
- 查看一下tomcat02的网络设置
[root@VM-0-10-centos java]# docker inspect tomcat02
[
{
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "b53669d518428b87af39c18dd4c16e06da2e3fac1f5e2f8d460fe00242bdba74",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"8080/tcp": null
},
"SandboxKey": "/var/run/docker/netns/b53669d51842",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "21edb21579c1682e228b9551c72c78ce44b1d4852e3d16419ff48f9e63531892",
"Gateway": "172.17.0.1", # tomcat02的网关就是docker0
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "72b5fd5f989d250b048ae24b0e3ebe3aa6b0d9fce64ceafd7dd2fe747593811a",
"EndpointID": "21edb21579c1682e228b9551c72c78ce44b1d4852e3d16419ff48f9e63531892",
"Gateway": "172.17.0.1", # 网关是docker0
"IPAddress": "172.17.0.3", # 当前的容器的网络ip
"IPPrefixLen": 16, # 可用编址空间为16位
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
}
}
}
}
]
自定义网络
- 查看所有的docker网络
[root@VM-0-10-centos java]# docker network ls
NETWORK ID NAME DRIVER SCOPE
72b5fd5f989d bridge bridge local
ea4002e14ec1 host host local
221aaac7ba29 none null local
-
网络模式
- bridge:桥接模式 搭桥(默认,自己搭建的网络也使用bridge模式)
- none:不配置网络
- host:主机模式,和宿主机共享网络
- container:容器网络联通(用的少,局限很大)
-
清理一下docker容器
[root@VM-0-10-centos java]# docker rm -f $(docker ps -aq)
47f07905b1b3
4f7e4ff8d23f
538a1e2d12c6
[root@VM-0-10-centos java]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 测试
# 我们直接启动的命令其实就默认有 --net bridge,如下命令,而这个bridge就是我们的docker0
[root@VM-0-10-centos java]# docker run -d -P --name tomcat01 --net bridge tomcat:7.0
- docker0的特点:默认,域名不能访问,使用–link可用打通连接
- 我们可以使用docker network create自定义网络
# 看一下帮助文档
[root@VM-0-10-centos java]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
# 创建自己的网络
# --driver bridge 指定路由模式为桥接模式
# --subnet 192.168.0.0/16 指定子网为192.168.x.x的,编码空间为后16(32-16=16)位
# --gateway 192.168.0.1 指定网关为192.168.0.1
# mynet 为这个自定义网络起名为mynet
[root@VM-0-10-centos java]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a
# 查看当前的网络,多了一个mynet
[root@VM-0-10-centos java]# docker network ls
NETWORK ID NAME DRIVER SCOPE
72b5fd5f989d bridge bridge local
ea4002e14ec1 host host local
46cac985389d mynet bridge local
221aaac7ba29 none null local
# 查看一下自己刚定义的网络
[root@VM-0-10-centos java]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a",
"Created": "2022-10-27T20:53:49.088066176+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16", # 自己配置的子网
"Gateway": "192.168.0.1" # 自己配置的网关
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
- 使用自定义的网络启动tomcat
[root@VM-0-10-centos java]# docker run -d -P --name tomcat-net-01 --net mynet tomcat:7.0
f180a0b2df38755360ea179b4cc4293b6b4b9965e67bf04d70cf1c2fd1070484
- 查看tomcat-net-01的网络信息
[
{
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "912ac999ee6b4772803ac4e21461f683add1766a49d1400d2466c43817e17cc4",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "49154"
},
{
"HostIp": "::",
"HostPort": "49154"
}
]
},
"SandboxKey": "/var/run/docker/netns/912ac999ee6b",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"mynet": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"f180a0b2df38"
],
"NetworkID": "46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a",
"EndpointID": "1a935a876a20c32f71bf9c2106a6fa725e05116e5c4f04ea4a20e3e0804d122e",
"Gateway": "192.168.0.1", # 网关是自己配置的mynet的网关
"IPAddress": "192.168.0.2", # 子网是自己配置的mynet的子网范围
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:00:02",
"DriverOpts": null
}
}
}
}
]
- 查看下mynet的网络信息
[root@VM-0-10-centos java]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a",
"Created": "2022-10-27T20:53:49.088066176+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": {
"f180a0b2df38755360ea179b4cc4293b6b4b9965e67bf04d70cf1c2fd1070484": {
"Name": "tomcat-net-01", # tomcat-net-01容器
"EndpointID": "1a935a876a20c32f71bf9c2106a6fa725e05116e5c4f04ea4a20e3e0804d122e",
"MacAddress": "02:42:c0:a8:00:02", # tomcat-net-01容器MAC地址
"IPv4Address": "192.168.0.2/16", # tomcat-net-01容器IP地址
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
- 再启动一个tomcat
[root@VM-0-10-centos java]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:7.0
99e9c24c98997bc58ed63ff7646cf00c2d5cd4f68f48dbcb1539f32cd9779d7b
- tomcat-net-02直接通过容器名ping tomcat-net-01,成功了
[root@VM-0-10-centos java]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:7.0
99e9c24c98997bc58ed63ff7646cf00c2d5cd4f68f48dbcb1539f32cd9779d7b
[root@VM-0-10-centos java]# docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.100 ms
...
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=9 ttl=64 time=0.068 ms
--- tomcat-net-01 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 184ms
rtt min/avg/max/mdev = 0.052/0.070/0.100/0.017 ms
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
好处:不同的集群使用不同的网络,保证集群是安全和健康的
网络联通
问题:不同网络内的docker容器能否联通?
- 使用docker0网络启动tomcat
[root@VM-0-10-centos java]# docker run -d -P --name tomcat01 tomcat:7.0
8595e908c6252dbff53d06a85f34f4b69ae50f618d93c8819de7ae648170e862
[root@VM-0-10-centos java]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8595e908c625 tomcat:7.0 "catalina.sh run" 4 seconds ago Up 3 seconds 0.0.0.0:49156->8080/tcp, :::49156->8080/tcp tomcat01
99e9c24c9899 tomcat:7.0 "catalina.sh run" 19 minutes ago Up 19 minutes 0.0.0.0:49155->8080/tcp, :::49155->8080/tcp tomcat-net-02
f180a0b2df38 tomcat:7.0 "catalina.sh run" 27 minutes ago Up 27 minutes 0.0.0.0:49154->8080/tcp, :::49154->8080/tcp tomcat-net-01
- 尝试在tomcat01使用容器名ping tomcat-net-01,发现不通
[root@VM-0-10-centos java]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
- 使用docker network connect联通一个网络到容器
# 查看命令帮助
[root@VM-0-10-centos ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
#
- 尝试打通tomcat01到mynet网络
[root@VM-0-10-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a",
"Created": "2022-10-27T20:53:49.088066176+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": {
"8595e908c6252dbff53d06a85f34f4b69ae50f618d93c8819de7ae648170e862": {
"Name": "tomcat01", # tomcat01被加入到这个网络的容器列表中了
"EndpointID": "21eff43172f5cf31350e89418716b3cfa61c17b6b1f5f5dd854523696dc53657",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16", # 这个网络为tomcat01分配了一个子网地址
"IPv6Address": ""
},
"99e9c24c98997bc58ed63ff7646cf00c2d5cd4f68f48dbcb1539f32cd9779d7b": {
"Name": "tomcat-net-02",
"EndpointID": "6582dbd1f1c6e1405eedbf34d296130b3cd91bfd1b25b7d0c6223d89ebebd5ec",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"f180a0b2df38755360ea179b4cc4293b6b4b9965e67bf04d70cf1c2fd1070484": {
"Name": "tomcat-net-01",
"EndpointID": "1a935a876a20c32f71bf9c2106a6fa725e05116e5c4f04ea4a20e3e0804d122e",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
docker network connect 就是将目标容器加入到了目标网络中,目标网络为目标容器分配了一个内网地址
这就是一个容器,多个IP地址
相当于直接加网卡
- 查看tomcat01的网络信息
[root@VM-0-10-centos ~]# docker inspect tomcat01
[
{
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "31e424fb16fa812066e1efdbbe62ca152a0127f85aeceb63490a3230add016ce",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "49156"
},
{
"HostIp": "::",
"HostPort": "49156"
}
]
},
"SandboxKey": "/var/run/docker/netns/31e424fb16fa",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "baa62f8b37a09456f4e1871b42f3e6af24856e26054ba006166a65b3f1042f8e",
"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": "72b5fd5f989d250b048ae24b0e3ebe3aa6b0d9fce64ceafd7dd2fe747593811a",
"EndpointID": "baa62f8b37a09456f4e1871b42f3e6af24856e26054ba006166a65b3f1042f8e",
"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
},
"mynet": { # 被添加进mynet网络
"IPAMConfig": {},
"Links": null,
"Aliases": [
"8595e908c625"
],
"NetworkID": "46cac985389df24982dbb1a8687e7f8cee4982f94927363888b779facdc4dd2a",
"EndpointID": "21eff43172f5cf31350e89418716b3cfa61c17b6b1f5f5dd854523696dc53657",
"Gateway": "192.168.0.1", # mynet网络的网关
"IPAddress": "192.168.0.4", # mynet网络中的ip地址
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:00:04",
"DriverOpts": {}
}
}
}
}
]
- 再次尝试在tomcat01内ping tomcat-net-01,成功
[root@VM-0-10-centos ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.107 ms
...
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=13 ttl=64 time=0.077 ms
--- tomcat-net-01 ping statistics ---
13 packets transmitted, 13 received, 0% packet loss, time 336ms
rtt min/avg/max/mdev = 0.053/0.070/0.107/0.017 ms
假设要跨网络操作别的容器,就需要使用docker network connect连通