前言

在之前的项目中,我基于五台虚拟机搭建了一套高可用架构(Keepalived + Nginx + Tomcat + MySQL)。随着容器化技术的普及,我决定将这些服务迁移到 Docker 中,实现更便捷的部署和管理。本文记录了将 Nginx 和 Tomcat 容器化的全过程,包括遇到的问题和解决方法,希望能为正在学习容器化的你提供参考。

环境准备

· 操作系统:Red Hat Enterprise Linux 9 (CentOS Stream 9) · Docker 版本:26.1.3 · 基础镜像:nginx:1.28.1、tomcat:11.0.18 · 项目文件:nginx.conf、tomcat.conf、testdb.jsp、server.xml

一、容器化 Nginx

1.1 准备配置文件

首先,将宿主机上 Nginx 的配置文件复制到工作目录:

mkdir -p /dockerdemo1
cp /etc/nginx/nginx.conf /dockerdemo1/
cp /etc/nginx/conf.d/tomcat.conf /dockerdemo1/
cd /dockerdemo1

1.2 编写 Dockerfile

创建一个名为 Dockerfile 的文件,内容如下:

FROM nginx:1.28.1
COPY nginx.conf /etc/nginx/nginx.conf
COPY tomcat.conf /etc/nginx/conf.d/
EXPOSE 80

这里直接将宿主机的配置文件覆盖到镜像中,这样构建出的镜像就包含了我们自定义的配置。

1.3 构建镜像

docker build -t my-nginx:1.0 .

构建成功后,会显示镜像 ID。

1.4 运行测试容器

docker run -d -p 8080:80 --name nginx-test my-nginx:1.0

映射宿主机的 8080 端口到容器的 80 端口,方便测试。

1.5 验证

curl http://localhost:8080

如果看到 Nginx 欢迎页,说明容器运行正常。你也可以通过浏览器访问 http://宿主机IP:8080 查看效果。

问题记录:一开始我直接访问 localhost:8080 时,总是得到宿主机 Nginx 的页面,后来发现是宿主机 Nginx 也监听了 80 端口。通过 systemctl stop nginx 停止宿主机服务后,问题解决。这也提醒我们:容器化前最好先关闭冲突的服务。

二、容器化 Tomcat

2.1 准备文件

Tomcat 需要 JSP 文件和配置文件。我复制了项目中的 testdb.jsp 和自定义的 server.xml 到工作目录的 tomcat 子目录:

mkdir -p /dockerdemo1/tomcat
cp testdb.jsp /dockerdemo1/tomcat/
cp server.xml /dockerdemo1/tomcat/
cd /dockerdemo1/tomcat

2.2 编写 Dockerfile

FROM tomcat:11.0.18
COPY testdb.jsp /usr/local/tomcat/webapps/ROOT/
COPY server.xml /usr/local/tomcat/conf/server.xml
EXPOSE 8080

关键点:Tomcat 默认的 Web 应用根目录是 webapps/ROOT,必须将 JSP 文件放到这个目录下才能直接通过 /文件名 访问。

2.3 构建镜像

docker build -t my-tomcat:1.0 .

2.4 运行容器

为了避免与宿主机原有的 Tomcat 端口冲突,我将容器的 8080 映射到宿主机的 8081 端口:

docker run -d -p 8081:8080 --name tomcat-test my-tomcat:1.0

2.5 验证

curl http://localhost:8081/testdb.jsp

如果返回 JSP 页面的内容(即使数据库连接失败),说明 Tomcat 已经正确加载了 JSP 文件。

2.6 踩坑记录

问题 1:webapps/ROOT 被覆盖成文件

第一次编写 Dockerfile 时,我错误地写成了:

COPY testdb.jsp /usr/local/tomcat/webapps/ROOT

注意:目标路径末尾没有加斜杠,导致 Docker 将 testdb.jsp 直接复制成了名为 ROOT 的文件,覆盖了原本的 ROOT 目录。正确的写法应该是 /usr/local/tomcat/webapps/ROOT/(以斜杠结尾,表示这是一个目录),或者指定完整文件名 /usr/local/tomcat/webapps/ROOT/testdb.jsp。

问题 2:大小写敏感

另一个常见错误是路径大小写。Tomcat 的根目录名是 ROOT(全大写),如果写成 Root 或 root,也会导致文件放错位置,Tomcat 找不到页面而返回 404。

问题 3:镜像标签不存在

拉取基础镜像时,tomcat:11.0.18 可能不存在,需要加上 -jdk21 或 -jre21 等后缀。建议先搜索官方仓库确认可用标签:

docker search tomcat
docker pull tomcat:11.0.18-jdk21

问题 4:网络问题导致拉取失败

在国内网络环境下,Docker Hub 访问不稳定。配置镜像加速器是关键:

{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}

配置后务必重启 Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker

三、验证容器间的网络连通(可选)

如果你已经将 Nginx 和 Tomcat 都容器化,并希望它们能够互相通信(例如 Nginx 反向代理到 Tomcat),可以通过创建自定义网络实现:

docker network create mynet
docker run -d --net mynet --name nginx-container my-nginx:1.0
docker run -d --net mynet --name tomcat-container my-tomcat:1.0

然后在 Nginx 配置文件中将 proxy_pass 指向 tomcat-container:8080,因为同一个网络内容器名可以作为主机名直接访问。

四、总结

通过本次实践,我成功将原本在虚拟机中手动配置的 Nginx 和 Tomcat 服务容器化。整个过程并不复杂,核心在于:

· 理解基础镜像的使用 · 正确复制配置文件到指定路径 · 注意目录和文件名的拼写

容器化带来了极大的便利:不再需要手动安装软件、配置环境,一条 docker run 命令就能启动完整服务,并且可以轻松分享给他人。

更多推荐