Docker add warfile to official Tomcat image - docker

I pulled official Docker image for Tomcat by running this command.
docker run -it --rm tomcat:8.0
By using this as base image I need to build new image that contains my war file in the tomcat webapps folder. I created Dockerfile like this.
From tomcat8
ADD warfile /usr/local/tomcat
When I run this Dockerfile by building image I am not able to see Tomcat front page.
Can anybody tell me how to add my warfile to official Tomcat images webapp folder.

Reading from the documentation of the repo you would do something like that
FROM tomcat
MAINTAINER xyz
ADD your.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
Then build your image with docker build -t yourName <path-to-dockerfile>
And run it with:
docker run --rm -it -p 8080:8080 yourName
--rm removes the container as soon as you stop it
-p forwards the port to your host (or if you use boot2docker to this IP)
-it allows interactive mode, so you see if something get's deployed

Building on #daniel's answer, if you want to deploy your WAR to the root of tomcat, I did this:
FROM tomcat:7-jre7
MAINTAINER xyz
RUN ["rm", "-fr", "/usr/local/tomcat/webapps/ROOT"]
COPY ./target/your-webapp-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh", "run"]
It deletes the existing root webapp, copies your WAR to the ROOT.war filename then executes tomcat.

docker run -it --rm --name MYTOMCAT -p 8080:8080 -v .../wars:/usr/local/tomcat/webapps/ tomcat:8.0
where wars folder contains war to deploy

How do you check the webapps folder?
The webapps folder is within the docker container.
If you want to access your webapps container you could mount a host directory within your container to use it as webapps folder. That way you can access files without accessing docker.
Details see here
To access your logs you could do that when you run your container e.g.
docker run -rm -it -p 8080:8080 **IMAGE_NAME** /path/to/tomcat/bin/catalina.sh && tail -f /path/to/tomcat/logs
or you start your docker container and then do something like:
docker exec -it **CONTAINER_ID** tail -f /path/to/tomcat/logs

If you are using spring mvc project then you require server to run your application suppose you use tomcat then you need base image of tomcat that your application uses which you can specify through FROM command.
You can set environment variable using ENV command.
You can additionally use RUN command which executes during Docker Image buiding.
eg to give read write execute permissions to webapps folder for tomcat to unzip war file
RUN chmod -R 777 $CATALINA_HOME/webapps
And one more command is CMD. Whatever you specifying in CMD command it will execute at a time of container running. You can specify options in CMD command using double quotes(" ") seperated by comma(,).
eg
CMD ["catalina.sh","start"]
(NOTE : Remember RUN command execute at a time of image building and CMD execute at a time of running container this is confusing for new users).
This is my Dockerfile -
FROM tomcat:9.0.27-jdk8-openjdk
VOLUME /tmp
RUN chmod -R 777 $CATALINA_HOME/webapps
ENV CATALINA_HOME /usr/local/tomcat
COPY target/*.war $CATALINA_HOME/webapps/myapp.war
EXPOSE 8080
CMD ["catalina.sh","run"]
Build your image using command
docker build -t imageName <path_of_Dockerfile>
check your docker image using command
docker images
Run image using command
docker run -p 9999:8080 imageName
here 8080 is tomcat port and application can access on 9999 port
Try accessing your application on
localhost:9999/myapp/

Related

Docker run commands works but dockerfile not

I have a problem with running the image of Dockerfile. CLI commands work fine but when I use the Dockerfile I get an error from the localhost:
localhost didn’t send any data.
What I am doing is simple. By CLI:
docker run -d --name mytomcat -p 8080:8080 tomcat:latest
docker exec -it mytomcat /bin/bash
mv webapps webapps2
mv webapps.dist/ webapps
exit
Which works fine.
My Dockerfile:
FROM tomcat:latest
CMD mv webapps webapps2 && mv webapps.dist/ webapps && /bin/bash
Build and run:
docker build -t myrepo/tomacat:1.00 .
docker run -d --name mytomcat -p 8080:8080 myrepo/tomacat:1.00
Doesn't work and show the above error.
Note: I am using mv command because I get 404 error!
Does anybody know the problem here?
When your Dockerfile has a CMD command, that runs instead of the command in the base image. With the tomcat image, the base image would run the Tomcat server; but with this Dockerfile, it's trying to run a bash shell instead, and without any input that just exits immediately.
To just moves files around, it's usually better to use COPY and RUN directives to set up the image once, rather than trying to repeat these steps every time you run the container. For this setup where the base image already has a reasonable CMD, you don't need to repeat it in your own custom Dockerfile.
FROM tomcat:latest
RUN mv webapps webapps2 && mv webapps.dist/ webapps
# no particular mention of bash; use the `CMD` from the base image
It's not uncommon for a base image to include some sort of runtime that needs to be configured, but for the base image's CMD to still be correct. In addition to tomcat, nginx and php:fpm work similarly; so long as their configuration files and code are in the right place, you don't need to repeat the CMD.

How ro access docker volume files from the code on docker container

i have creted a docker volume with such command
docker run -ti --rm -v TestVolume1:/testvolume1 ubuntu
then i created a file there, called TestFile.txt and added text to it
Also i have a simple "Hello world" .net core app with Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY bin/Release/net6.0/publish/ ShareFileTestInstance1/
WORKDIR /ShareFileTestInstance1
ENTRYPOINT ["dotnet", "ShareFileTestInstance1.dll"]
I published it using
dotnet publish -c Release
then ran
docker build -t counter-image -f Dockerfile .
And finally executed
docker run -it --rm --name=counter-container counter-image -v TestVolume1:/testvolume1 ubuntu
to run my app with a docker volume
So what i want to achive to access a file which is in a volume("TestFile.txt" in my case) from a code in the container.
for example
Console.WriteLine(File.Exists("WHAT FILE PATH HAS TO BE HERE") ? "File exists." : "File does not exist.");
Is it also possible to combine all this stuff in a Dockerfile? I want to add one more container next and connect to the volume to save data there.
The parameters for docker run can be either for docker or for the program running in the docker container. Parameters for docker go before the image name and parameters for the program in the container go after the image name.
The volume mapping is a parameter for docker, so it should go before the image name. So instead of
docker run -it --rm --name=counter-container counter-image -v TestVolume1:/testvolume1 ubuntu
you should do
docker run -it --rm --name=counter-container -v TestVolume1:/testvolume1 counter-image
When you do that, your file should be accessible for your program at /testvolume1/TestFile.txt.
It's not possible to do the mapping in the Dockerfile as you ask. Mappings may vary from docker host to docker host, so they need to be specified at run-time.

Docker bind-mount not working as expected within AWS EC2 Instance

I have created the following Dockerfile to run a spring-boot app: myapp within an EC2 instance.
# Use an official java runtime as a parent image
FROM openjdk:8-jre-alpine
# Add a user to run our application so that it doesn't need to run as root
RUN adduser -D -s /bin/sh myapp
# Set the current working directory to /home/myapp
WORKDIR /home/myapp
#copy the app to be deployed in the container
ADD target/myapp.jar myapp.jar
#create a file entrypoint-dos.sh and put the project entrypoint.sh content in it
ADD entrypoint.sh entrypoint-dos.sh
#Get rid of windows characters and put the result in a new entrypoint.sh in the container
RUN sed -e 's/\r$//' entrypoint-dos.sh > entrypoint.sh
#set the file as an executable and set myapp as the owner
RUN chmod 755 entrypoint.sh && chown myapp:myapp entrypoint.sh
#set the user to use when running the image to myapp
USER myapp
# Make port 9010 available to the world outside this container
EXPOSE 9010
ENTRYPOINT ["./entrypoint.sh"]
Because I need to access myapp's logs from the EC2 host machine, i want to bind-mount a folder into the logs folder sitting within "myapp" container here: /home/myapp/logs
This is the command that i use to run the image in the ec2 console:
docker run -p 8090:9010 --name myapp myapp:latest -v home/ec2-user/myapp:/home/myapp/logs
The container starts without any issues, but the mount is not achieved as noticed in the following docker inspect extract:
...
"Mounts": [],
...
I have tried the followings actions but ended up with the same result:
--mount type=bind instead of -v
use volumes instead of bind-mount
I have even tried the --privileged option
In the Dockerfile: I tried to use the USER root instead of myapp
I believe that, this has nothing to do with the ec2 machine but my container. Since running other containers with bind-mounts on the same host works like a charm.
I am pretty sure i am messing up with my Dockerfile.
But what am i doing wrong in that Dockerfile ?
or
What am i missing out ?
Here you have the entrypoint.sh if needed:
#!/bin/sh
echo "The app is starting ..."
exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar -Dspring.profiles.active=${SPRING_ACTIVE_PROFILES} "${HOME}/myapp.jar" "$#"
I think the issue might be the order of the options on the command line. Docker expects the last two arguments to be the image id/name and (optionally) a command/args to run as pid 1.
https://docs.docker.com/engine/reference/run/
The basic docker run command takes this form:
$ docker run [OPTIONS] IMAGE[:TAG|#DIGEST] [COMMAND] [ARG...]
You have the mount options (-v in the example you provided) after the image name (myall:latest). I'm not sure but perhaps the -v ... is being interpreted as arguments to be passed to your entrypoint script (which are being ignored) and docker run isn't seeing as a mount option.
Also, the source of the mount here (home/ec2-user/myapp) doesn't start with a leading forward slash (/), which, I believe, will make it relative to where the docker run command is executed from. You should make sure the source path starts with a forward slash (i.e. /home/ec2-user/myapp) so that you're sure it will always mount the directory you expect. I.e. -v /home/ec2-user...
Have you tried this order:
docker run -p 8090:9010 --name myapp -v /home/ec2-user/myapp:/home/myapp/logs myapp:latest

docker file for tomcat

I wrote one docker file for tomcat installation, the file is
FROM openjdk:8-jre-alpine
RUN wget http://mirrors.fibergrid.in/apache/tomcat/tomcat-8/v8.5.34/bin/apache-tomcat-8.5.34.tar.gz
RUN gzip apache-tomcat-8.5.34.tar.gz
ADD https://github.com/spagop/quickstart/raw/master/management-api-examples/mgmt-deploy-application/application/jboss-as-helloworld.war /apache-tomcat-8.5.34/*/webapps
EXPOSE 8080
CMD ["catalina.sh", "run"]
And I built the above docker file by using
$ docker build -t tomacat -f docker file name .
And created the container by using above docker image, command is
$ docker run --name=tom1 -d -it -p 9090:8080 tomcat
After running the docker run container is up and running
But tomcat server is not up and running in background
I replaced the catalina.sh with startup.sh in CMD area and also i getting same problem
Please help me for resolving problem
As mentioned in the question, I did everything as stated and started a container. After that I accessed the tomcat through HOST_IP:HOST_PORT and I was able to access the Tomcat. The issue may be that you are not accessing the Tomcat correctly like HOST_IP is not correct.

How to deploy webapp or war file in tomcat that is running in docker container

I have created Docker container and Tomcat is running in this container. How can I deploy a webapp or war file in Tomcat that is running in docker container.
First create a Dockerfile:
FROM library/tomcat
RUN rm -rf /usr/local/tomcat/webapps/*
ADD ./relative/path_to_war.war /usr/local/tomcat/webapps/ROOT.war
Then build Docker image
$ docker build -t user/image_name .
And finally run docker container.
$ docker run --name container_name -p 80:8080 -d user/image_name
After that your webapp should be responding on Docker host's ip on default http 80 port.
You might need to link a database container to your webapp, see more on Docker documentation
You can implement an effective way of using Tomcat Docker.
docker run -d -p 80:8080 -v <mount-path>:/usr/local/tomcat/webapps/ tomcat:8.0
And then copy the .war files to the mounted volume. This would eliminate the need for restarting the Tomcat Docker each time when there is a code change. A zero downtime implementation could be achieved.
If it's a one-time deployment then you may create a custom Docker and copy the war file into /usr/local/tomcat/webapps/ and start the Docker.

Resources