目录大纲
Part01-基础概念与理论知识
1.1 Docker基本概念
Docker是一种容器化技术,主要特点包括:
- 轻量级:相比虚拟机,容器更轻量级
- 快速启动:容器启动速度快
- 环境一致:保证开发、测试、生产环境一致
- 易于部署:容器易于部署和迁移
- 资源隔离:容器之间资源隔离
Docker的核心概念包括:
- 镜像:应用的只读模板
- 容器:镜像的运行实例
- 仓库:存储和分发镜像
- Dockerfile:构建镜像的脚本
- Compose:定义和运行多容器应用
更多视频教程www.fgedu.net.cn
1.2 Tomcat Docker镜像
Tomcat官方提供了Docker镜像,支持以下功能:
- 官方镜像:Tomcat官方维护的镜像
- 多版本支持:支持多个Tomcat版本
- 多架构支持:支持多种CPU架构
- 轻量级:基于Alpine Linux的轻量级镜像
- 易于使用:开箱即用
Tomcat Docker镜像的特点:
- 标准化:遵循Docker镜像标准
- 安全性:定期更新和修复漏洞
- 可定制:支持自定义配置
- 多标签:提供多个标签选择
- 文档完善:提供详细的使用文档
1.3 容器化原理
Docker容器化的工作原理:
- 镜像构建:使用Dockerfile构建镜像
- 镜像存储:将镜像存储在本地或仓库
- 容器启动:从镜像启动容器
- 容器运行:容器运行应用
- 容器停止:停止和删除容器
Docker容器化的优势:
- 环境一致:保证环境一致性
- 快速部署:快速部署和扩展
- 资源高效:提高资源利用率
- 易于管理:简化应用管理
- 支持CI/CD:支持持续集成和部署
1.4 容器化架构
Docker容器化的架构包括以下组件:
- Docker客户端:与Docker守护进程交互
- Docker守护进程:管理容器和镜像
- Docker镜像:应用的只读模板
- Docker容器:镜像的运行实例
- Docker仓库:存储和分发镜像
Docker容器化的设计原则:
- 单一职责:每个容器只运行一个应用
- 无状态:容器应该是无状态的
- 可移植:容器应该易于移植
- 可扩展:容器应该易于扩展
- 安全:容器应该是安全的
风哥提示:Docker容器化是现代应用部署的重要技术,合理使用Docker可以实现高效的容器化部署
Part02-生产环境规划与建议
2.1 Docker开发建议
在生产环境中,Docker开发的建议:
- 使用官方镜像:使用Tomcat官方镜像
- 优化镜像:优化镜像大小和层数
- 多阶段构建:使用多阶段构建减小镜像大小
- 安全扫描:定期扫描镜像漏洞
- 版本管理:管理镜像版本
2.2 Docker部署建议
Docker部署的建议:
- 配置资源:配置合理的CPU和内存限制
- 配置存储:配置持久化存储
- 配置网络:配置容器网络
- 配置日志:配置容器日志
- 配置监控:监控容器状态
2.3 运维建议
Docker运维的建议:
- 定期更新:定期更新镜像和容器
- 备份配置:备份容器配置和数据
- 监控资源:监控容器资源使用
- 日志管理:管理容器日志
- 故障处理:及时处理容器故障
学习交流加群风哥QQ113257174
Part03-生产环境项目实施方案
3.1 Docker镜像构建步骤
Docker镜像构建的步骤如下:
- 准备应用:准备Tomcat应用
- 编写Dockerfile:编写Dockerfile
- 构建镜像:使用docker build构建镜像
- 测试镜像:测试镜像
- 推送镜像:推送镜像到仓库
3.2 Docker容器部署步骤
Docker容器部署的步骤:
- 拉取镜像:拉取Tomcat镜像
- 配置参数:配置容器参数
- 启动容器:使用docker run启动容器
- 配置网络:配置容器网络
- 验证部署:验证容器部署
3.3 部署验证与测试
部署完成后,需要进行以下验证和测试:
- 容器状态:检查容器运行状态
- 应用访问:测试应用访问
- 性能测试:测试容器性能
- 安全测试:测试容器安全性
- 压力测试:测试容器稳定性
Part04-生产案例与实战讲解
4.1 Docker镜像构建实战
以下是Docker镜像构建的实战案例:
mkdir -p /Tomcat/docker/fgedu_app
cd /Tomcat/docker/fgedu_app
# 2. 创建简单应用
cat > index.html << EOF
FGEDU Tomcat Docker Application
This is a Tomcat application running in Docker container
Container ID:
Host:
Time:
EOF
# 3. 创建Dockerfile
cat > Dockerfile << EOF
# 使用Tomcat官方镜像
FROM tomcat:11.0.9-jdk17
# 维护者信息
LABEL maintainer="fgedu@fgedu.net.cn"
# 设置工作目录
WORKDIR /usr/local/tomcat
# 复制应用到webapps
COPY index.html /usr/local/tomcat/webapps/ROOT/
# 暴露端口
EXPOSE 8080
# 启动Tomcat
CMD ["catalina.sh", "run"]
EOF
# 4. 构建镜像
docker build -t fgedu/tomcat:11.0.9 .
# 输出示例:
Sending build context to Docker daemon 3.072kB
Step 1/6 : FROM tomcat:11.0.9-jdk17
11.0.9-jdk17: Pulling from library/tomcat
e1cde46db0e3: Pull complete
...
Digest: sha256:abcdef1234567890
Status: Downloaded newer image for tomcat:11.0.9-jdk17
---> abcdef123456
Step 2/6 : LABEL maintainer=”fgedu@fgedu.net.cn”
—> Running in 1234567890ab
—> defghij012345
Removing intermediate container 1234567890ab
Step 3/6 : WORKDIR /usr/local/tomcat
—> Running in 2345678901bc
—> efghij123456
Removing intermediate container 2345678901bc
Step 4/6 : COPY index.html /usr/local/tomcat/webapps/ROOT/
—> 9876543210ab
Step 5/6 : EXPOSE 8080
—> Running in 3456789012cd
—> 1234567890ab
Removing intermediate container 3456789012cd
Step 6/6 : CMD [“catalina.sh”, “run”]
—> Running in 4567890123de
—> 2345678901bc
Removing intermediate container 4567890123de
Successfully built 2345678901bc
Successfully tagged fgedu/tomcat:11.0.9
# 5. 查看镜像
docker images
# 输出示例:
REPOSITORY TAG IMAGE ID CREATED SIZE
fgedu/tomcat 11.0.9 2345678901bc 2 minutes ago 468MB
tomcat 11.0.9-jdk17 abcdef123456 2 days ago 468MB
# 6. 测试镜像
docker run -d –name fgedu_test -p 8080:8080 fgedu/tomcat:11.0.9
# 输出示例:
3456789012ef
# 7. 查看容器状态
docker ps
# 输出示例:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3456789012ef fgedu/tomcat:11.0.9 “catalina.sh run” 10 seconds ago Up 9 seconds 0.0.0.0:8080->8080/tcp fgedu_test
# 8. 测试应用
curl http://localhost:8080/
# 输出示例:
FGEDU Tomcat Docker Application
This is a Tomcat application running in Docker container
Container ID:
Host:
Time:
# 9. 停止并删除测试容器
docker stop fgedu_test
docker rm fgedu_test
# 输出示例:
fgedu_test
fgedu_test
4.2 Docker容器部署实战
以下是Docker容器部署的实战案例:
mkdir -p /Tomcat/fgdata/logs
mkdir -p /Tomcat/fgdata/webapps
# 2. 创建自定义配置
cat > /Tomcat/docker/fgedu_config/server.xml << EOF
EOF
# 3. 创建docker-compose.yml
cat > /Tomcat/docker/docker-compose.yml << EOF
version: '3.8'
services:
tomcat:
image: fgedu/tomcat:11.0.9
container_name: fgedu_tomcat
ports:
- "8080:8080"
volumes:
- /Tomcat/fgdata/webapps:/usr/local/tomcat/webapps
- /Tomcat/fgdata/logs:/usr/local/tomcat/logs
- /Tomcat/docker/fgedu_config/server.xml:/usr/local/tomcat/conf/server.xml
environment:
- CATALINA_OPTS=-Xms512m -Xmx1024m
- JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/"]
interval: 30s
timeout: 10s
retries: 3
networks:
- fgedu_network
networks:
fgedu_network:
driver: bridge
EOF
# 4. 启动容器
cd /Tomcat/docker
docker-compose up -d
# 输出示例:
Creating network "docker_fgedu_network" with driver "bridge"
Creating fgedu_tomcat ... done
# 5. 查看容器状态
docker-compose ps
# 输出示例:
NAME COMMAND SERVICE STATUS PORTS
fgedu_tomcat "catalina.sh run" tomcat running 0.0.0.0:8080->8080/tcp
# 6. 查看容器日志
docker-compose logs -f tomcat
# 输出示例:
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/11.0.9
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jul 21 2024 10:00:00 UTC
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number: 11.0.9.0
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 5.15.0-105-generic
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 17.0.8+7
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Eclipse Adoptium
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xms512m -Xmx1024m
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.security.egd=file:/dev/./urandom
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs=
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -classpath
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: org.apache.catalina.startup.Bootstrap start
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: wait
fgedu_tomcat | 21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: org.apache.catalina.startup.Bootstrap command line argument: start
# 7. 测试应用
curl http://localhost:8080/
# 输出示例:
FGEDU Tomcat Docker Application
This is a Tomcat application running in Docker container
Container ID:
Host:
Time:
# 8. 查看容器资源使用
docker stats fgedu_tomcat
# 输出示例:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
3456789012ef fgedu_tomcat 0.50% 512MiB / 2GiB 25.00% 1.2kB / 1.5kB 0B / 0B 45
# 9. 查看容器详细信息
docker inspect fgedu_tomcat
# 输出示例:
[
{
“Id”: “3456789012ef…”,
“Created”: “2024-07-21T11:00:00.000000000Z”,
“Path”: “catalina.sh”,
“Args”: [
“run”
],
“State”: {
“Status”: “running”,
“Running”: true,
“Paused”: false,
“Restarting”: false,
“OOMKilled”: false,
“Dead”: false,
“Pid”: 12345,
“ExitCode”: 0,
“Error”: “”,
“StartedAt”: “2024-07-21T11:00:00.000000000Z”,
“FinishedAt”: “0001-01-01T00:00:00Z”
},
“Image”: “sha256:2345678901bc…”,
“ResolvConfPath”: “/var/lib/docker/containers/3456789012ef…/resolv.conf”,
“HostnamePath”: “/var/lib/docker/containers/3456789012ef…/hostname”,
“HostsPath”: “/var/lib/docker/containers/3456789012ef…/hosts”,
“LogPath”: “/var/lib/docker/containers/3456789012ef…/3456789012ef-json.log”,
“Name”: “/fgedu_tomcat”,
“RestartCount”: 0,
“Driver”: “overlay2”,
“Platform”: “linux”,
“MountLabel”: “”,
“ProcessLabel”: “”,
“AppArmorProfile”: “”,
“ExecIDs”: null,
“HostConfig”: {
“Binds”: [
“/Tomcat/fgdata/webapps:/usr/local/tomcat/webapps”,
“/Tomcat/fgdata/logs:/usr/local/tomcat/logs”,
“/Tomcat/docker/fgedu_config/server.xml:/usr/local/tomcat/conf/server.xml”
],
“PortBindings”: {
“8080/tcp”: [
{
“HostIp”: “”,
“HostPort”: “8080”
}
]
},
“RestartPolicy”: {
“Name”: “unless-stopped”,
“MaximumRetryCount”: 0
}
},
“Config”: {
“Hostname”: “3456789012ef”,
“Domainname”: “”,
“User”: “”,
“AttachStdin”: false,
“AttachStdout”: false,
“AttachStderr”: false,
“ExposedPorts”: {
“8080/tcp”: {}
},
“Tty”: false,
“OpenStdin”: false,
“StdinOnce”: false,
“Env”: [
“CATALINA_OPTS=-Xms512m -Xmx1024m”,
“JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom”,
“PATH=/usr/local/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”,
“LANG=C.UTF-8”,
“JAVA_VERSION=17.0.8”,
“TOMCAT_VERSION=11.0.9”,
“TOMCAT_SHA512=abcdef1234567890”
],
“Cmd”: [
“catalina.sh”,
“run”
],
“Image”: “fgedu/tomcat:11.0.9”,
“Volumes”: null,
“WorkingDir”: “/usr/local/tomcat”,
“Entrypoint”: null,
“OnBuild”: null,
“Labels”: {
“com.docker.compose.config-hash”: “1234567890”,
“com.docker.compose.container-number”: “1”,
“com.docker.compose.oneoff”: “False”,
“com.docker.compose.project”: “docker”,
“com.docker.compose.service”: “tomcat”,
“com.docker.compose.version”: “3.8”,
“maintainer”: “fgedu@fgedu.net.cn”
}
}
}
]
4.3 Docker运维实战
以下是Docker运维的实战案例:
docker logs fgedu_tomcat
# 输出示例:
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/11.0.9
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jul 21 2024 10:00:00 UTC
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number: 11.0.9.0
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 5.15.0-105-generic
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 17.0.8+7
21-Jul-2024 11:00:00.000 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Eclipse Adoptium
# 2. 进入容器
docker exec -it fgedu_tomcat bash
# 输出示例:
root@3456789012ef:/usr/local/tomcat#
# 3. 在容器中执行命令
docker exec fgedu_tomcat cat /usr/local/tomcat/conf/server.xml
# 输出示例:
# 4. 重启容器
docker-compose restart tomcat
# 输出示例:
Restarting fgedu_tomcat … done
# 5. 停止容器
docker-compose stop tomcat
# 输出示例:
Stopping fgedu_tomcat … done
# 6. 启动容器
docker-compose start tomcat
# 输出示例:
Starting fgedu_tomcat … done
# 7. 删除容器
docker-compose down
# 输出示例:
Stopping fgedu_tomcat … done
Removing fgedu_tomcat … done
Removing network docker_fgedu_network
# 8. 查看容器资源使用
docker stats –no-stream
# 输出示例:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
3456789012ef fgedu_tomcat 0.50% 512MiB / 2GiB 25.00% 1.2kB / 1.5kB 0B / 0B 45
# 9. 查看容器进程
docker top fgedu_tomcat
# 输出示例:
UID PID PPID C STIME TTY TIME CMD
root 12345 12344 0.5 11:00 ? 00:00:05 java -Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
# 10. 查看容器端口映射
docker port fgedu_tomcat
# 输出示例:
8080/tcp -> 0.0.0.0:8080
# 11. 查看容器网络
docker network inspect docker_fgedu_network
# 输出示例:
[
{
“Name”: “docker_fgedu_network”,
“Id”: “1234567890abcdef”,
“Created”: “2024-07-21T11:00:00.000000000Z”,
“Scope”: “local”,
“Driver”: “bridge”,
“EnableIPv6”: false,
“IPAM”: {
“Driver”: “default”,
“Options”: null,
“Config”: [
{
“Subnet”: “172.18.0.0/16”,
“Gateway”: “172.18.0.1”
}
]
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
“ConfigOnly”: false,
“Containers”: {
“3456789012ef…”: {
“Name”: “fgedu_tomcat”,
“EndpointID”: “1234567890abcdef”,
“MacAddress”: “02:42:ac:12:00:02”,
“IPv4Address”: “172.18.0.2/16”,
“IPv6Address”: “”
}
},
“Options”: {},
“Labels”: {
“com.docker.compose.network”: “fgedu_network”,
“com.docker.compose.project”: “docker”,
“com.docker.compose.version”: “3.8”
}
}
]
# 12. 备份容器配置
docker inspect fgedu_tomcat > /Tomcat/docker/fgedu_tomcat_backup.json
# 输出示例:
(无输出,文件已创建)
# 13. 查看备份文件
cat /Tomcat/docker/fgedu_tomcat_backup.json | head -20
# 输出示例:
[
{
“Id”: “3456789012ef…”,
“Created”: “2024-07-21T11:00:00.000000000Z”,
“Path”: “catalina.sh”,
“Args”: [
“run”
],
“State”: {
“Status”: “running”,
“Running”: true,
“Paused”: false,
“Restarting”: false,
“OOMKilled”: false,
“Dead”: false,
“Pid”: 12345,
“ExitCode”: 0,
“Error”: “”,
“StartedAt”: “2024-07-21T11:00:00.000000000Z”,
“FinishedAt”: “0001-01-01T00:00:00Z”
}
更多学习教程公众号风哥教程itpux_com
Part05-风哥经验总结与分享
5.1 Docker常见问题与解决方案
在Docker运维中,常见的问题及解决方案如下:
- 容器启动失败:检查镜像和配置
- 容器无法访问:检查端口映射和网络配置
- 容器资源不足:检查CPU和内存限制
- 容器日志丢失:配置日志驱动和日志轮转
- 容器数据丢失:使用数据卷持久化数据
5.2 生产环境Docker最佳实践
在生产环境中,Docker的最佳实践包括:
- 使用官方镜像:使用官方或可信的镜像
- 定期更新:定期更新镜像和容器
- 配置资源限制:配置合理的CPU和内存限制
- 使用数据卷:使用数据卷持久化数据
- 监控容器:监控容器状态和资源使用
5.3 Docker运维经验分享
以下是一些Docker运维的经验分享:
- 镜像优化:优化镜像大小和层数
- 日志管理:配置日志驱动和日志轮转
- 备份策略:定期备份容器配置和数据
- 安全加固:扫描镜像漏洞,加固容器安全
- 自动化运维:使用自动化工具管理容器
风哥提示:Docker容器化是现代应用部署的重要技术,合理使用Docker可以实现高效的容器化部署和运维
from Tomcat视频:www.itpux.com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
