参考
【狂神说Java】Docker最新超详细版教程通俗易懂
Docker 启动报错
前言
记录下笔记, 之后好复习
Docker安装
Docker的基本组成
镜像(image):
Docker镜像就好比是一个模板, 可以通过这个模板创建容器服务, tomcat镜像 —> run —> tomacat01容器, 通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中)
容器(container):
Docker利用容器技术, 独立运行一个或者一组引用, 通过镜像来创建
启动, 停止, 删除, 基础命令
目前就可以把这个容器理解为就是一个简易的linux 系统
仓库(repository):
仓库就是存放镜像的地方
仓库分为公有仓库和私有仓库
Docker Hub(默认是国外的)
阿里云… 都有容器服务器(配置镜像加速)
Docker安装
# 1.卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2.需要的安装包
sudo yum install -y yum-utils
# 3.设置镜像仓库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认从国外, 很慢
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 推荐阿里云
# 4.更新yum软件索引 (optional)
sudo yum makecache fast # centos7
sudo yum makecache # centos8
# centos 7 没问题, centos 8 j会报错
# 5. 安装docker引擎 docker-ce 社区版本 ee 企业版
# 核心 客户端 容器
sudo yum install docker-ce docker-ce-cli containerd.io
# 6. 查看docker版本
# 7. 启动docker
sudo systemctl start docker
# 8. 验证docker engine是否安装成功
sudo docker run hello-world
# 9. 查看下载的hello-world镜像
sudo docker images
Docker 卸载
# 1. 卸载安装包
sudo yum remove docker-ce docker-ce-cli containerd.io
# 2. 卸载资源
sudo rm -rf /var/lib/docker # docker的默认工作路径
sudo rm -rf /var/lib/containerd
配置阿里云镜像加速
-
找到阿里云加速地址
-
配置使用
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://yxrav1j4.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
回顾Hello-world流程
底层原理
Docker是什么工作的?
Docker 是一个Client-Server结构的系统, Docker 的守护进程运行在主机上, 通过Socket从客户端访问
DockerServer 接收到Docker-Client的指令, 就会执行这个命令
Docker为什么比VM快?
- Docker 有着比虚拟机更少的抽象层
- Docker 利用的是宿主机的内核, VM需要Guest OS
Docker的常用命令
帮助命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息, 包括镜像和容器的数量
docker 命令 --help # 帮助命令
帮助文档的地址: https://docs.docker.com/reference/
镜像命令
docker images 查看所有本地的主机上的镜像
[root@zb zhoubin]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 3 days ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a, --all Show all images (default hides intermediate images)
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
-q, --quiet # 只显示镜像的id
docker search 搜索镜像
[root@zb zhoubin]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11473 [OK]
mariadb MariaDB Server is a high performing open sou… 4356 [OK]
# 可选项
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results (default 25)
--no-trunc Don't truncate output
# 例子
docker search mysql -f=STARS=3000 # 搜索星星大于3000
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
[root@zb zhoubin]# docker pull mysql
Using default tag: latest # 如果不写tag, 默认就是latest
latest: Pulling from library/mysql
a330b6cecb98: Pull complete # 分层下载, docker image的核心 联合文件系统
9c8f656c32b8: Pull complete
88e473c3f553: Pull complete
062463ea5d2f: Pull complete
daf7e3bdf4b6: Pull complete
1839c0b7aac9: Pull complete
cf0a0cfee6d0: Pull complete
1b42041bb11e: Pull complete
10459d86c7e6: Pull complete
b7199599d5f9: Pull complete
1d6f51e17d45: Pull complete
50e0789bacad: Pull complete
Digest: sha256:99e0989e7e3797cfbdb8d51a19d32c8d286dd8862794d01a547651a896bcf00c # 签名 防伪标志
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
docker rmi 删除镜像
[root@zb zhoubin]# docker rmi -f 镜像id # 删除指定的镜像
[root@zb zhoubin]# docker rmi -f 镜像id 镜像id 镜像id 镜像id # 删除多个镜像
[root@zb zhoubin]# docker rmi -f $(docker images -aq) # 删除全部的镜像
# 可选的
-f, --force Force removal of the image
--no-prune Do not delete untagged parents
容器命令
有了镜像才可以创建容器, 下载一个centos镜像来测试学习
docker pull centos
docker run 新建容器并启动
docker run [可选参数] image
# 可选的
--name="Name" 容器名字, 用来区分容器
-d 后台方式运行
-it 使用交互方式运行, 进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口
# 例子
# 启动并进入容器
[root@zb zhoubin]# docker run -it centos /bin/bash
[root@af490be56050 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退出
[root@af490be56050 /]# exit
exit
[root@zb /]# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var zhoubin
docker ps 列出所有运行的容器
[root@zb /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zb /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af490be56050 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago infallible_mccarthy
f9456648c272 feb5d9fea6a5 "/hello" 2 hours ago Exited (0) 2 hours ago hungry_curran
# 可选的
-a, --all Show all containers (default shows just running), 包括历史运行的
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print containers using a Go template
-n, --last int Show n last created containers (includes all states) (default -1)
-l, --latest Show the latest created container (includes all states)
--no-trunc Don't truncate output
-q, --quiet # 只显示容器的编号
-s, --size Display total file sizes
退出容器
exit # 直接容器停止并推出
Ctrl + P + Q # 容器不停止退出
docker rm 删除容器
docker rm 容器id # 删除指定的容器, 不能删除正在运行的容器, 如果要强制删除 rm -f
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 # 强制定制当前的容器
常用的其他命令
后台启动容器
# 命令 docker run -d 镜像名
[root@zb /]# docker run -d centos
# 问题docker ps, 发现centos停止了
# 常见的坑: docker 容器使用后台运行, 就必须要有一个前台进程, docker发现没有引用, 会自动停止
# centos 容器启动后, 发现自己没有提供服务, 就会立刻停止
docker logs 查看日志
docker logs [可选参数] 容器
# 可选的
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
docker top 常看容器中进程信息
# 命令 docker top 容器id
[root@zb /]# docker top fdcb4ce7d32c
UID PID PPID C STIME TTY TIME CMD
root 2049439 2049419 0 17:35 pts/0 00:00:00 /bin/bash
docker inspect 查看镜像的源数据
# 命令 docker inspect 容器id
[root@zb /]# docker inspect fdcb4ce7d32c
[
{
"Id": "fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74",
"Created": "2021-09-27T09:35:55.474260558Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2049439,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-09-27T09:35:55.740878875Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74/hostname",
"HostsPath": "/var/lib/docker/containers/fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74/hosts",
"LogPath": "/var/lib/docker/containers/fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74/fdcb4ce7d32ce6d1c0024b8616b4cb7bd346458b7adf1e4be5364edd5033ee74-json.log",
"Name": "/cranky_elbakyan",
"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/2546a273abe99c7335fbb03d67f8d380f743d91b6a47647231a4548967e23832-init/diff:/var/lib/docker/overlay2/ae442db66d110d0f4da98712944be8533e5c129299d4378bd8b50157e1715767/diff",
"MergedDir": "/var/lib/docker/overlay2/2546a273abe99c7335fbb03d67f8d380f743d91b6a47647231a4548967e23832/merged",
"UpperDir": "/var/lib/docker/overlay2/2546a273abe99c7335fbb03d67f8d380f743d91b6a47647231a4548967e23832/diff",
"WorkDir": "/var/lib/docker/overlay2/2546a273abe99c7335fbb03d67f8d380f743d91b6a47647231a4548967e23832/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "fdcb4ce7d32c",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "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": "7949bffe1d061e2cf0ea576114c80fc61f593d9ac8b33cc3b65823af443dc449",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/7949bffe1d06",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "1e0662f10c7915bee627d362cf5ec94a9a460a88ac4d17d7ce856e3fc2c5c94a",
"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": "aa59f89e5467987caa069f8a0de56691ac5d953cdafb7b842287b0c8b3bc6d1e",
"EndpointID": "1e0662f10c7915bee627d362cf5ec94a9a460a88ac4d17d7ce856e3fc2c5c94a",
"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
}
}
}
}
]
进入当前正在运行的容器
通常容器都是使用后台方式运行的, 需要进入容器, 修改一些配置
方式1:
# 命令
docker exec -it 容器id bashShell
# 例子
[root@zb /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fdcb4ce7d32c centos "/bin/bash" 11 minutes ago Up 11 minutes cranky_elbakyan
[root@zb /]# docker exec -it fdcb4ce7d32c /bin/bash
[root@fdcb4ce7d32c /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@fdcb4ce7d32c /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:35 pts/0 00:00:00 /bin/bash
root 15 0 0 09:47 pts/1 00:00:00 /bin/bash
root 30 15 0 09:47 pts/1 00:00:00 ps -ef
方式2:
# 命令
docker attach 容器id
# 例子
[root@zb /]# docker attach fdcb4ce7d32c
正在执行当前的代码...
区别:
docker exec : 进入容器后开启一个新的终端, 可以在里面操作(常用)
docker attach: 进入容器正在执行的终端, 不会启动新的进程
docker cp 从容器内拷贝文件到主机上
#命令 docker cp 容器id:容器内路径 目标主机路径
[root@zb home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
806a97d603e4 centos "/bin/bash" 3 minutes ago Up 2 minutes mystifying_leakey
[root@zb home]# docker exec -it 806a97d603e4 /bin/bash
[root@806a97d603e4 /]# cd /home
[root@806a97d603e4 home]# ls
[root@806a97d603e4 home]# touch text.cpp
[root@806a97d603e4 home]# read escape sequence
[root@zb home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
806a97d603e4 centos "/bin/bash" 3 minutes ago Up 3 minutes mystifying_leakey
[root@zb home]# ls
test.java
[root@zb home]# docker cp 806a97d603e4:/home/text.cpp /home
[root@zb home]# ls
test.java text.cpp
# 拷贝是一个手动过程, 未来我们使用 -v 卷的技术, 可以实现自动同步
小结
attach Attach local standard input, output, and error streams to a running container # 当前shell下attach链接指定运行镜像
build Build an image from a Dockerfile # 通过Dockerfile 定制镜像
commit Create a new image from a container’s changes # 提交当前容器为新的镜像
cp Copy files/folders between a container and the local filesystem # 从容器中拷贝指定文件或者目录到宿主机
create Create a new container # 创建一个新的容器, 同run, 但不启动容器
diff Inspect changes to files or directories on a container’s filesystem # 查看docker容器变化
events Get real time events from the server # 从docker服务获取容器实时事件
exec Run a command in a running container # 在已存在的容器上运行命令
export Export a container’s filesystem as a tar archive # 导出容器的内容流作为一个tar归档文件[对应import]
history Show the history of an image # 展示一个镜像形成历史
images List images # 列出系统当前镜像
import Import the contents from a tarball to create a filesystem image # 从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on Docker objects # 查看容器详细信息
kill Kill one or more running containers # kill 指定docker 容器
load Load an image from a tar archive or STDIN # 从一个tar包中加载一个镜像[对应save]
login Log in to a Docker registry # 注册或者登陆一个 docker 源服务器
logout Log out from a Docker registry # 从当前的Docker registry
logs Fetch the logs of a container # 输出当前容器日志信息
pause Pause all processes within one or more containers # 暂停容器
port List port mappings or a specific mapping for the container # 查看映射端口对应的容器内部源端口
ps List containers # 列出容器列表
pull Pull an image or a repository from a registry # 从docker镜像源服务器拉去指定镜像或者库镜像
push Push an image or a repository to a registry # 推送指定镜像或者库镜像至docker源服务器
rename Rename a container
restart Restart one or more containers # 重启运行容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除, 否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container # 创建一个新的容器并运行一个命令
save Save one or more images to a tar archive (streamed to STDOUT by default) # 保存一个镜像为一个 tar 包[对应 load]
search Search the Docker Hub for images # 在 docker hub 中搜索镜像
start Start one or more stopped containers # 启动容器
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers # 停止容器
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE # 给源中镜像打标签
top Display the running processes of a container # 查看容器中运行的进程信息
unpause Unpause all processes within one or more containers # 取消暂停容器
update Update configuration of one or more containers
version Show the Docker version information # 查看docker 版本号
wait Block until one or more containers stop, then print their exit codes # 截取容器停止时的退出状态值
可视化
-
portainer(先用这个)
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portianer
-
Rancher(CI/CD再用)
什么是portainer?
Docker图形化界面管理工具, 提供一个后台面板供我们操作
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试: http://120.55.42.144:8088/
Docker镜像讲解
镜像是什么
镜像是一种轻量级, 可执行的独立软件包, 用来打包软件运行环境和机遇运行环境开发的软件, 它包含运行某个软件所需的所有内容, 包括代码, 运行时, 库, 环境变量和配置文件
所有应用, 直接打包docker镜像, 就可以直接跑起来
如何得到镜像
- 从远处仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统): Union文件系统(UnionFS) 是一种分层, 轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directiories 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的kernel, 自己只需要提供rootfs就可以了, 由此可见对于不同的linux发行版, bootf基本是一直的, rootfs会有差别, 因为不同的发行版可以公有bootfs
分层理解
分层的镜像
我们可以去下载一个镜像, 可以看到是一层一层的再下载的
为什么Docker镜像要采用这种分层的结构呢?
最大的好处, 莫过于资源共享, 比如有多个镜像都从相同的 Base镜像构建而来, 那么宿主机只需在磁盘上保留一份base镜像, 同事内存中只需要加载一份base镜像, 这样就可以为所有的容器服务了, 而且镜像的每一层可以被共享
查看镜像分层的方式可以通过docker image inspect 命令
[root@zb zhoubin]# docker image inspect redis:latest
[
// .....
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d000633a56813933cb0ac5ee3246cf7a4c0205db6290018a169d7cb096581046",
"sha256:bdad86443e47c5665683ac41c1f24f28479d830d7e3cc47d0a337ee5166c7714",
"sha256:6a7992ac480029d82b7dbb757d16fe5d023aa283ed32b52267cd1fe9e6b73c49",
"sha256:be43d2475cf809c0f2ec31950e849d0f888f3121970fd99196a11a903f8c3820",
"sha256:be5818ef2907adfe19be14bf66647b5fb5a2029143f9297f8ce1ff1fd1d35753",
"sha256:c54e0c16ea22fa873c12f6a7f3fb4e021bb58d67c292156a6ce6e08637458b7c"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
理解:
所有的Docker 镜像都起始于一个基础镜像层, 当进行修改或增加新的内容时, 就会在当前镜像层之上, 创建新的镜像层
举个简单的例子, 例如基于Ubuntu Linux 16.04创建一个新的镜像, 这就是新镜像的第一层, 如果在该镜像中添加Python包, 就会在基础镜像层之上创建第二个镜像层, 如果继续添加一个安全补丁, 就会创建第三个镜像层
该镜像当前已经包含3个镜像层
在添加额外的镜像层的同时, 镜像始终保持是当前所有镜像的组合, 理解这一点非常重要, 下图举了一个简单的例子,每个镜像层包含3个文件, 而镜像包含了两个镜像层的6个文件
上图中的镜像层跟之前图的略有区别, 主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像, 在外部看来整个镜像只有6个文件, 这是因为最上层的文件7是文件5的一个更新版本
这种情况下, 上层镜像层中的文件覆盖了底层镜像层的文件, 这样就使得文件的更新八本作为一个新的镜像层添加到镜像当中去
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈, 并保证多镜像层对外展示为统一的文件系统
Linux 上可用的存储引擎有AUFS, Overlay2, Device Mapper, Btrfs 以及 ZFS, 顾名思义, 每种存储引擎都基于Linux中对应的文件系统或者块设备技术, 并且每种存储引擎都有其独有的性能特点
Docker在Windows上仅支持windowfilter一种存储引擎, 改引擎基于NTFS文件系统之上实现分层和Cow[1]
下图展示了与系统相同的三层镜像, 所有镜像层堆叠并合并, 对外提供统一的视图
特点
Docker镜像都是只读的, 容器启动时, 一个新的可写层被加载到镜像的顶部
这一层就是我们通常说的容器层, 容器之下的都叫镜像层
Commit镜像
docker commit 提交容器成为新的副本
# 命令和git原理相似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1. 启动一个默认的tomcat
# 2. 发现这个默认的tomcat是没有webapps应用, 镜像的原因, 官方的镜像默认webapps下面是没有文件的
# 3. 我自己拷贝进去了基本的文件
# 4. 将我们操作过的容器通过commit提交为一个镜像
容器数据卷
什么是容器数据卷
Docker的理念回顾
将应用和环境打包成一个镜像
数据,如果数据都在容器中, 那么容器删除, 数据就会丢失。需求: 数据可以持久化
MySQL,容器删了, 删库跑路 需求: MySQL数据可以存储在本地
容器之前可以有一个数据共享的技术, Docker容器中产生的数据, 同步到本地
这就是卷技术, 目录的挂载, 将我们容器内的目录, 挂载到linux上面
总结: 容器的持久化和同步操作, 容器间也可以数据共享
使用数据卷
方式1:直接使用命令来挂载 -v
docker run -it -v 主机目录:容器内目录
# 测试
[root@zb home]# docker run -it -v /home/test:/home centos /bin/bash
# 启动后通过docker inspect 容器id
好处: 之后修改只需要本地修改即可
实战: 安装mysql
思考: MySQL的数据持久化的问题
# 获取镜像
[root@zb test]# docker pull mysql:5.7
# 运行容器, 需要做数据挂载 # 安装启动mysql, 需要配置密码
# 官方测试: docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动mysql
[root@zb test]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
具名和匿名挂载
# 匿名挂载
-v 容器内路径
[root@zb data]# docker run -d -P --name nginx01 -v /etc/nginx/ nginx
de24b43780f17972c33f104d377c6fe19c9cdcf5b7a8f4db78f8f0596d76e304
# 查看所有的volume 的情况
[root@zb data]# docker volume ls
DRIVER VOLUME NAME
local 19be477cd4e0b3b2822f7d00e18fd5179198d5e0dcd37354c8d8af26a32cb5b7
local a4f93cf8eb95af73bd61ac16ec45d0d69d7e240b368bbdd9e1c536d68e6a7aa0
# 这种就是匿名挂载, 在-v只写了容器内的路径, 没有写容器外的路径
# 具名挂载
[root@zb data]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
35663552faf1b1a7661bb84a854f67c2e2e514d8daab79191f6cd331b13edb2e
[root@zb data]# docker volume ls
DRIVER VOLUME NAME
local 19be477cd4e0b3b2822f7d00e18fd5179198d5e0dcd37354c8d8af26a32cb5b7
local a4f93cf8eb95af73bd61ac16ec45d0d69d7e240b368bbdd9e1c536d68e6a7aa0
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷
[root@zb data]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2021-09-29T10:01:57+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/xxx/_data
通过具名挂载可以方便的找到我们的一个卷大多数情况在使用的具名挂载
# 如何确定是具名挂载还是匿名挂载, 还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径, ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦设置容器的权限, 容器对挂载出来的内容就有限定
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 说明这个路径只能通过宿主机改变, 容器内部是无法操作
# 默认是rw
初识Dockerfile
Dockerfile就是用来构建docker镜像的构建文件, 命令脚本, 体验一下
通过这个脚本可以生成镜像, 镜像是一层层, 脚本一个个命令, 每个命令都是一层
# 创建一个dockerfile 文件,建议 Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "---------end--------"
CMD /bin/bash
#这里的每个命令, 就是镜像的一层
这个卷和外部一定有一个同步的目录
查看卷挂载的路径
未来使用的十分多, 通过会构建自己的镜像
构建镜像时没有挂载卷, 要手动镜像挂载 -v卷名: 容器内路径
数据卷容器
多个mysql 同步数据
# 启动3个容器
# 测试, 删除centos01, 查看centos02 和 centos03 是否还可以访问这个文件
# 测试依旧可以访问
多个mysql 实现数据共享
[root@zb test]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@zb test]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 --volumes-from mysql01 mysql:5.7
# 实现两个容器数据同步
结论:
容器之间配置信息的传递, 数据卷容器的生命周期一直持续到没有容器使用为止
一旦持久化到了本地, 本地的数据不会删除
DockerFile
Docker构建介绍
dockerfile 是用来构建docker镜像文件, 命令参数脚本
构建步骤:
- 编写一个dockerfile 文件
- docker build 构建称为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub, 阿里云镜像仓库)
DockerFile构建过程
基础知识:
-
每个保留关键字(指令)都是必须大写字母
-
执行从上到下顺序执行
-
/# 表示注释
-
每个指令都会创建提交一个新的镜像层, 并提交
dockerfile 是面向开发的, 要发布项目, 做镜像
步骤: 开发, 部署, 运营
DockerFile: 构建文件, 定义了一切的步骤
DockerImages: 通过DockerFile构建生成的镜像, 最终发布和运行的产品, 原来是jar, war
Docker容器: 容器就是镜像运行起来提供服务器
DockerFile的指令
FROM # 基础镜像, 一切从这里开始构建
MAINTAINER # 镜像是谁写的, 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤: tomcat镜像, 这个tomcat压缩包, 添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载目录
EXPOST # 暴露端口配置
CMD # 指定容器启动时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的名利, 可以追加命令
ONBUILD # 当构建一个被继承DockerFile 这个时候就会运行ONBUILD的指令, 触发指令
COPY # 类似ADD, 将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战测试
Docker Hub 中 99%镜像都是从这个基础镜像过来FROM scratch, 然后配置需要的软件和配置来进行的构建
创建一个自己的centos
# 1.编写Dockerfile的文件
[root@zb docker-file]# cat mydockerfile
FROM centos
MAINTAINER zb<421830611@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end---"
CMD /bin/bash
# 2. 通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] .
[root@zb docker-file]# docker build -f mydockerfile -t mycentos:0.1 .
# 3. 测试运行
对比: 之前的原生的centos
我们增加之后的景象
可以列出本地进行的变更历史
CMD 和 ENTRYPOINT 区别
ENTRYPOINT # 指定这个容器启动的时候要运行的名利, 可以追加命令
COPY # 类似ADD, 将我们文件拷贝到镜像中
测试cmd
# 编写dockerfile 文件
[root@zb docker-file]# vim dockerfile-cmd-test
FROM centos
CMD ["ls", "-a"]
# 构建镜像
[root@zb docker-file]# docker build -f dockerfile-cmd-test -t cmdtest .
# run运行, 发现ls -a 命令生效
[root@zb docker-file]# docker run 04f016b4925e
.
..
.dockerenv
bin
# 想追加一个命令 -l,想要有la -al效果
[root@zb docker-file]# docker run 04f016b4925e -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# cmd的清理下 -l 替换了 CMD["ls", "-a"]命令, -l 不是命令, 报错
测试 ENTRYPOINT
# 编写dockerfile 文件
[root@zb docker-file]# vim dockefile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls", "-a"]
# 构建镜像
[root@zb docker-file]# docker build -f dockefile-cmd-entrypoint -t entorypoint-test .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Running in ba2c39e2bfe3
Removing intermediate container ba2c39e2bfe3
---> 488df2cac5a4
Successfully built 488df2cac5a4
Successfully tagged entorypoint-test:latest
[root@zb docker-file]# docker run 488df2cac5a4
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 追加命令是直接拼接在ENTRYPOINT后面的
[root@zb docker-file]# docker run 488df2cac5a4 -l
total 0
drwxr-xr-x 1 root root 6 Sep 29 07:19 .
drwxr-xr-x 1 root root 6 Sep 29 07:19 ..
-rwxr-xr-x 1 root root 0 Sep 29 07:19 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Sep 29 07:19 dev
drwxr-xr-x 1 root root 66 Sep 29 07:19 etc
drwxr-xr-x 2 root root 6 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 6 Sep 15 14:17 lost+found
drwxr-xr-x 2 root root 6 Nov 3 2020 media
drwxr-xr-x 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x 147 root root 0 Sep 29 07:19 proc
dr-xr-x--- 2 root root 162 Sep 15 14:17 root
drwxr-xr-x 11 root root 163 Sep 15 14:17 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Sep 29 07:19 sys
drwxrwxrwt 7 root root 171 Sep 15 14:17 tmp
drwxr-xr-x 12 root root 144 Sep 15 14:17 usr
drwxr-xr-x 20 root root 262 Sep 15 14:17 var
实战: tomcat 镜像
-
准备镜像文件tomcat 压缩包, jdk的压缩包
-
编写dockerfile 文件, 官方命名
Dockerfile
, build 会自动寻找这个文件, 不需要-f 指定MAINTAINET zb<421830611@qq.com> COPY readme.txt /usr/local/readme.txt ADD jdk-8u11-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.22.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_11 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATLINA_HOME /usr/local/apache-tomcat-9.0.22 ENV CATLINA_PASH /usr/local/apache-tomcat-9.0.22 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/logs/catalina.out
-
构建镜像
# docker build -t zbtomcat .
-
启动镜像
[root@zb tomcat]# docker run -it -p 9090:8080 --name zbtomcat -v /tmp/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test -v /tmp/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.22/logs zbtomcat
-
访问测试
-
发布项目(由于做了卷挂载, 直接在本地编写项目就可以发布)
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> </web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>hello</title> </head> <body> Hello World!<br/> <% System.out.println("------my test web logs -----"); %> </body> </html>
发布自己的镜像
DockerHub
-
地址https://hub.docker.com/注册自己的账号
-
确定这个账号可以登录
-
在服务器上提交自己的镜像
[root@zb zhoubin]# 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@zb zhoubin]# docker login -u zzbbzb Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
-
登录完毕后就可以提交镜像, 就是一步docker push
# push 自己的镜像到服务器上 [root@zb zhoubin]# docker push zbtomcat Using default tag: latest The push refers to repository [docker.io/library/zbtomcat] 606a9fcc1aa2: Preparing 2580ff04a607: Preparing 255d8e8398a5: Preparing e7d27dc20f3e: Preparing 74ddd0ec08fa: Preparing denied: requested access to the resource is denied # 拒绝 # 镜像问题? [root@zb zhoubin]# docker push zb/zbtomcat:1.0 The push refers to repository [docker.io/zb/zbtomcat] An image does not exist locally with the tag: zb/zbtomcat # 处理, 增加tag, tag 要用户名/镜像名:tag [root@zb tomcat]# docker tag a42188e7ed03 zzbbzb/zbtomcat:1.0 [root@zb tomcat]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE zbtomcat latest a42188e7ed03 2 minutes ago 643MB zzbbzb/zbtomcat 1.0 a42188e7ed03 2 minutes ago 643MB entorypoint-test latest 488df2cac5a4 31 hours ago 231MB cmdtest latest 04f016b4925e 31 hours ago 231MB mycentos 0.1 c14351513f8f 32 hours ago 336MB zb/centos 1.0 85db2884db4a 36 hours ago 231MB tomcat_zb 1.0 56ec5de67d3c 2 days ago 684MB mysql 5.7 9f35042c6a98 2 days ago 448MB centos latest 5d0da3dc9764 2 weeks ago 231MB tomcat 9.0 62146f8bda84 2 weeks ago 680MB tomcat latest bb832de23021 2 weeks ago 680MB nginx latest ad4c705f24d3 2 weeks ago 133MB redis latest 02c7f2054405 3 weeks ago 105MB portainer/portainer latest 580c0e4e98b0 6 months ago 79.1MB # docker push 上去 [root@zb tomcat]# docker push zzbbzb/zbtomcat:1.0 The push refers to repository [docker.io/zzbbzb/zbtomcat] d2d29553047a: Pushing [=> ] 1.66MB/72.56MB beb0f6e2950e: Pushing [====> ] 1.361MB/15.41MB 1c2f3be1f20c: Pushing [> ] 1.594MB/324MB 4b5e8fca88ed: Pushed 74ddd0ec08fa: Pushing [> ] 2.196MB/231.3MB
阿里云镜像上
-
登录阿里云
-
找到容器镜像服务
-
创建命名空间
-
创建容器镜像
-
浏览阿里云文档
小结
Docker 网络(铺垫 容器编排 集群部署)
理解Docker0
清空所有images和容器
测试
三个网络
# docker是如何处理容器网络访问的?
# [root@zb /]# docker run -d -P --name tomcat01 tomcat
# 查看容器内部网络地址 ip addr, 发现容器启动的时候会得到一个 eth0@if116 ip地址, docker分配的
[root@zb tomcat]# 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
115: eth0@if116: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# linux 能不能ping通 容器内部
[root@zb tomcat]# 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.084 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.039 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.047 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.044 ms
# linux可以ping通docker容器内部
原理
- 每启动一个docker容器, docker就会给docker 容器分配一个ip, 只要安装了docker,就会有一个网卡docker0桥接模式, 使用的技术是veth-pair 技术
再次测试ip addr
- 再启动一个测试, 发现又多了一个网卡
# 我们发现这个容器带来的网卡, 都是一对对的
# veth-pair 就是一对的虚拟设备接口, 都是成对出现的, 一段连着协议, 一段彼此相连
# 有这个特性, veth-pair 充当一个桥梁,链接各种虚拟网络设备
# OpenStac, Docker 容器之间的链接, ovs的链接, 都是使用 veth-pair技术
-
测试tomcat01 和 tomcat02 是否可以ping通
[root@zb tomcat]# docker exec -it tomcat02 ping 172.17.0.1 PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data. 64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.075 ms 64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.051 ms # 结论: 容器和容器之间是可以互相ping通
绘制一个网络模型图:
结论: tomcat01 和 tomcat02 是公用的一个路由器docker0
所有的容器不指定网络的情况下, 都是docker0 路由, docker 会给我们容器分配一个默认可用的ip地址
小结
Docker 使用是LInux 的桥接,宿主机中是一个Docker容器的网桥 docker0
Docker中的所有的网络接口都是虚拟的, 虚拟的转发效率高
只要容器删除, 对应的一对网桥就没了
–link
思考一个场景, 项目不重启, 数据库ip换掉了, 可以通过名字来访问容器
[root@zb tomcat]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何解决
# 通过--link可以解决了网络连通问题
[root@zb tomcat]# docker run -d -P --name tomcat03 --link tomcat02 mytomcat
a513374a099c59c789df5c3a5cd2c65a4a3558ff0b4e2fc93ce02ed5bf9f9ce5
[root@zb tomcat]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.071 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.076 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.057 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=5 ttl=64 time=0.045 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=6 ttl=64 time=0.057 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=7 ttl=64 time=0.055 ms
--- tomcat02 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6121ms
rtt min/avg/max/mdev = 0.045/0.062/0.076/0.013 ms
# 方向可以ping通嘛
[root@zb tomcat]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
探究: inspect
其实这个tomcat03就是在本地配置了tomcat02配置
# 查看host配置
[root@zb tomcat]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 94488e4e8bb6
172.17.0.4 a513374a099c
本质探究: --link 就是在hosts配置中增加了172.17.0.3 tomcat02 94488e4e8bb6
现在玩Docker 不建议的–link
自定义网络, 不使用docker0
docker0问题: 不支持容器名链接访问
自定义网络
查看所有的docker 网络
网络模式
bridge: 桥接模式 docker0 搭桥(默认, 自己创建也适用birdge模式)
none: 不配置网络
host: 和宿主机共享网络
container: 容器网络连通(用的少)
测试
# 我们直接启动的命令 --net bridge, 这个就是我们的docker0
docker run -d -P --name tomcat01 mytomcat
docker run -d -P --name tomcat01 --net bridge mytomcat
# docker0特点: 默认域名不能访问, --link 可以打通连接
# 自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16 192.168.0.2 192.168.255.255
# --gateway 192.168.0.1
[root@zb tomcat]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
84219c18de814d86d92b12f51a3c5df4786ee92531c7c26f0516574c8e002648
[root@zb tomcat]# docker network ls
NETWORK ID NAME DRIVER SCOPE
609a25ab1e11 bridge bridge local
d0a1cdd793b6 host host local
84219c18de81 mynet bridge local
自己的网络就创建好了
[root@zb tomcat]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "84219c18de814d86d92b12f51a3c5df4786ee92531c7c26f0516574c8e002648",
"Created": "2021-10-01T19:49:51.739326047+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": {
"88451c50139b7134879879aba1c29fc10c52b5aaa2828bc8050591375e9a7a17": {
"Name": "tomcat_net_02",
"EndpointID": "5ef468aca35753f6ed899e817adbe1ccd6cc1376224208028f77585ef2ec09aa",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"9caf86f431f3fa336f5da303c4c6d2ae48d579b779457f8b282d1d5abbaa459b": {
"Name": "tomcat_net_01",
"EndpointID": "8b55ac78dd05ee2832932a3fe512985c33545c665016d12db102bace6ac6f964",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
# 再次测试ping链接
[root@zb tomcat]# docker exec -it tomcat_net_01 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.107 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.072 ms
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1041ms
rtt min/avg/max/mdev = 0.072/0.089/0.107/0.019 ms
# 现在不使用--link 也可以ping名字
[root@zb tomcat]# docker exec -it tomcat_net_01 ping tomcat_net_02
PING tomcat_net_02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat_net_02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from tomcat_net_02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from tomcat_net_02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.064 ms
--- tomcat_net_02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2037ms
rtt min/avg/max/mdev = 0.050/0.057/0.064/0.010 ms
自定义网络docker 已经帮我们维护好了队对应的关系, 推荐平时这样使用网络
好处:
redis - 不同的集群使用不同的网络,保证集群是安全和健康的
mysql - 不同的集群使用不同的网络, 保证集群是安全和健康的
网络连通
# 测试打通 tomcat01 - mynet
[root@zb tomcat]# docker network connect mynet tomcat01
# 连通之后就是将tomcat01 放到了mynet网络下
# 一个容器两个ip地址
# 类似于阿里云一个公网, 一个私网
# 01链接ok
[root@zb tomcat]# 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.069 ms
64 bytes from tomcat_net_01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.052 ms
# 02 是依旧打不通的
[root@zb tomcat]# docker exec -it tomcat02 ping tomcat_net_01
ping: tomcat_net_01: Name or service not known
结论: 假设要跨网络操作别人, 就需要使用docker net connet 连通
作业
Docker 安装 Nginx
# 1. 搜索镜像
[root@zb home]# docker search nginx
# 2. 下载镜像
[root@zb home]# docker pull nginx
# 3. 运行测试
[root@zb home]# docker run -d --name nginx01 -p 3389:80 nginx
[root@zb home]# curl localhost:3389
端口暴露的概念
Docker 安装tomacat
# 官方使用
docker run -it --rm tomcat:9.0
# 之前启动都是后台, 停止了容器之后, 容器还是可以访问到
# docker run -it --rm, 一般用来测试, 用完即删
# 下载在启动
docker pull tomcat:9.0
# 启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 测试访问没有问题
# 进入容器
[root@zb home]# docker exec -it tomcat01 /bin/bash
# 发现问题: 1. linux命令少了 2. 没有webapps
# 原因: 阿里云镜像的原因, 默认是最小镜像, 所有不必要的都剔除掉
部署es + kibana
# es 暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录, 挂载
# 启动 elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 启动linux就很卡 docker stats查看 cpu的状态
# 增加内存限制, 修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
使用kinana连接es? 思考网络如果才能连接过去