Pass Spring Boot port through Docker run - spring

I want to run the same application on multiple containers on the same Docker network, I have another application that will start the docker containers, the issue is the number of containers is undefined, so I want to pass the ports when I run the image not build it, by default the container will run on port 8080, but when a new container starts it will also try to run on 8080, therefore I want to change the port to not cause the other containers to fail.
Here is the Dockerfile for the application:
FROM maven:3.8.6-openjdk-18-slim as BUILD
WORKDIR /usr/src/app
#Download dependencies
COPY pom.xml ./
RUN ["/usr/local/bin/mvn-entrypoint.sh", "mvn", "verify", "clean", "--fail-never"]
#Create war file
COPY ./src ./src
RUN mvn -f ./pom.xml package
FROM openjdk:18.0.2.1-jdk-slim
ARG port
ENV PORT $port
WORKDIR /usr/src/app
COPY --from=BUILD /usr/src/app/target/*.war /usr/src/app/*.war
ENTRYPOINT java -jar "/usr/src/app/*.war" --server.port=$PORT
EXPOSE $PORT
if I use --build-arg it works since it's using the ARG port, but since I want to set it on run time so I made an environmental variable.
If I run docker run -it <container_id> -e "PORT=8085" the application still runs on 8080 or the --build-arg if provided.
Is there a way to provide the port when using docker run instead of building the same image every single time I want it to run on a different port?

There should be no conflict if multiple containers are using the same port since each container has a different IP address, which can be verified with docker container inspect NAME|ID.

Related

Run Laravel docker image with exposing ports -p

I have a laravel app but I can't make it run with docker run command. The last two instructions are
EXPOSE 9000
CMD ["php", "artisan", "serve","--port=9000"]
I am trying to make it run trying with:
docker run -p 9000:9000 my_image:latest
docker run --net="host" -p 9000:9000 my_image:latest
docker run --net="bridge" -p 9000:9000 my_image:latest
The only thing I see is the classic laravel output
Laravel development server started: <http://127.0.0.1:9000>
What am I missing?
The problem is 127.0.0.1:9000, i.e., the server is bound to localhost within the container, instead of listening on an external interface. The solution is to use the --host 0.0.0.0 argument, which will bind the server to all available interfaces.
CMD ["php", "artisan", "serve", "--host", "0.0.0.0", "--port=9000"]

Testcontainers ; Running #Testcontainers Tests inside docker [Running Docker inside Docker]

How To Run #Testcontainers based test cases inside the docker container ?
I have Simple Spring Boot App that has Integration Test (Component level) that are interacting with containers using Testcontainers. Test cases are ruining fine from outside container(Local machine).
We are running everything in containers and build is running on docker jenkins image.
Docker file is creating jar and then image. #Testcontainers is not able to find docker installed.
Below is my docker file.
FROM maven:3.6-jdk-11-openj9
VOLUME ["/var/run/docker.sock"]
RUN apt-get update
RUN apt-get -y install docker.io
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN mvn -Dmaven.repo.local=/root/m2 --batch-mode -f pom.xml clean package
EXPOSE 8080
CMD ["/bin/bash"]
While running build i am getting below below error
org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy - ping failed with configuration Environment variables, system properties and defaults. Resolved dockerHost=unix:///var/run/docker.sock due to org.rnorth.ducttape.TimeoutException: Timeout waiting for result with exception
Whats the best way to handle this case ? I want to run my component level integration test during mvn build phase using docker file.
below reference did not helped me.
https://www.testcontainers.org/supported_docker_environment/continuous_integration/dind_patterns/
This is not complete answer but you should enable access to a docker daemon from inside your container. Installing Docker and running it's daemon inside your container is complicated so not recommended. Docker can be controlled via Unix socket or over TCP (I assume the host system is a Linux).
How Test containers look for Docker:
By default it tries to connect to Unix socket /var/run/docker.sock. You can specify other socket path or TCP address by setting environment variables (DOCKER_HOST).
How docker exposes it's control API:
By default via Unix socket /var/run/docker.sock (on your host). You can expose docker API elsewhere by adding following parameters to docker start command (the location of command launching your docker is system dependent): -H fd:// -H tcp://127.0.0.1:2376. Note that you can specify more than one option. -H fd:// - is the default, tcp://127.0.0.1:2376 - tells Docker to listen on localhost port 2376.
How to make Docker available inside your container ("Docker in Docker"): If you enabled network access - no need to do additional config except pointing Testcontaners to it as mentioned above. If you want to use default Unix socket then you can map (mount) it into container via volume option:
docker run --volume /var/run/docker.sock:/var/run/docker.sock your-image-id-here
The remaining problem is that mounted docker.sock inside container will also be owned by root:docker (with same uid:gid as on your host system) so Testcontainers would work only if your container user can connect to that socket. That is user of running process is root or happen to have exact same group id inside your container as group id of docker on your host system.
I do not know yet a good solution to this one, so for starters you can run your tests inside container as root, or hard-code container's user group-id to match your host's docker group id.

Docker map port is invalid

I followed the tutorial to compile the project's image file with gradle and type it into docker. At the same time, the image is run and the virtual port is mapped to port 8761. However, my host accesses port 8761 and cannot connect. At the same time, I start the project locally and the host 8761 can be used.
I modified the dependent jdk8 image and added EXPOSE to the dockerfile.
Below are the configuration files and the docker run command:
FROM gmaslowski/jdk
VOLUME /tmp
ADD his-eureka-server-one-0.0.1-SNAPSHOT.jar app.jar
#RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-
jar","/app.jar"]
EXPOSE 8760
docker run -d -t -p 127.0.0.1:8760:8760 com.anhuishangjue/his-eureka-
server-one:0.0.1-SNAPSHOT
I want the host's 127.0.0.1:8760 to be able to access the eureka registry, but he told me to deny access

How to remove docker container using port number

I have Node services which are running in Docker container
I am using shell script to run these services
I want to run three different instances of the same service on 3 different port. say 9011 9022 9033
I also want it to configure it in such a way that after every new deployment it should stop the previous service and remove it
I am using docker rm test-service to remove it but it will remove other instances too.
by this approach only once instance can be running.
Is there any way to remove Docker service running on the specific port.
here is my shell script
#!/bin/bash
ORGANISATION="$1"
SERVICE_NAME="$2"
VERSION="$3"
ENVIRONMENT="$4"
INTERNAL_PORT_NUMBER="$5"
EXTERNAL_PORT_NUMBER="$6"
NETWORK="$7"
docker build -t ${ORGANISATION}/${SERVICE_NAME}:${VERSION} --build-arg PORT=${INTERNAL_PORT_NUMBER} --build-arg ENVIRONMENT=${ENVIRONMENT} --no-cache .
docker stop ${SERVICE_NAME}
docker rm ${SERVICE_NAME}
sudo npm install
sudo npm install -g express
docker run -p ${EXTERNAL_PORT_NUMBER}:${INTERNAL_PORT_NUMBER} --network ${NETWORK} --name ${SERVICE_NAME} --restart always -itd ${ORGANISATION}/${SERVICE_NAME}:${VERSION}
I can not run more than one container with the same name. Can I run the docker service with the same name on 3 different port. if yes what modifications do i need to make in above shell file?
That would be three docker run, each using the same internal port, but mapped to a different host port, with three different names
docker run -p ${EXTERNAL_PORT_NUMBER1}:${INTERNAL_PORT_NUMBER} --name ${SERVICE_NAME1}
docker run -p ${EXTERNAL_PORT_NUMBER2}:${INTERNAL_PORT_NUMBER} --name ${SERVICE_NAME2}
docker run -p ${EXTERNAL_PORT_NUMBER3}:${INTERNAL_PORT_NUMBER} --name ${SERVICE_NAME3}
I want to perform LoadBalance for service
See docker swarm mode
The swarm manager uses ingress load balancing to expose the services you want to make available externally to the swarm.
The swarm manager can automatically assign the service a PublishedPort or you can configure a PublishedPort for the service. You can specify any unused port. If you do not specify a port, the swarm manager assigns the service a port in the 30000-32767 range.
Example:
the following command publishes port 80 in the nginx container to port 8080 for any node in the swarm
$ docker service create \
--name my-web \
--publish 8080:80 \
--replicas 2 \
nginx

Debugging Tomcat in Docker container

I have a CoreOS running in Vagrant. Vagrant private network IP is 192.168.111.1. Inside a CoreOS is a docker container with Tomcat 8.0.32. Pretty much everything works ok (app deployment etc.) just debugging does not. Tomcat is mapped to 8080 port and the JPDA port should be 8000.
Facts
Tomcat JPDA is configured with:
JDPA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
It starts with catalina.sh jpda start command. The output in the console when running it with docker-compose is:
tomcat | Listening for transport dt_socket at address: 8000
From the container info I assume that ports are mapped as they should:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dcae1e0148f8 tomcat "/run.sh" 8 minutes ago Up 8 minutes 0.0.0.0:8000->8000/tcp, 0.0.0.0:8080->8080/tcp tomcat
My docker image is based on this Dockerfile.
Problem
When trying to run Remote debug configuration (screenshot below) I get the error Error running Debug: Unable to open debugger port (192.168.111.1:8000): java.net.ConnectException "Connection refused". I've tried everything from changing various configuration but no luck. Am I missing something?
This is the command I use for this:
docker run -it --rm \
-e JPDA_ADDRESS=8000 \
-e JPDA_TRANSPORT=dt_socket \
-p 8888:8080 \
-p 9000:8000 \
-v D:/tc/conf/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml \
tomcat:8.0 \
/usr/local/tomcat/bin/catalina.sh jpda run
Explanation
-e JPDA_ADDRESS=8000debugging port in container, passed as environment variable
-e JPDA_TRANSPORT=dt_sockettransport type for debugging as socket, passed as environment variable
-p 8888:8080 expose tomcat port 8080 on host as port 8888
-p 9000:8000 expose java debugging port 8000 on host as port 9000
-v {host-file}:{container-file}overwrite tomcat-user.xml with my local on, since I need access to the manager apiomit this line if this isn't necessary for your use case
tomcat:8.0see https://hub.docker.com/_/tomcat/
/usr/local/tomcat/bin/catalina.sh jpda runcommand to run in the container
The accepted answer didn't work for me, apparently because I was using Java 11. It seems that if you're using Java 9 or newer, you need to specify the JPDA address like this:
JPDA_ADDRESS=*:8100
You can always update the Dockerfile to something like the following: -
FROM tomcat:8-jre8
MAINTAINER me
ADD target/app.war /usr/local/tomcat/webapps/app.war
ENV JPDA_ADDRESS="8000"
ENV JPDA_TRANSPORT="dt_socket"
EXPOSE 8080 8000
ENTRYPOINT ["catalina.sh", "jpda", "run"]
This does mean though that your docker file has debug on by default which is probably not suited to a production environment.
Try add to your Dockerfile
ENV JPDA_ADDRESS=8000
ENV JPDA_TRANSPORT=dt_socket
It works for me
You need to make sure that port 8080 is exposed to IntelliJ for connection. That is while running docker you shall require something like docker run -p 8080:8080
For example, I am able to achieve the similar requirement like this by doing below mentioned steps/checks.
This is what my docker run command looks like:
sudo docker run --privileged=true -d -p 63375:63375 -p 63372:8080 -v /tmp/:/usr/local/tomcat/webapps/config <container name>:<tag>
NOTE: I am exposing an extra port 63375 on container and on my host both. The same port I am using in CATALINA_OPTS below.
This is what my entry point (for the image that I am building) looks like. NOTE: I am using CATALINA_OPTS. Also, I am using maven to create image so below is excrept from pom.xml.
<entryPoint>
<shell>cd /usr/local/tomcat/bin; CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=63375,server=y,suspend=n" catalina.sh run</shell>
</entryPoint>
I resolved a similar, if not the same, issue when using docker-compose.
It involved the environment variables not being passed properly from the docker-compose.yml file.
See my stack overflow issue:
For me is cleaner this way:
docker run -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n" -p 8000:8000 tomcat:8.5-jdk8
This way you don't have to modify your container Dockerfile.
Explanation: all java version check the JAVA_TOOL_OPTIONS environment variable: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars002.html
I have similar setup in my local environment. I included JPDA_ADDRESS as environment variable in the Dockerfile and recreated the containers.
ENV JPDA_ADDRESS 8000
#Expose port 8080, JMX port 13333 & Debug port 8000
EXPOSE 8080 13333 8000
CMD ["tail", "-f", "/dev/null"]

Resources