8

I'm running tomcat in docker, but I can't see the logs. They are written to various log files under tomcat/logs, but I can't see them when tomcat is running in a docker container.

Here is my Dockerfile

FROM tomcat:7-jre8
COPY target/MYAPP.war /usr/local/tomcat/webapps/MYAPP.war
RUN ["/usr/local/tomcat/bin/catalina.sh", "start"]

This is how I build image & start container from it:

docker build -t MYAPP .
docker run -it --rm -p 8080:8080 --name MYAPP MYAPP

My app creates log file: /var/log/MYAPP.log after tomcat deploys MYAPP.war

How should I amend Dockerfile and which command should I use to run it ("docker run ...") so that right after starting the container MYAPP using the oneliner "docker run -it --rm -p 8080:8080 --name MYAPP MYAPP" the contents of /var/log/MYAPP.log would be printed to stdout?

I tried to add to Dockerfile the command below but it didn't help.

CMD tail -f /usr/local/MYAPP.log
Software Engineer
  • 15,457
  • 7
  • 74
  • 102
Oleg
  • 121
  • 1
  • 1
  • 4

7 Answers7

8

Following needs to be done to direct all logs to stdout:

  1. Similar to the answer given to How to stop application logs from logging into catalina.out in Tomcat, you can pass the CATALINA_OUT environment variable value as /dev/stdout. This will make sure all tomcat logs are sent to stdout.
  2. In logging.properties of catalina base, keep java.util.logging.ConsoleHandler and remove other handlers.
  3. Change the configuration of the logging in your application (For example, log4j2.xml file if you are using log4j2) to send logs to stdout. In log4j2, you can do it by using the console appender.
Ritesh
  • 7,472
  • 2
  • 39
  • 43
7

You seem to be confused about the different between RUN and CMD.

The RUN directive is used to run commands during the build process. It is never executed in a container. When you write...

RUN ["/usr/local/tomcat/bin/catalina.sh", "start"]

...this means that during the docker build process, Docker will start tomcat, but will immediately kill it and continue to build your image.

Only the CMD and ENTRYPOINT directives define commands that will be run when you boot an image with docker run. So possibly you want something like:

CMD /usr/local/tomcat/bin/catalina.sh start && tail -f /usr/local/MYAPP.log
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Oh, thanks, I see difference between RUN and CMD now, interesting! I tried but now it says: Successfully built 3a1ccf47c08c Successfully tagged MYAPP:latest Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /docker-java-home/jre Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. tail: cannot open '/usr/local/MYAPP.log' for reading: No such file or directory tail: no files remaining – Oleg Dec 08 '17 at 13:51
  • The error message "no such file or directory" seems pretty clear. Possibly the file hasn't been created by the time you run `tail -f`. Consider using `tail -F` instead, which should wait for the file to appear. – larsks Dec 08 '17 at 13:52
  • Thanks, it helped! – Oleg Dec 08 '17 at 14:47
  • 2
    This isn't really recommended. If you simply use `catalina.sh run` rather than `start` then the logs will be redirected to stdout where you'll find them easy to access using the docker tools (`docker logs ...`) – Software Engineer Jun 06 '18 at 22:19
  • Really the point of this answer was the difference between `RUN` and `CMD`. – larsks Jun 06 '18 at 23:51
4

Ok, your dockerfile should contain something like this**:

from tomcat:7-jre8
copy target/myapp.war /usr/local/tomcat/webapps/myapp.war
entrypoint ["/bin/bash", "/usr/local/tomcat/bin/catalina.sh", "run"]

Then you can run a container based on this image with something like:

docker run -itd -p 8080:8080 --name aname animage

So, the catalina 'run' command is designed to redirect all logs to stdout. This is useful to us because this is how docker works. If you run the container now you'll be able to run:

docker logs aname

The output will be anything that has been sent to stdout within the container. You can do with this what you wish, but common strategies are transporting the logs to logstash, splunk, or a thousand other places, or you could write them to a file (though that last one is mostly for developers).

** Of course, you'll have to change the entrypoint to match the specifics of your installation. And the run command I've shown here is for a daemon.

Original problem: Your original problems were based on a common mistake; you were trying to run the tomcat server during provisioning (building the image). You actually want to run the server when you run the container. So, I've removed the run and replaced it with an entrypoint, which is the correct way of running a command like this. Finally, cmd is for passing parameters to the entrypoint, which we don't need in this case.

Finally, I've chosen to use cataline.sh run rather than start because run is designed to send the logs to stdout rather than a file, as start does.

References

View logs: https://docs.docker.com/config/containers/logging/

Conf logs: https://docs.docker.com/config/containers/logging/configure/

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
4

Found a nice way here: https://github.com/Scout24/tomcat-stdout-accesslog/issues/2

Replace the following Valve in your server.xml file.

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/proc/self/fd"
       prefix="1" suffix="" rotatable="false"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

Linux only!

This "nice way" works for me as expected.

Lars
  • 3,576
  • 2
  • 15
  • 13
  • This works for me. I'm not sure how performant this will be at scale - I will post back here if I find any scaling issues with this. – Jaron F Jun 03 '21 at 18:29
  • For me `` This send logs to stdout – arulraj.net Feb 13 '22 at 23:42
  • I don't have the server.xml file. What to do? – Alexander Pravdin Dec 09 '22 at 14:35
  • I've started a `docker run -it tomcat:10.1 bash` and found the server.xml in the conf directory. To test it, I also installed version 11.0 and 9 and I see the server.xml in conf directory. Maybe your installation is corrupt? Try it within docker. – Lars Dec 10 '22 at 15:15
1

Below worked for me in Tomcat 9.0.37:

Instead of using ./statup.sh, use ./catalina.sh run to start the tomcat server.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Mayur Chavan
  • 833
  • 8
  • 14
0

May be it will be better to write logs directly to the stdout instead of the file in the container. It will be lost after restart.

See for more details https://12factor.net/logs

Ardling
  • 183
  • 1
  • 1
  • 9
0

If you are already using log4j2. you can just remove the default logging.properties when building your image.

RUN rm /usr/local/tomcat/conf/logging.properties

ref: Keeping your logs clean with Apache Tomcat 9, log4j2 and spring-boot

Mahmoud
  • 9,729
  • 1
  • 36
  • 47