https://github.com/samrocketman/docker-tomcat
A minimal security hardened Docker based Tomcat
https://github.com/samrocketman/docker-tomcat
Last synced: 4 months ago
JSON representation
A minimal security hardened Docker based Tomcat
- Host: GitHub
- URL: https://github.com/samrocketman/docker-tomcat
- Owner: samrocketman
- License: mit
- Created: 2022-11-12T15:49:30.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-11-14T02:24:42.000Z (over 3 years ago)
- Last Synced: 2025-11-16T21:05:56.055Z (8 months ago)
- Language: Dockerfile
- Size: 65.4 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Hardened minimal tomcat
Minimal tomcat container based on alpine meant for production use. TLS is
assumed to be provided externally by a load balancer.
- [Best practices](#best-practices)
- [Tomcat base image](#tomcat-base-image)
- [Application deployment](#application-deployment)
- [Example Application Dockerfile](#example-application-dockerfile)
- [Security Manager on by default](#security-manager-on-by-default)
- [Debug security manager](#debug-security-manager)
- [Disable Security Manager](#disable-security-manager)
- [Logging](#logging)
- [Filesystem layout](#filesystem-layout)
- [WebApp example](#webapp-example)
# Best practices
- Tomcat 9 running on openjdk11
- JRE by default but JDK available by Docker build arg.
- Configuration split between `CATALINA_HOME` and `CATALINA_BASE`.
- Docker practices
- Minimal alpine image.
- Final image size is 187MB.
- Compatible with both AMD64 and ARM architectures.
- PID 1 init program to handle process signals and child processes.
- Application starts as a normal system user instead of `root`.
- Web server starts in foreground.
- Web server logs to stdout and stderr to be handled by Docker instead of
writing logs to disk.
- Security hardened
- CIS Apache Tomcat 9 Benchmark; v1.1.0 - 12-18-2020
- Default tomcat apps removed.
- Tomcat security manager enabled with a sane initial security policy.
- Access restricted to tomcat user for configuration files
- `unpackWARs` and `autoDeploy` is disabled.
- Printing stack traces on error is disabled.
- TRACE HTTP method disabled.
- LockOutRealm is configured.
- Shutdown port is disabled.
- Shutdown command is randomized on boot.
- Connector security configured for HTTP
- Autodeployment on startup is disabled and `/webapps/ROOT` is defined for
manual deployment context in `server.xml`.
- Connection timeout set to 60 seconds.
# Tomcat base image
The tomcat base image can be viewed in [`Dockerfile`](Dockerfile).
docker build -t tomcat .
# Application deployment
* `/webapps/ROOT` - Extract your application WAR here.
* `/data` - If your app requires persistent data then `/data` is the location
assumed.
Security policy grants your app unconstrained access to the following locations.
```
/data
/dev/shm
/home/tomcat
/tmp
/var/tmp
/webapps/ROOT
```
Other locations will require a policy update.
Modify JVM behavior through the following environment variables.
* `CATALINA_OPTS`
* `JAVA_OPTS`
### Example Application Dockerfile
An example [application Dockerfile](example/Dockerfile) has also been provided.
Due to hardening automatic application deployment is disabled. You must extract
your war files as part of Docker image building.
> Note: The application Dockerfile uses `java xf *.war` to extract an
> application into `/webapps/ROOT`. This folder is the ROOT context for tomcat.
### Security Manager on by default
It is recommended to keep tomcat security hardening in place. By default a very
broad policy is applied which allows most actions within reason.
If you wish to overwrite this policy then overwrite the following policy file in
the tomcat container.
* [`/tomcat/conf/catalina.policy`](tomcat-base/conf/catalina.policy) (see also [Tomcat
docs][tomcat-security]).
### Debug security manager
You can enable more debug logs for security manager with the following
environment variable.
docker run -e CATALINA_OPTS=-Djava.security.debug=access ...
### Disable Security Manager
If you want to disable sandboxing entirely you can add the following line to the
end of your [application Dockerfile](example/Dockerfile) removing `-security`
option.
```dockerfile
CMD ["/opt/tomcat/bin/catalina.sh", "run"]
```
# Logging
All logs should push to stdout.
If your application has special logging enabled, then don't write to a file.
Instead, write the log to stdout and add a log prefix to differentiate instead.
* Logs with no prefix are assumed to be tomcat and its deployed application.
* Access logs are prefixed with `ACCESS:` followed by standard tomcat format.
For a `stdout` example, see `AccessLogValve` in
[`/tomcat/conf/server.xml`](tomcat-base/conf/server.xml).
# Filesystem layout
A filesystem layout has been generated highlighting the parts for tomcat
excluding Java.
See [filesystem-layout.txt](example/filesystem-layout.txt)
```bash
docker run -u root tomcat /bin/sh -c \
'apk add --no-cache tree &> /dev/null; \
rm -rf /var/cache/*; \
tree /home/tomcat /tmp /var/cache /var/tmp /webapps /tomcat /opt/tomcat' \
> example/filesystem-layout.txt
```
# WebApp example
You can try this out with Jenkins. At the root of this repository download
Jenkins.
curl -sSfLO https://get.jenkins.io/war-stable/2.361.3/jenkins.war
Build all prerequisite docker images.
docker build --build-arg java=jdk --build-arg all=true -t tomcat .
docker build -t sample -f example/Dockerfile .
Run Jenkins webapp in hardened tomcat container.
```bash
mkdir ../jenkins_home
JENKINS_HOME="$(cd ../jenkins_home; pwd)"
docker run -v "${JENKINS_HOME}:/data \
-e JENKINS_HOME=/jenkins --rm -p 8080:8080 sample
```
Visit http://localhost:8080/ to see your example app running. Use `CTRL+C` to
exit.
[tomcat-security]: https://tomcat.apache.org/tomcat-9.0-doc/security-manager-howto.html