---
id: webserver-tomcat
title: "Tomcat"
shortTitle: "Tomcat"
track: webserver
trackTitle: "Web Server, Proxy & Load Balancer"
order: 3
level: important
status: published
estimatedMinutes: 30
prerequisites:
  - webserver-edge
next: webserver-iis
reviewedAgainst: 2026-10-12
sources:
  - title: "Tomcat 10.1 documentation"
    url: https://tomcat.apache.org/tomcat-10.1-doc/index.html
  - title: "Tomcat security considerations"
    url: https://tomcat.apache.org/tomcat-10.1-doc/security-howto.html
---

# Tomcat

Tomcat chạy ứng dụng Java kiểu servlet. Nó nghe HTTP. Đừng để cổng quản trị của nó ra Internet. Nginx hoặc load balancer đứng trước, như các bài proxy đã làm.

## Để làm gì

Chạy Tomcat trong lab, thấy trang mặc định, và biết file nào là app, file nào là cấu hình server.

## Gồm những gì

- Image `tomcat:10.1`, cổng 8080.
- `webapps` và file WAR.
- `server.xml` chỉ ở mức connector.

Không gồm viết servlet hay cấu hình JDBC pool cho production.

## Dùng khi nào

Một app Java được đóng gói WAR hoặc một thư mục trong `webapps`. Spring Boot thường nhúng Tomcat và không cần cài Tomcat riêng. Gặp process `catalina` trên server là bản cài riêng.

Đừng expose 8080 ra public nếu chưa có TLS và chưa tắt các app mẫu. Trang mặc định xác nhận server sống, đồng thời cho người lạ biết version.

## Kiến thức cốt lõi

`CATALINA_HOME` là thư mục cài. Connector HTTP mặc định trong image chính thức nghe 8080. App đặt ở `webapps/ROOT` thì path là `/`. `webapps/shop` thì path là `/shop`.

File WAR là zip đúng cấu trúc. Tomcat bung nó khi start, trừ khi bạn tắt auto deploy. Bạn sửa class trong thư mục đã bung mà không build lại WAR thì lần deploy sau đè mất bản sửa.

Manager và host-manager là webapp quản trị. Docs bảo mật của Tomcat nói rõ đừng để chúng lộ, và đừng dùng user mặc định. Image lab không cần các app đó.

## Lệnh và code mẫu

```bash
docker run -d --name lab-tomcat -p 8080:8080 tomcat:10.1
curl.exe -sS -o NUL -w "%{http_code}\n" http://127.0.0.1:8080/
docker rm -f lab-tomcat
```

## Thực hành

1. Chạy container. Đợi vài giây vì JVM khởi động.
2. Lấy status code trang `/`.
3. Xóa container. Không map cổng 8080 ra máy khác.

## Kết quả mong đợi

Status `200` hoặc `404` từ process Tomcat, không phải connection refused. Image 10.1 có lúc không kèm app ở `ROOT` và trả `404`. Cả hai đều có nghĩa là connector đã nghe. `docker rm -f` dọn xong.

## Checklist

- [ ] Cổng 8080 chỉ tới từ proxy, không mở security group ra `0.0.0.0/0`.
- [ ] Không để manager app với password trong file mẫu.
- [ ] App Spring Boot đã nhúng server thì không cài thêm Tomcat rồi deploy trùng.

## Thẻ ôn

### webserver-tomcat-war
kind: command
cue: Thả `shop.war` vào `webapps` thì app nằm ở `/shop`. Muốn gốc site thì tên file là `ROOT.war`. Sửa class trong thư mục đã bung mà không build lại WAR thì lần deploy sau đè mất.

Q: Bạn copy `shop.war` vào thư mục `webapps` của Tomcat. Người dùng vào URL nào để tới app? Muốn app nằm ở gốc site thì file phải tên gì? Sửa một class ngay trong thư mục Tomcat đã bung ra thì lần deploy sau còn giữ không?

A: Tên file, bỏ đuôi `.war`, thành context path. `shop.war` được phục vụ ở `/shop`. Muốn người dùng vào đúng gốc site, không có tiền tố, file phải là `ROOT.war`. Tomcat bung WAR thành một thư mục để chạy. Sửa class trong thư mục đã bung mà không đưa sửa đó vào bản WAR thì lần deploy sau, khi WAR được bung lại, bản sửa bị đè. Sửa ở nguồn, build lại WAR, rồi mới thả file mới vào.

### webserver-tomcat-expose
kind: trap
cue: Đừng mở cổng 8080 của Tomcat ra Internet khi chưa có TLS. Trang mặc định lộ version, manager với password mẫu không được để lộ. Cổng đó chỉ tới từ proxy.

Q: Có người mở security group cho cổng 8080 của Tomcat ra `0.0.0.0/0` để khỏi cấu hình proxy, và chưa gắn TLS. Vì sao không nên, và nếu app đã là Spring Boot có server nhúng thì còn thêm lỗi gì khi cài thêm Tomcat?

A: Cổng 8080 lúc đó là HTTP trần ra Internet. Trang mặc định của Tomcat cho người ngoài biết version đang chạy. Ứng dụng manager nếu còn password mẫu thì đó là cửa quản trị mở. Cổng 8080 chỉ nên nhận kết nối từ proxy đứng trước, nơi TLS và giới hạn địa chỉ được đặt. Spring Boot đã nhúng một server để chạy app thì không cài thêm một Tomcat rồi deploy cùng app một lần nữa. Hai server chồng lên nhau, port và đường deploy không còn một chỗ để mà sửa.

## Lỗi thường gặp

**WAR đặt sai tên.** `shop.war` bung thành `/shop`, không thành `/`. Muốn gốc site thì tên file là `ROOT.war`.

**Sửa `server.xml` trong container đang chạy.** Mất khi xóa container. Connector và app phải nằm trong image hoặc một file mount mà pipeline quản lý.

## Nguồn

1. [Tomcat 10.1 docs](https://tomcat.apache.org/tomcat-10.1-doc/index.html) — cấu trúc thư mục và connector.
2. [Security considerations](https://tomcat.apache.org/tomcat-10.1-doc/security-howto.html) — manager app và bề mặt mặc định.

## Tiếp theo

[IIS](./04-iis.md)
