视频链接:Docker | 狂神说
环境说明
Windows For Docker + WSL2
概念
Docker是什么?
百度百科:百度百科
Docker 是一个开源的平台,它利用操作系统级虚拟化技术来打包和运行应用程序。通过使用容器化技术,Docker 提供了一种标准化的方式,在任何环境中一致地部署、管理和扩展应用程序。
Docker架构图
-
**Docker 客户端(Docker Client)**是用户与 Docker 守护进程(Docker Daemon)进行交互的主要工具。它通常指的是命令行界面(CLI),但也可以指其他形式的客户端,如图形用户界面(GUI)、编程语言的 SDK 或者 REST API 客户端。Docker 客户端发送指令给守护进程来管理镜像、容器、网络和卷等资源。
-
DOCKER_HOST 是一个环境变量,用于指定 Docker 客户端连接到哪个 Docker 守护进程(Docker daemon)。通过设置 DOCKER_HOST,你可以控制 Docker 命令行工具(CLI)或 SDK 连接到本地或远程的 Docker 守护进程。这对于管理多个 Docker 环境、跨机器部署容器或者在没有直接安装 Docker 的机器上执行 Docker 操作非常有用。
-
Docker 守护进程(Docker Daemon),通常简称为 Docker daemon 或 dockerd,是 Docker 架构中的核心组件之一。它是一个常驻后台的进程,负责管理 Docker 对象如镜像、容器、网络和卷等。守护进程监听来自 Docker 客户端(CLI 或其他 API 客户端)的请求,并执行相应的操作,例如创建、启动、停止或删除容器。
-
Docker 容器是基于 Docker 镜像创建的运行实例,它提供了一个轻量级、可移植且自包含的环境来运行应用程序。容器将应用程序与其依赖项打包在一起,确保其在任何环境中都能一致地运行。每个容器都是独立的,拥有自己的文件系统、网络栈和进程空间,从而实现了良好的隔离性。
-
Docker 镜像是一个轻量级、独立且可执行的软件包,它包含了运行某个应用程序所需的一切:代码、运行时环境、库、环境变量和配置文件。镜像是构建容器的基础,每个容器都是从镜像启动的一个实例。Docker 镜像使得开发者可以在任何环境中一致地部署应用,确保了“在我的机器上能正常工作”的问题不再出现。
-
Docker Registry 是一个存储和分发 Docker 镜像的服务。它允许用户上传(推送)他们构建的镜像,并从中下载(拉取)镜像用于部署或进一步开发。Docker Registry 可以是公共的,如 Docker Hub,也可以是私有的,供组织内部使用。通过 Registry,团队可以更方便地管理和共享容器化应用程序。
Docker主要组成部分
1. Docker 客户端 (Docker CLI)
- 定义:这是用户与 Docker 守护进程(Docker Daemon)进行交互的主要工具。它通常指的是命令行界面(CLI),但也可以指其他形式的客户端,如图形用户界面(GUI)、编程语言的 SDK 或 REST API 客户端。
- 功能:
- 发送指令给守护进程以管理镜像、容器、网络和卷等资源。
- 提供丰富的命令集来执行各种操作,如构建 (
docker build
)、推送 (docker push
)、拉取 (docker pull
) 镜像,启动 (docker run
)、停止 (docker stop
) 容器等。
2. Docker 守护进程 (Docker Daemon)
- 定义:Docker Daemon 是一个常驻后台的进程,负责管理 Docker 对象如镜像、容器、网络和卷等。它监听来自 Docker 客户端的请求,并执行相应的操作。
- 功能:
- 管理镜像、容器、网络和卷的生命周期。
- 提供 RESTful API 接口,允许第三方工具和服务与 Docker 进行交互。
- 使用 Linux 控制组(cgroups)和命名空间(namespaces)来为容器设置资源限制,确保良好的隔离性和安全性。
3. Docker 注册表 (Docker Registry)
- 定义:这是一个存储和分发 Docker 镜像的服务。它可以是公共的,如 Docker Hub,也可以是私有的,供组织内部使用。
- 功能:
- 存储由开发者构建的 Docker 镜像,以便可以在不同环境中重复使用。
- 支持对镜像进行标签(tags)管理,帮助追踪不同版本的应用程序。
- 提供权限管理机制,确保只有授权用户才能推送或拉取特定镜像。
4. Docker 镜像 (Image)
- 定义:Docker 镜像是一个轻量级、独立且可执行的软件包,它包含了运行某个应用程序所需的一切:代码、运行时环境、库、环境变量和配置文件。
- 特点:
- 不可变性:一旦创建,镜像内容不能被修改;如果需要更新,则需基于现有镜像创建新的镜像。
- 分层存储:镜像由多个只读层(layers)组成,每一层代表镜像的一个特定状态或更改。
- 标准化:通过
Dockerfile
定义如何构建一个镜像,这为应用程序提供了一种标准化的打包方式。
5. Docker 容器 (Container)
- 定义:容器是从镜像创建的运行实例。它提供了一个轻量级、可移植且自包含的环境来运行应用程序。
- 特点:
- 隔离性:每个容器都在自己的命名空间中运行,拥有独立的文件系统、进程 ID、用户 ID 和网络接口。
- 轻量化:容器共享宿主机的操作系统内核,因此比虚拟机更轻量,启动速度更快,并且占用较少的资源。
- 可移植性:由于容器包含了应用程序及其所有依赖项,所以可以在不同的环境中无缝迁移。
6. Docker Compose
- 定义:Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件(
docker-compose.yml
),你可以配置应用程序的服务,并使用一条命令启动所有服务。 - 功能:
- 定义多个服务之间的关系和依赖。
- 简化了复杂应用的部署流程,特别是对于微服务架构的应用。
7. Docker Swarm
- 定义:Docker 自带的集群管理和编排工具,可以管理多个 Docker 主机组成的集群。
- 功能:
- 创建和管理 Docker 节点集群。
- 实现服务的自动发现、负载均衡和服务扩展。
8. Docker 网络 (Networking)
- 定义:Docker 提供了多种网络驱动来管理容器之间的通信以及容器与外部世界的连接。
- 类型:
- 桥接网络(Bridge Network):默认情况下,容器连接到一个名为
bridge
的网络。 - 主机网络(Host Network):容器直接使用宿主机的网络栈。
- 覆盖网络(Overlay Network):用于跨多个 Docker 守护进程的容器之间通信。
- 桥接网络(Bridge Network):默认情况下,容器连接到一个名为
9. Docker 卷 (Volume)
- 定义:卷是 Docker 中用于持久化数据的一种机制。它们提供了独立于容器生命周期的数据存储方式。
- 功能:
- 持久化容器内的数据,即使容器被删除,数据仍然保留。
- 共享数据:允许多个容器访问同一个卷中的数据。
10. Docker 插件 (Plugins)
- 定义:插件用于扩展 Docker 的核心功能,例如添加新的网络驱动、卷驱动或其他特性。
- 功能:
- 增强 Docker 的功能,使其更加灵活和强大。
安装教程(Windows11)
安装步骤:
-
打开PowerShell作为管理员:可以通过在开始菜单中搜索
PowerShell
,然后右键点击它并选择“以管理员身份运行”。 -
启用WSL2 和 虚拟机平台:
- 在PowerShell中执行以下命令:
C:\Windows\System32\dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart C:\Windows\System32\dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestar
- 在PowerShell中执行以下命令:
-
重启计算机:重启计算机使上述更改生效。
-
设置默认的WSL版本为2:
- 在PowerShell中输入并执行:
wsl --set-default-version 2
- 在PowerShell中输入并执行:
-
下载并安装Docker Desktop:访问Docker官网下载适用于Windows的Docker Desktop安装程序并安装。
-
启动Docker Desktop:安装完成后,启动Docker Desktop并根据提示完成设置。
-
查看Docker是否正常运行:
docker --version docker run hello-world
可自行配置阿里云镜像加速器
问题解决:
解决镜像不能下载问题:
windows 安装docker_windows docker下载-CSDN博客
Docker Hub访问不了:
我出现这个问题,排查了半天,发现是加速器问题
我下载的是这个:apnetwork
使用教程
命令文档:https://docs.docker.com/reference/
常用命令:
docker --version #显示docker版本信息
docker --info # 显示docker的系统信息,包括镜像和容器数量
docker --help # 帮助命令
docker 命令 --help # 帮助命令
镜像命令
官方文档:Docker image
docker images ls
PS C:\Users\Lenovo> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d2c94e258dcb 20 months ago 13.3kB
### 输出解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
### 可选项
-a, --all # 列出所有镜像(包括悬空和未标记的镜像)
--digests #显示摘要信息(Digests)
-f, --filter filter #根据提供的条件过滤输出
--format string #使用自定义模板格式化输出:
'table': 以表格格式打印输出,并包含列标题(默认)
'table TEMPLATE': 使用给定的 Go 模板以表格格式打印输出
'json': 以 JSON 格式打印输出
'TEMPLATE': 使用给定的 Go 模板打印输出
#关于使用模板格式化输出的更多信息,请参阅 https://docs.docker.com/go/formatting/
--no-trunc #不截断输出(显示完整信息)
-q, --quiet #只显示镜像 ID
--tree #以树状结构列出多平台镜像(实验性功能)
常用命令:
docker image ls : 查看全部镜像
docker search 镜像 : 查找
docker pull 镜像:下载镜像( docker image pull | Docker Docs)
docker rmi : 删除镜像
容器命令
注意:必须先下载镜像,才能运行容器
下载镜像
docker pull centos
新建容器并启动
官方文档:docker run
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字
-d 后台方式运行,ja nohup
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P 随机指定端口
启动并进入容器
docker run -it centos /bin/bash
查看运行中的容器
docker ps
#docker ps命令
-a # 列出当前正在运行的容器+历史运行过的容器
-n=? #显示最近创建的容器(?是表示显示几个)
-q #只显示容器的编号
查看曾经运行过的容器
docker ps -a
退出容器
exit #直接停止容器并退出到主机
Ctrl + P + Q #容器不停止退出
删除容器
docker rm 容器id #删除指定容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) #删除所有容器
docker ps -a -q|xargs docker rm #删除所有容器
启动容器
docker start 容器id
重启容器
docker restart 容器id
停止容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
常用其他命令:
后台启动
docker run -d centos /bin/bash
问题:通过后台启动容器,发现centos停止了
答案: docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止(即使有前台进程,例如nginx,如果nginx启动后发现没有提供服务,也会立刻停止,就是没有程序了)
查看日志
docker logs
### 输出结果
PS C:\Users\Lenovo> docker logs"docker logs" requires exactly 1 argument.
See 'docker logs --help'.
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
### 可选
Options:
--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 logs -f -t --tail number 容器id
### 问题
发现没有日志输出:
--自己编写shell脚本:
(1)docker run -d centos /bin/sh -c 脚本
(2)docker logs -f -t --tail number 容器id
查看容器中进程信息
docker top 容器id
查看镜像元数据
docker inspect 容器id
###PS C:\Users\Lenovo> docker inspect d2a4619249c5
[
{
"Id": "d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a",
"Created": "2025-01-24T07:02:52.721200131Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo happy;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1731,
"ExitCode": 0,
"Error": "",
"StartedAt": "2025-01-24T07:02:52.86930599Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a/hostname",
"HostsPath": "/var/lib/docker/containers/d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a/hosts",
"LogPath": "/var/lib/docker/containers/d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a/d2a4619249c5e16fbca3d5ec3f63511ae09d2fa31fa9f37f06b024587eb4fe1a-json.log",
"Name": "/determined_hypatia",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "bridge",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"ConsoleSize": [
13,
106
],
"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",
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": [],
"BlkioDeviceWriteBps": [],
"BlkioDeviceReadIOps": [],
"BlkioDeviceWriteIOps": [],
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": [],
"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",
"/sys/devices/virtual/powercap"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/accb45a7ce8467253f6aadfb117c44d99501cc5913e2bcc6685e3a32f62c1c84-init/diff:/var/lib/docker/overlay2/a1d31160bfdf442acdb6d93c031a2e754585228a3d4d88da74a1f9b8d0f73e5a/diff",
"MergedDir": "/var/lib/docker/overlay2/accb45a7ce8467253f6aadfb117c44d99501cc5913e2bcc6685e3a32f62c1c84/merged",
"UpperDir": "/var/lib/docker/overlay2/accb45a7ce8467253f6aadfb117c44d99501cc5913e2bcc6685e3a32f62c1c84/diff",
"WorkDir": "/var/lib/docker/overlay2/accb45a7ce8467253f6aadfb117c44d99501cc5913e2bcc6685e3a32f62c1c84/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "d2a4619249c5",
"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 happy;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": "a824215687398e1c83cb35ac6341854de3d091b7a496de0ad9f2d91f385337ca",
"SandboxKey": "/var/run/docker/netns/a82421568739",
"Ports": {},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "4dca6640fa35ab2c50740577fe9306ac82a749d06a43f6bb744a975db085395a",
"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,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null,
"NetworkID": "dd25f4f3216eeedd203889d3e347fc0baea75b53caa9de5af771e11c49353c09",
"EndpointID": "4dca6640fa35ab2c50740577fe9306ac82a749d06a43f6bb744a975db085395a",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": null
}
}
}
}
]
进入当前正在运行的容器
#docker exec -it 容器id bashShell
#docker attach 容器id
区别:
– docker exec : 进入容器后开启一个新的终端,可以在里面操作
– docker attach : 进入容器正在执行的终端,不会启动新的进程
# 通常容器是以后台方式运行的,若想要进入容器修改配置
### 方式一:
PS C:\Users\Lenovo> #docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2a4619249c5 centos "/bin/sh -c 'while t…" 17 minutes ago Up 17 minutes determined_hypatia
PS C:\Users\Lenovo> #docker exec -it d2a4619249c5 /bin/bash
[root@d2a4619249c5 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
### 方式二:
PS C:\Users\Lenovo> #docker attach d2a4619249c5
正在执行当前代码
从容器内拷贝文件到主机上
[!IMPORTANT]
docker cp 容器id:容器内路径 目的主机路径
PS C:\Users\Lenovo\test> #docker cp 0fb7995c2965:/home/test.java ./
Successfully copied 1.54kB to C:\Users\Lenovo\test\.\
小结
# 常用命令
run # 从镜像创建并运行一个新的容器
exec # 在运行中的容器中执行命令
ps # 列出所有容器
build # 从Dockerfile构建镜像
pull # 从仓库下载镜像
push # 将镜像上传到仓库
images # 列出镜像
login # 登录到仓库进行认证
logout # 从仓库登出
search # 在Docker Hub中搜索镜像
version # 显示Docker版本信息
info # 显示系统范围的信息
# 管理命令
ai* # 向Gordon提问 - Docker代理(注:此条目可能是特定环境下的自定义命令)
builder # 管理构建过程
buildx* # Docker Buildx(用于高级构建功能)
compose* # Docker Compose(用于多容器应用的编排)
container # 容器管理
context # 上下文管理
debug* # 进入任何镜像或容器的shell进行调试
desktop* # Docker Desktop相关命令(测试版)
dev* # Docker开发环境
extension* # 管理Docker扩展
feedback* # 在终端内直接提供反馈
image # 镜像管理
init* # 创建与Docker相关的项目启动文件
manifest # 管理Docker镜像清单和清单列表
network # 网络管理
plugin # 插件管理
sbom* # 查看基于包的软件物料清单(SBOM)对于一个镜像
scout* # Docker Scout(具体用途未知,可能为特定服务或工具)
system # Docker系统管理
trust # 管理Docker镜像的信任
volume # 卷管理
# Swarm命令
swarm # 管理Swarm集群
# 其他命令
attach # 将本地标准输入、输出和错误流附加到正在运行的容器
commit # 根据容器的更改创建新的镜像
cp # 在容器和本地文件系统之间复制文件/文件夹
create # 创建一个新的容器但不启动它
diff # 检查容器文件系统中文件或目录的变化
events # 获取服务器的实时事件
export # 将容器的文件系统导出为tar归档文件
history # 显示镜像的历史
import # 从tarball导入内容以创建文件系统镜像
inspect # 返回Docker对象的低级信息
kill # 终止一个或多个正在运行的容器
load # 从tar归档文件或STDIN加载镜像
logs # 获取容器的日志
pause # 暂停一个或多个容器内的所有进程
port # 列出容器的端口映射,或指定映射
rename # 重命名容器
restart # 重启一个或多个容器
rm # 移除一个或多个容器
rmi # 移除一个或多个镜像
save # 将一个或多个镜像保存为tar归档文件(默认情况下流向STDOUT)
start # 启动一个或多个已停止的容器
stats # 显示容器资源使用情况的实时流
stop # 停止一个或多个正在运行的容器
tag # 创建指向SOURCE_IMAGE的新标签TARGET_IMAGE
top # 显示容器中运行的进程
unpause # 解除暂停一个或多个容器内的所有进程
update # 更新一个或多个容器的配置
wait # 阻塞直到一个或多个容器停止,然后打印它们的退出代码
# 全局选项
--config string # 客户端配置文件的位置 (默认 "C:\\Users\\Lenovo\\.docker")
-c, --context string # 使用连接到守护程序的上下文名称 (覆盖DOCKER_HOST环境变量和默认上下文)
-D, --debug # 启用调试模式
-H, --host list # 要连接的守护程序套接字
-l, --log-level string # 设置日志级别 ("debug", "info", "warn", "error", "fatal") (默认 "info")
--tls # 使用TLS;由--tlsverify隐含
--tlscacert string # 仅信任由该CA签名的证书 (默认 "C:\\Users\\Lenovo\\.docker\\ca.pem")
--tlscert string # TLS证书文件路径 (默认 "C:\\Users\\Lenovo\\.docker\\cert.pem")
--tlskey string # TLS密钥文件路径 (默认 "C:\\Users\\Lenovo\\.docker\\key.pem")
--tlsverify # 使用TLS并验证远程方
-v, --version # 打印版本信息并退出
部署Nginx
# 1.搜索镜像 search 建议去docker hub
# 2.下载镜像 docker pull nginx
# 3.运行 docker run -d --name nginx01 -p 3344:80 nginx
# 4.测试 http://localhost:3344/
# 5.进入容器:docker exec -it nginx01 /bin/bash
可以访问到你所部署的nginx服务器(windows访问步骤):
1.查看本机ip地址:以管理员身份打开命令行工具,输入
ipconfig
2.在浏览器中搜索:http://本机ip地址:3344/ 即可访问到nginx
解释:
docker run -d --name nginx01 -p 3344:80 nginx
当docker中的nginx01运行起来,本地就相当于一个服务器,端口为3344,那么就意味着在任何一台设备中,通过ip地址可以找到本机(服务器),通过端口映射可以找到docker中的nginx
部署Tomcat
# 官方的使用
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:9.0
#测试访问没有问题
http://本机ip地址:3355/
# 进入容器
docker exec -it tomcat01 /bin/bash
# 发现问题:1.Linux命令少了 2.没有webapps 阿里云镜像的原因。默认最小的镜像,所有的不必要的都剔除掉。
# 保证最小可运行环境
# 解决方法:将webapps.dist目录下的所有文件复制到webapps目录下
root@b532969c54d6:/usr/local/tomcat/webapps.dist# cp -r * ../webapps/
curl工具下载
#步骤 1:安装 Chocolatey
-- 以管理员身份打开 PowerShell:
-- 按 Win + X 键,选择 Windows PowerShell (管理员) 或 终端 (管理员)。
-- 运行以下命令来安装 Chocolatey:
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
#步骤 2:使用 Chocolatey 安装 curl
choco install curl -y
# 步骤3:将curl.exe添加到环境变量
#步骤3:验证安装:
-- 关闭并重新打开 PowerShell 窗口,然后运行:
curl.exe --version
可视化
-
portainer(先用这个)
(powershell中的换行符是反引号)
docker run -d -p 8088:9000 ` --restart=always ` -v /var/run/docker.sock:/var/run/docker.sock ` --privileged=true ` portainer/portainer
-
Rancher
portainer
什么是portainer?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
访问链接:http://本机ip地址:8088/
Docker镜像讲解
镜像是什么?
指的是一个轻量级、独立且可执行的软件包,包含运行某个应用或服务所需的所有内容,包括代码、运行时环境、系统工具、库和设置等
所有的应用,直接打包成为一个Docker镜像,就可以直接跑起来!
如何得到镜像?
- 从远程仓库下载
- 拷贝
- 自己制作镜像
Docker镜像加载原理
Docker镜像加载原理主要基于联合文件系统(UnionFS)和分层存储技术。
Docker的镜像实际上由一层一层的文件系统组成。
Docker镜像的基本概念
一个Docker镜像是由多个只读层组成的,每一层代表了镜像的一个变更。这些层是叠加在一起的,形成最终的文件系统视图。当创建一个新的容器时,会在镜像的顶层添加一个可写的层,所有对容器的修改都会在这个可写层中进行。
联合文件系统(UnionFS)
Docker使用了一种称为联合文件系统的技术来实现镜像的分层结构。联合文件系统允许将多个目录合并成一个单一的虚拟文件系统。在Docker中,每个镜像层都是这个虚拟文件系统中的一个独立层,它们可以被不同的容器共享。
分层结构
bootfs(boot file system):这是Docker镜像的最底层,包含了引导加载器(bootloader)和内核(kernel)。当启动容器时,bootfs会被加载到内存中,并且一旦内核被加载完毕,bootfs就会被卸载以释放资源。所有的镜像都共享这一层。
rootfs(root file system):位于bootfs之上,包含了一个典型Linux系统中的标准目录和文件,如
/dev
,/proc
,/bin
,/etc
等。rootfs可以根据不同的操作系统发行版有所不同,比如Ubuntu、CentOS等。
镜像加载过程
当Docker需要加载一个镜像时,它会执行以下步骤:
查找镜像:首先,Docker会在本地的镜像仓库中查找该镜像。如果找不到,则会去远程的镜像仓库(例如Docker Hub)查找并下载镜像。
下载镜像:如果镜像不在本地,Docker会从远程仓库下载镜像。由于镜像是分层的,所以下载也是按层进行的。如果某些层已经存在于本地,则不会重复下载。
加载镜像:下载完成后,Docker会将镜像的各个层解压并存储在Docker的存储驱动中。然后,根据这些层构建出完整的文件系统视图。
创建容器:当创建容器时,Docker会在镜像的最上层添加一个可写的层。这个可写层允许容器运行时进行修改,而不会影响到底层的镜像层。
分层的好处
- 资源共享:由于镜像层是可以共享的,因此多个容器可以共享同一基础镜像的不同层,节省磁盘空间。
- 快速部署:因为只需要传输发生变化的部分,所以镜像的传输速度更快,部署也更迅速。
- 版本控制:镜像层的变化可以看作是一次提交,这使得我们可以轻松地回滚到之前的某个状态。
存储引擎
为了管理镜像层的堆栈并保证多镜像层对外展示为统一的文件系统,Docker使用了不同的存储引擎。常见的存储引擎包括AUFS、Overlay2、Device Mapper、Btrfs以及ZFS等。每种存储引擎都有其特定的性能特点和适用场景。
实际操作示例
当你使用命令
docker pull ubuntu
下载一个名为ubuntu的镜像时,实际上是在下载多个镜像层。每个镜像层可能对应着操作系统的基础部分、软件包安装、配置文件等。下载完成后,你可以使用docker images
查看已有的镜像列表,并用docker run
命令基于这些镜像创建新的容器实例。通过
docker image inspect <image_name>
命令,你可以查看镜像的具体信息,包括它的层结构等细节。
commit镜像
[!IMPORTANT]
docker commit 提交容器成为一个新的副本 # 命令和git原理类似 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# step1:运行tomcat镜像
docker run -it -p 8080:8080 tomcat:9.0
# step2:进入容器内部,修改配置文件
docker exec -it 容器id /bin/bash
root@b7b1b360aaa9:/usr/local/tomcat# cp -r webapps.dist/* webapps
# step3:通过commit提交镜像
docker commit -a="kkkwang2" -m="add webapps application" b7b1b360aaa9 tomcat02:1.0
PS C:\Users\Lenovo> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 2ab0c1a9784f 9 seconds ago 487MB
容器数据卷
什么是容器数据卷(Volume)?
在 Docker 中,数据卷是一种用于持久化存储数据的机制。它独立于容器的生命周期,即使容器被删除,数据卷中的数据依然存在。
数据卷容器是指专门用来管理数据卷的容器。通常,我们会创建一个专门的数据卷容器来挂载和共享数据卷,以便其他容器可以使用这些数据卷。
总结一句话:容器的持久化和同步操作,容器间也是可以数据共享的
使用数据卷
# 挂载 -v 数据卷 docker run -it -v .\test\test:/home centos /bin/bash # 查看容器详细信息 docker inspect 容器id
容器外和容器内挂载的目录内容保持同步
进一步测试:
-
将容器停止
-
修改主机内挂载目录内容
-
开启容器
-
查看容器挂载目录内容
好处:我们修改只需要在本地修改即可,容器内会自动同步!
安装MySQL
下载SQLyog:
# 1.获取镜像
docker pull mysql:5.7
# 2.运行容器,需要做数据挂载
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
docker run -d -p 3310:3306 -v .\test\test\mysql\conf:/etc/mysql/conf.d -v .\test\test\mysql\data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功后 在本地用SQLyog测试一下
# SQLyog-连接到服务器的3310 --- 3310和容器内的3306映射
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok
# 容器删除,挂载到本地的数据卷依旧没有丢失,这就实现了数据持久化
具名挂载和匿名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
#查看所有卷的情况
docker volume ls
# 这种就是匿名挂载,我们 -v 只写了容器内的路径,没有写容器外的路径!
# 具名挂载
# 通过 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 查看卷信息
PS C:\Users\Lenovo> docker volume inspect juming-nginx
[
{
"CreatedAt": "2025-02-05T06:20:38Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
如果是使用wsl的,在资源管理器中查找如下,就能快速找到数据卷存放地址了
\\wsl$\docker-desktop\mnt\docker-desktop-disk\data\docker\volumes
通过具名挂载可以方便找到卷
然后确定是具名挂载还是匿名挂载呢?
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v .\容器外路径:容器内路径 #指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 可以改变读写权限
-ro readonly 只读
-rw readwrite 可读可写
# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
# ro:挂载出来的文件内容只能通过宿主机来操作,容器内部是无法操作的
# rw:默认
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
DockerFile概述
Dockerfile 就是用来构建Docker镜像的构建文件,其实就是一段命令脚本,通过这个脚本可以生成镜像
镜像是一层一层的,脚本一个个的命令,每个命令都是一层
dockerfile1内容如下
# 使用官方 CentOS 镜像作为基础镜像
FROM centos:latest
# 定义卷
VOLUME ["/volume01", "/volume02"]
CMD echo "---end---"
# 默认命令:启动一个交互式的 bash shell
CMD ["/bin/bash"]
构建镜像
PS C:\Users\Lenovo\docker-home\docker-test-volume> # docker build -f .\dockerfile1 -t kkkwang2/centos:1.0
测试自己写的镜像
docker run -it kkkwang2/centos:1.0 /bin/bash
在容器内挂载目录创建文件,看宿主机挂载目录有没有同步
成功同步!
数据卷容器
多个容器同步数据
测试
# 启动centos01
docker run -it --name centos01 kkkwang2/centos:1.0
# 启动centos02,并与centos02保持同步
docker run -it --name centos02 --volumes-from centos01 kkkwang2/centos:1.0
# 启动centos03,并与centos03保持同步
docker run -it --name centos03 --volumes-from centos01 kkkwang2/centos:1.0
centos03也自动同步了centos01和centos02里面的内容
删除centos01后,centos02和centos03依旧可以访问这个文件,并且centos02和centos03中的挂载目录下的内容保持同步
三个容器相当于挂载在宿主机的同一个目录下
多个mysql容器实现同步
# 启动mysql01
docker run -d -p 3310:3306 -v .\test\test\mysql\conf:/etc/mysql/conf.d -v .\test\test\mysql\data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动mysql02
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
#mysql01与mysql02两个容器数据同步
数据卷容器的生命周期
-
创建数据卷容器
- 这是数据卷容器的“出生”阶段。
- 我们通过
docker create
或docker run
命令创建一个容器,并指定要使用的数据卷。 - 例如:
这里我们创建了一个名为docker create -v /volume01 --name data_container centos
data_container
的容器,并定义了一个名为/volume01
的数据卷。
-
使用数据卷容器
- 创建好数据卷容器后,其他容器可以通过
--volumes-from
参数来挂载这个数据卷容器的数据卷。 - 例如:
这个命令启动了一个新的容器,并从docker run -it --rm --volumes-from data_container centos bash
data_container
挂载了/volume01
数据卷。
- 创建好数据卷容器后,其他容器可以通过
-
读写数据
- 在挂载了数据卷的容器中,你可以像操作普通文件系统一样读写数据卷中的文件。
- 例如,在新启动的容器中,你可以执行以下命令来查看或修改
/volume01
目录下的文件:echo "Hello, World!" > /volume01/hello.txt cat /volume01/hello.txt
-
停止和删除容器
- 当你停止并删除挂载了数据卷的容器时,数据卷本身不会被删除。
- 例如:
即使你删除了这些容器,docker stop <container_id> docker rm <container_id>
data_container
中的数据卷仍然存在。
-
删除数据卷容器
- 如果你不再需要数据卷容器及其数据卷,可以通过以下命令删除它们:
注意:docker rm -v data_container
-v
参数会同时删除未被其他容器使用的数据卷。
- 如果你不再需要数据卷容器及其数据卷,可以通过以下命令删除它们:
-
数据卷的持久性
- 数据卷是独立于容器存在的,因此即使删除了所有使用该数据卷的容器,只要数据卷容器没有被删除,数据卷中的数据仍然保留。
- 如果你希望手动删除某个数据卷,可以使用以下命令:
docker volume rm <volume_name>
举个生活中的例子
想象一下你有一个带锁的保险箱(数据卷),而你有几个不同的房间(容器)。你把保险箱放在其中一个房间里(创建数据卷容器),然后你可以在其他房间里通过钥匙(--volumes-from
)打开这个保险箱并存取东西(读写数据)。
- 创建保险箱(数据卷容器):你买了一个保险箱并把它放在一个房间里。
- 使用保险箱(挂载数据卷):你用钥匙打开保险箱,取出或存放物品。
- 关闭房间(停止容器):你离开房间,但保险箱里的东西还在。
- 删除房间(删除容器):即使你拆掉了房间,保险箱还在原地,里面的物品也不会丢失。
- 删除保险箱(删除数据卷容器):如果你不再需要保险箱了,你可以选择彻底销毁它,这样里面的物品也会消失。
DockerFile
什么是Dockerfile?
Dockerfile 是一个文本文件,其中包含了构建 Docker 镜像所需的所有指令。这些指令按照特定的顺序排列,定义了如何从一个基础镜像开始,逐步构建出一个新的 Docker 镜像。每个指令会在镜像中创建一个新的层(layer),这些层组合在一起构成了最终的镜像。
通过编写 Dockerfile,开发者可以自动化地创建一致且可重复使用的环境,确保在不同的机器或平台上运行的应用程序具有相同的配置和依赖项。这极大地简化了应用程序的部署过程,并提高了开发、测试和生产环境之间的一致性。
dockerfile是面向开发的,我们以后开发项目就需要编写dockerfile文件
构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每一个指令都会创建提交一个镜像层
- DockerFile:构建文件,定义了一切步骤,源代码
- DockerImages: 通过DockerFile构建生成的镜像,最终发布运行产品
- Docker容器:容器就是运行起来提供服务器
Dockerfile文件
- FROM:指定基础镜像,必须是第一个非注释命令,格式为
FROM <image>:<tag>
。- LABEL:为生成的镜像添加元数据标签信息,如
LABEL maintainer="admin@example.com"
。- RUN:执行命令并创建新的镜像层,常用于安装软件包,例如
RUN apt-get update && apt-get install -y vim
。- CMD:提供启动容器时默认执行的命令和参数,但可以被docker run命令行参数覆盖。只能有一条CMD指令生效。
- EXPOSE:声明运行时容器提供服务的端口,如
EXPOSE 80
。- ENV:设置环境变量,在容器内可通过$VARIABLE引用,如
ENV MY_NAME World
。- ADD:从主机复制文件、目录或远程文件URL到容器中,并自动解压tar文件。
- COPY:类似于ADD,但不会自动解压缩文件或处理远程URLs。
- ENTRYPOINT:配置容器启动后执行的命令,并且不可被docker run命令行参数覆盖,适合用来构建不可改变的容器。
- VOLUME:创建一个挂载点,将主机或其他容器的一个目录共享给容器使用。
- USER:设置启动容器时使用的用户名或UID。
- WORKDIR:配置工作目录,后续的RUN, CMD, ENTRYPOINT命令都会在此目录下执行。
FROM #基础镜像,一切从这里开始
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #docker镜像构建的时候需要运行的命令
ADD #步骤:tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR #镜像的工作目录
VOLUME #容器卷,挂载点目录位置
EXPOSE #暴露端口
RUN #运行
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile这个时候就会运行ONBUILD的指令,触发指令
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量
练习:创建一个自己的centos
# 1.编写Dockerfile文件
FROM centos:7
MAINTAINER kkkwang2
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup && \
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
yum clean all && \
yum makecache
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]
docker build -f mydockerfile-centos -t mycentos:7 .
#构建结果:
[+] Building 54.0s (9/9) FINISHED docker:desktop-linux
=> [internal] load build definition from mydockerfile-centos 0.0s
=> => transferring dockerfile: 482B 0.0s
=> WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 2) 0.0s
=> WARN: LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" form 0.0s
=> WARN: JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior rela 0.0s
=> WARN: MultipleInstructionsDisallowed: Multiple CMD instructions should not be used in the same st 0.0s
=> WARN: JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior rela 0.0s
=> WARN: MultipleInstructionsDisallowed: Multiple CMD instructions should not be used in the same st 0.0s
=> WARN: JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior rela 0.0s
=> [internal] load metadata for docker.io/library/centos:7 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
#=> [1/5] FROM docker.io/library/centos:7 0.0s
#=> CACHED [2/5] WORKDIR /usr/local 0.0s
#=> [3/5] RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup && c 44.7s
#=> [4/5] RUN yum -y install vim 6.9s
#=> [5/5] RUN yum -y install net-tools 1.4s
=> exporting to image 0.8s
=> => exporting layers 0.8s
=> => writing image sha256:9a26892417b26691cc04203f25da31f5f880d662bc0c8ba22ea7faf1e0faf093 0.0s
=> => naming to docker.io/library/mycentos:7
#测试
PS C:\Users\Lenovo\docker-home\dockerfile> docker run -it mycentos:7 /bin/bash
[root@98291ee0a2e9 local]# pwd
/usr/local
[root@98291ee0a2e9 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 9 bytes 1046 (1.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@98291ee0a2e9 local]# vim test
[root@98291ee0a2e9 local]#
# 查看镜像构建历史
# docker history 镜像
PS C:\Users\Lenovo\docker-home\dockerfile> docker history sha256:9a26892417b26691cc04203f25da31f5f880d662bc0c8ba22ea7faf1e0faf093
IMAGE CREATED CREATED BY SIZE COMMENT
9a26892417b2 8 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 8 minutes ago CMD ["/bin/sh" "-c" "echo \"---end---\""] 0B buildkit.dockerfile.v0
<missing> 8 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
<missing> 8 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 8 minutes ago RUN /bin/sh -c yum -y install net-tools # bu… 221MB buildkit.dockerfile.v0
<missing> 8 minutes ago RUN /bin/sh -c yum -y install vim # buildkit 276MB buildkit.dockerfile.v0
<missing> 8 minutes ago RUN /bin/sh -c mv /etc/yum.repos.d/CentOS-Ba… 532MB buildkit.dockerfile.v0
<missing> 10 minutes ago WORKDIR /usr/local 0B buildkit.dockerfile.v0
<missing> 10 minutes ago ENV MYPATH=/usr/local 0B buildkit.dockerfile.v0
<missing> 10 minutes ago MAINTAINER kkkwang2 0B buildkit.dockerfile.v0
<missing> 3 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 3 years ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
PS C:\Users\Lenovo\docker-home\dockerfile>
使用dockerfile构建镜像
[!IMPORTANT]
docker build -f dockerfile文件名 -t 镜像名:[TAG]
CMD和ENTRYPOINT的区别
- CMD 提供容器启动时的默认命令及其参数,但可以被 docker run 命令覆盖。
- ENTRYPOINT 配置容器启动时固定的可执行文件,并允许通过 docker run 传递额外参数来修改其行为。
实战:Tomcat镜像
1.准备镜像文件:tomcat压缩包、jdk压缩包
omcat:Tomcat下载
JDK8:jdk8
2.编写Dockerfile文件
FROM centos:7
# 使用 LABEL 替代 MAINTAINER
LABEL maintainer="kkkwang2"
# 复制 readme.txt 文件到容器中
COPY readme.txt /usr/local/readme.txt
# 添加适用于 Linux 的 JDK 和 Tomcat 压缩包并解压
ADD jdk-8u441-linux-i586.tar.gz /usr/local/
ADD apache-tomcat-9.0.98.tar.gz /usr/local/
# 重命名解压后的目录(如果需要)
RUN mv /usr/local/jdk1.8.0_441 /usr/local/jdk8
RUN mv /usr/local/apache-tomcat-9.0.98 /usr/local/apache-tomcat
# 更新 yum 源并安装 vim 和 32 位库支持
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup && \
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
yum clean all && \
yum makecache && \
yum -y install vim glibc.i686 libstdc++.i686
# 设置工作目录
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 设置环境变量
ENV JAVA_HOME /usr/local/jdk8
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat
ENV CATALINA_BASH /usr/local/apache-tomcat
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
# 暴露端口
EXPOSE 8080
# 启动 Tomcat 并保持容器运行
CMD ["sh", "-c", "$CATALINA_HOME/bin/startup.sh && tail -F $CATALINA_HOME/logs/catalina.out"]
3.构建镜像
docker build -t mytomcat .
4.启动镜像
docker run -d -p 3333:8080 --name mytomcat01 `
-v .\docker-home\dockerfile\tomcat\test:/usr/local/apache-tomcat/webapps/test `
-v .\docker-home\dockerfile\tomcat\logs:/usr/local/logs `
mytomcat
5.测试
1.在test目录下新建WEB-INF和index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome to My Web App</title>
</head>
<body>
<h1>Welcome to My Simple Web Application!</h1>
<p>This is a simple JSP page.</p>
<p>The current date and time is: <%= new java.util.Date() %></p>
<h2>Links:</h2>
<ul>
<li><a href="hello">Go to Hello Servlet</a></li>
</ul>
</body>
</html>
2.在WEB-INF中创建web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Simple Web Application</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
发布自己的镜像
官方文档:Docker push
前提条件
- Docker 已安装并运行:确保 Docker 已正确安装并在你的机器上运行。
- Docker 登录凭证:如果你要推送镜像到 Docker Hub 或其他需要认证的 Docker Registry,你需要登录。
步骤
1. 登录 Docker Registry
如果你要推送镜像到 Docker Hub,首先需要登录:
docker login
系统会提示你输入 Docker Hub 的用户名和密码。
2. 标记镜像
在推送镜像之前,你需要给镜像打标签(tag),以便指定目标仓库和镜像名称。格式如下:
docker tag <本地镜像名>:<标签> <仓库地址>/<命名空间>/<镜像名>:<标签>
<本地镜像名>
:你本地构建的镜像名称。<标签>
:镜像的标签,通常是latest
或者版本号。<仓库地址>
:Docker Registry 的地址,如果是 Docker Hub 可以省略。<命名空间>
:通常是你在 Docker Hub 上的用户名或组织名。<镜像名>
:你在仓库中的镜像名称。
docker tag mytomcat kkwang2/mytomcat:latest
3. 推送镜像
使用 docker push
命令将标记好的镜像推送到 Docker Registry:
docker push <仓库地址>/<命名空间>/<镜像名>:<标签>
docker push kkwang2/mytomcat:latest
Docker小结
Docker 网络
官方文档:Docker|network
什么是Docker网络?
Docker网络是指容器之间以及容器与外部系统之间进行通信的方式。
原理
Docker使用了虚拟网络来隔离容器,并通过不同的网络驱动实现容器间的通信。默认情况下,Docker会创建一个名为 docker0 的桥接网络(bridge network),所有新启动的容器都会连接到这个默认的桥接网络上。
–Link(已弃用)
它允许一个容器与另一个容器进行通信,并通过别名解析容器名称。然而,随着 Docker 网络功能的增强(如自定义桥接网络和覆盖网络),–link 已经被标记为已弃用,并且不再推荐使用。
1.两个容器建立连接 tomcat03 --> tomcat02
docker run -d -P --name tomcat03 --link tomcat02 tomcat
2.测试连通
docker exec -it tomcat03 ping tomcat02
# 问题
PS C:\Users\Lenovo> docker exec -it tomcat03 ping tomcat02
OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown
What's next:
Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug tomcat03
Learn more at https://docs.docker.com/go/debug-cli/
#解决方法:
-- 进入容器内部输入:
apt-get update && apt-get install -y iputils-ping
-- 再次输入:
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.404 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.201 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.163 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.158 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=5 ttl=64 time=0.176 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=6 ttl=64 time=0.172 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=7 ttl=64 time=0.177 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=8 ttl=64 time=0.255 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=9 ttl=64 time=0.161 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=10 ttl=64 time=0.200 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=11 ttl=64 time=0.167 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=12 ttl=64 time=0.163 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=13 ttl=64 time=0.160 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=14 ttl=64 time=0.159 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=15 ttl=64 time=0.159 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=16 ttl=64 time=0.171 ms
^C
--- tomcat02 ping statistics ---
16 packets transmitted, 16 received, 0% packet loss, time 15575ms
rtt min/avg/max/mdev = 0.158/0.190/0.404/0.060 ms
# 反向连接不可以ping通
docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
# 查看网络
PS C:\Users\Lenovo> docker network ls
NETWORK ID NAME DRIVER SCOPE
a7f4b01af50f bridge bridge local
415a75655af9 host host local
6946f32282b4 none null local
PS C:\Users\Lenovo> docker network inspect a7f4b01af50f
[
{
"Name": "bridge",
"Id": "a7f4b01af50fc4a9a99f9abfccbb04eb1536aaacba30e3731329d9a8b52100f0",
"Created": "2025-02-08T05:00:00.765969212Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1" # docker0
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"23d09c537aa25a6b4cabf99ace995795e82105674ab562dc3a134d2c68101025": {
"Name": "tomcat03",
"EndpointID": "c5a58f7afe55e9d78d55467b8680b37c5f193e2e991c858fc65aacd60c721a0d",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"8734a5b207f3ca95fb57f0841b9396eca443f5ebdc8c6973418402af9fdf9f2d": {
"Name": "tomcat02",
"EndpointID": "35be13d81fbf7b63202d648a5f7ef1f8310eda538f214774b0de3d5f4ea683cf",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"c19d248ea5157098fd1e933c58216b767d46af90163a2315a68237450cefc024": {
"Name": "tomcat01",
"EndpointID": "20c58ac7fa0ce74c1ff5783fc64861d3aa1cc1313c4a6f8817c3644a4b3d2f8d",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
为什么Tomcat02可以ping通Tomcat03?
自定义网络
查看所有的docker网络
docker network ls
网络模式
bridge : 桥接docker(默认)
none:不配置网络
host:和宿主机共享网络
container:容器网络连通 !(用的少!局限很大)
自定义网络命令
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
PS C:\Users\Lenovo> docker network ls
NETWORK ID NAME DRIVER SCOPE
d5212bca3cd3 bridge bridge local
415a75655af9 host host local
9c220d44b666 mynet bridge local
6946f32282b4 none null local
测试(tomcat)
# 由于我的tomcat镜像没有ping指令,我使用Dockerfile创建了自己的镜像
docker build -t mytomcat .
FROM tomcat
# 使用 LABEL 替代 MAINTAINER
LABEL maintainer="kkkwang2"
RUN apt-get update && apt-get install -y iputils-ping
# 1.编写自己的网络
PS C:\Users\Lenovo> docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 2.启动两个tomcat
PS C:\Users\Lenovo> docker run -d -P --name tomcat02 --net mynet mytomcat
e5bc00372ce2671c0a0f9ce4524e00d4f92ebb2ad19b92808ac44e6855e782c2
PS C:\Users\Lenovo> docker run -d -P --name tomcat03 --net mynet mytomcat
79f10552dbcafb33fc1b838067f8e7e3986e60a4d4580d7c4411a9eb51e3542b
# 2.查看自己写的网络
PS C:\Users\Lenovo> docker network inspect mynet
[
{
"Name": "mynet",
"Id": "9c220d44b666f6d63f6b3b0e1050e69f45d201db352dbcc07bda6f2fc2540966",
"Created": "2025-02-08T11:15:49.791238875Z",
"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": {
"79f10552dbcafb33fc1b838067f8e7e3986e60a4d4580d7c4411a9eb51e3542b": {
"Name": "tomcat03",
"EndpointID": "75585f857af080d1585e7659029bb32b812be7d286b4c925ac5b16839619fadd",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"e5bc00372ce2671c0a0f9ce4524e00d4f92ebb2ad19b92808ac44e6855e782c2": {
"Name": "tomcat02",
"EndpointID": "4fbec39ef7ad2552f9224502f5e88ef2655c581c03bac1e88db6fe9119cf86a0",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 4.测试连通
PS C:\Users\Lenovo> docker exec -it tomcat02 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.395 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.155 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.180 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2115ms
rtt min/avg/max/mdev = 0.155/0.243/0.395/0.107 ms
PS C:\Users\Lenovo> docker exec -it tomcat03 ping tomcat02
PING tomcat02 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.246 ms
64 bytes from tomcat02.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.165 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.165/0.205/0.246/0.040 ms
网络连通
docker run -d -P --name tomcat01 mytomcat
docker network connect mynet tomcat01 # 打通了mynet --- tomcat01
PS C:\Users\Lenovo\docker-home\dockerfile\mytomcat> docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.040 ms
64 bytes from tomcat02.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.040 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1036ms
rtt min/avg/max/mdev = 0.040/0.040/0.040/0.000 ms
What's next:
Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug tomcat01
Learn more at https://docs.docker.com/go/debug-cli/
SpringBoot微服务打包Docker镜像
1.构建SpringBoot项目
2.打包应用
3.编写dockerfile
FROM java:openjdk-8u111-jdk-alpine
LABEL authors="kkkwang2"
COPY *.jar .\app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java", "-jar", ".\app.jar"]
4.构建镜像
docker build -t helloworld .
[+] Building 1.3s (7/7) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 206B 0.0s
=> WARN: JSONArgsRecommended: JSON arguments recommended for ENTRYPOINT to prevent unintended behavio 0.0s
=> [internal] load metadata for docker.io/library/java:openjdk-8u111-jdk-alpine 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.7s
=> => transferring context: 20.68MB 0.6s
=> [1/2] FROM docker.io/library/java:openjdk-8u111-jdk-alpine 0.1s
=> [2/2] COPY *.jar .app.jar 0.3s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:85f29eea389558daed4637e4e11f521404352d0c23ea4d2eec3c4c127e2ab6d2 0.0s
=> => naming to docker.io/library/helloworld 0.0s
1 warning found (use docker --debug to expand):
- JSONArgsRecommended: JSON arguments recommended for ENTRYPOINT to prevent unintended behavior related to OS signals (line 7)
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/i177l2cycp1fabxomd1723clq
注意:
1.本篇文章中的图片来自百度百科以及视频截图(侵删)!
2.在Windows中换行符以及文件路径写法与在Linux中不同
3.如有错误,欢迎指正!