Firstly, this question is not a duplicate of the question here. I am currently learning docker, and am required to create a dockerfile
which installs tomcat
and runs it at the start of a container with the entrypoint
command:
Following are the contents of my dockerfile
:
FROM ubuntu:latest
LABEL MAINTAINER="kesarling"
RUN apt update
RUN apt upgrade -y
RUN apt install apt-utils -y
RUN apt install maven gradle -y
RUN apt install wget tar zip unzip openjdk-14-jdk -y
RUN mkdir /usr/local/apache-tomcat-v8.5.55
RUN wget http://www-us.apache.org/dist/tomcat/tomcat-8/v8.5.55/bin/apache-tomcat-8.5.55.tar.gz -O /tmp/apache-tomcat-v8.5.55.tar.gz
RUN cd /tmp && tar xvfz apache-tomcat-v8.5.55.tar.gz
RUN cp -Rv /tmp/apache-tomcat-8.5.55/* /usr/local/apache-tomcat-v8.5.55/
RUN mkdir /usr/local/spring-v5.2.6
RUN wget https://repo.spring.io/release/org/springframework/spring/5.2.6.RELEASE/spring-5.2.6.RELEASE-dist.zip -O /tmp/spring-v5.2.6.zip
RUN cd /tmp && unzip spring-v5.2.6.zip
RUN cp -Rv /tmp/spring-framework-5.2.6.RELEASE/* /usr/local/spring-v5.2.6/
RUN cd ~
RUN touch server-start.sh
RUN echo "#!/bin/sh" | cat > server-start.sh
# start of condition
RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run&"' | cat >> server-start.sh
RUN echo "/bin/bash" | cat >>server-start.sh
# end of condition
RUN chmod +x server-start.sh
EXPOSE 8080
ENTRYPOINT [ "./server-start.sh" ]
As the server starts as a background process, it runs fine only when I give the -it
flag.
Else, as expected, the container quits the moment I detach it.
So, in a nutshell:
docker container run -it -p 8080:8080 <mydockername>
Works but:
docker container run -dp 8080:8080 <mydockername>
Does not (as expected). That is where the condition comes in. In a nutshell, I need it to detect if the docker has been run in background or in interactive mode.
The condition
block mentioned in the dockerfile
needs to be as follows:
If I am executing it with the -it
flag:
RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run&"' | cat >> server-start.sh
RUN echo "/bin/bash" | cat >>server-start.sh
Else if I am executing with the -d flag:
RUN echo 'bash -c "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh run"' | cat >> server-start.sh
(Notice that the /bin/bash
has been removed)
How do I go about this?
P.S. This is my first week into docker, so please bear with my dockerfile :P
Oh, and not to mention that searching detect if the container has been run with an interactive flag
doesn't bring up anything useful on Google
At build time, you won't know what the runtime environment will look like. So there's no way to modify the RUN
statements based on the -it
flags or lack there of, we don't have time travel to look into the future for that, and the same image could be run multiple times with different flags.
You could do this within the entrypoint script. /dev/stdin
which is mapped for interactive containers points to /proc/self/fd/0
which will point to different things based on whether you have -i
, -it
, or neither:
$ docker run -it --rm busybox ls -al /dev/stdin
lrwxrwxrwx 1 root root 15 Jun 18 14:43 /dev/stdin -> /proc/self/fd/0
$ docker run -it --rm busybox ls -al /proc/self/fd/0
lrwx------ 1 root root 64 Jun 18 14:43 /proc/self/fd/0 -> /dev/pts/0
$ docker run -i --rm busybox ls -al /proc/self/fd/0
lr-x------ 1 root root 64 Jun 18 14:50 /proc/self/fd/0 -> pipe:[9858991]
$ docker run --rm busybox ls -al /proc/self/fd/0
lrwx------ 1 root root 64 Jun 18 14:43 /proc/self/fd/0 -> /dev/null
So if you stat the link to see if it's going to /dev/null
or not, that would give you the answer to the question you asked.
Side note, if you only care about the -t
, there's another check in shell you can run, [ -t 0 ]
, e.g.:
$ docker run -it --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
tty
$ docker run -i --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
no tty
$ docker run --rm busybox /bin/sh -c 'if [ -t 0 ]; then echo tty; else echo no tty; fi'
no tty
However, best practice with docker is to run the app itself in the foreground, as pid 1. And if you need to enter the container for debugging in a development environment, use docker exec
for that. Your entrypoint then becomes:
ENTRYPOINT [ "/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh", "run" ]
And by doing that, you avoid an extra shell in pid 1 that could block container stop signals from gracefully stopping the app.
Then to debug, you'd exec after the run, using the container name:
docker container run -dp 8080:8080 -n tomcat-app <mydockername>
docker container exec -it tomcat-app /bin/sh
You don't need the start.sh
at all.
Just use CMD directive as follows.
CMD ["/usr/local/apache-tomcat-v8.5.55/bin/catalina.sh", "run"]
Both the following command will start tomcat
docker run -it -p 8080:8080 <imagename>
docker run -p 8080:8080 <imagename>
In case you want to debug something inside the container and want to access container shell, you can start a container and run bash as follows
docker run -it <imagename> bash
This will override the defaut CMD with bash
.
You can also replace CMD
with ENTRYPOINT
in the above suggestion but then if you want to access the container shell you have to do as follows -
docker run --entrypoint bash -it <imagename>
You can also look at official tomcat images and their dockerfiles here - https://hub.docker.com/_/tomcat
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With