Docker-Compose - Control docker-compose execution order - java

I need to control the order of Docker containers instantiation, the problem is that I want to build a Jar file with the Docker maven container then pass that jar to an OpenJDK Docker container in order to build an image and then instantiate a MongoDB container and a Java-App container with the OpenJDK image generated before that communicates between them via docker-compose.
The problem is the Build always fails because some of the Unit tests talk to the database before it's initialized and since the tests fail the build also fails.
This is my dockerfile:
FROM maven:3.5-alpine
COPY ./ /app
RUN cd /app && mvn package
FROM openjdk:8
COPY spring-rest-iw-exam.jar /tmp/spring-rest-iw-exam.jar
EXPOSE 8087
ENTRYPOINT ["java", "-jar", "/tmp/spring-rest-iw-exam.jar"]
This is my Docker-Compose:
version: '2'
services:
mongodb:
image: mongo
container_name: iw_exam_mongo
restart: always
ports:
- "27017:27017"
environment:
- MONGO_INITDB_DATABASE=fizz_buzz_collection
volumes:
- /opt/iw-exam/data:/data/db
spring-app:
container_name: iw_exam_java_rest_api
build: ./
restart: always
ports:
- "8087:8087"
depends_on:
- mongodb
I tried with depends_on and did some other tests with a tool call dockerize but none of it works, the maven build always starts before docker-compose even start to instantiate mongodb.
This is the github repository of the proyect:
https://github.com/dsalasboscan/exam
I need to instantiate Mongodb first and THEN start with the maven build and java image generation.

I came across similar problem before, and would like to share my experience.
Basically, we need to wait for a while to make sure mongodb is completely boot up, here is the tool that you can leverage. It's fairly easy to use.

Related

Run selenium tests in docker container from JAR file

I currently have a docker-compose file with 3 services:
selenium-hub
chrome-node
a container containing my selenium JUnit tests.
I want to selenium-test (w/ JUnit) my JAR file (containing these tests) with a command in the container's Dockerfile. I thought about using the selenium-server.jar but I can't seem to figure out what the exec command should be (in the Dockerfile).
Anyone can help me out?
My docker-compose.yml:
version: "3"
services:
chrome:
image: selenium/node-chrome:4.1.4-20220427
shm_size: 2gb
container_name: chrome
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
selenium-hub:
image: selenium/hub:4.1.4-20220427
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
application:
build: .
container_name: application
ports:
- "4447:4447"
depends_on:
- chrome
And my Dockerfile:
#
# Build stage
#
FROM maven:3.6.0-jdk-11-slim AS build
COPY src .
COPY pom.xml .
RUN mvn -f pom.xml jar:test-jar
#
# Package stage
#
FROM openjdk:11-jre-slim
COPY --from=build target/playground-project-selenium-1.0-SNAPSHOT-tests.jar /usr/local/lib/demo.jar
ADD selenium-server.jar .
ENTRYPOINT exec java -jar selenium-server.jar --ext /usr/local/lib/demo.jar:selenium/node-chrome standalone --port 4447
EXPOSE 4447
After some sessions of trial-and-error, I've managed to answer my own question. I created a so-called Fat-JAR (using the maven assembly plugin) containing all tests, resources and dependencies and I used JUnit 4 with the org.junit.runner.JUnitCore class to run a test suite.
Now, my selenium UI tests are fully running in a Docker container using selenium hub and chrome driver in separate containers.

Docker files to docker compose

Im new at docker. I am making a java sockets music server and i have 2 files. Client.java and Server.java. Both are in separate containers. To mention, i run both services in command line
Docker files
FROM java:8
COPY Server.java /
RUN javac Server.java
EXPOSE 25000
ENTRYPOINT ["java"]
CMD ["Server"]
FROM java:8
COPY Client.java /
RUN javac Client.java
EXPOSE 25000
ENTRYPOINT ["java"]
CMD ["Client"]
i create also a network for these two to communicate.
docker network create client_server_network
and i run the images as follows:
docker run --env SERVER_HOST_ENV=server --network-alias server --network client_server_network -it server
docker run --network client_server_network -it clientimage
Now i want to create a docker compose file with those two Dockerfiles and the network. This is what i have done so far:
version:'3'
services:
client:
image: java:8
ports:
-25000:25000
network:
default:
name: client_server_network
server:
image: java:8
ports:
-25000:25000
environment:
-SERVER_HOST_ENV=server
network:
My question is how to add the common network in both services. Also is the way i write my docker compose file correct?
Below is the code, by default both container is added to network named net and it must provide in the last line also
version:'3'
services:
client:
image: java:8
ports:
- 25000:25000
networks:
- client_server_network
server:
image: java:8
ports:
- 25000:25000
environment:
- "SERVER_HOST_ENV=server"
networks:
- client_server_network
networks:
client_server_network:
Note that the network should be specified commonly at last in the same level of services and version. As indenting is a main factor in docker-compose. if it is incorrectly indent may shows error.
Delete all of the networks: blocks in the entire file. client and server will be usable as host names by these two containers.
This behavior is described further in Networking in Compose in the Docker documentation. If you don't declare top-level networks:, Compose creates a network called default, and if you don't declare networks: on a given service, Compose attaches it to that default network.
A functional translation of your two docker run commands would look like:
version: '3.8'
# Compose creates `networks: { default: }` on its own; you do not need
# top-level `networks:`
services:
server: # <-- this name is usable as a host name
image: server
environment:
- SERVER_HOST_ENV=server
# Automatically on `networks: [default]`
client:
image: clientimage

Make image by docker compose to start automatically Spring Boot and Cassandra

I'm trying to create docker image by docker-compose. How I can do that?
I can start my project (spring boot + cassandra) by docker-compose up. And everything works great. But in next step I want to make from this project image, push to docker hub and pull it from docker hub to test on other computer. Im tried 'docker-compose build', 'docker-compose push' and then 'docker-compose pull'. After pull I can see information that cassandra and spring-boot-app is downloaded. But then, when I want to run this image by 'docker run' but it runs only springboot, without cassandra.
This is my docker-compose.yaml file:
version: '3'
services:
cassandra:
build:
context: ../
dockerfile: docker/cassandra/Dockerfile
ports:
- "9042:9042"
container_name: cassandra
spring-boot-cassandra:
build:
context: ../
dockerfile: docker/springbootsample/Dockerfile
links:
- cassandra
ports:
- "8080:8080"
environment:
SPRING_DATA_CASSANDRA_CONTACT_POINTS: cassandra
container_name: springboot
entrypoint: /wait-for-it.sh cassandra:9042 -- java -Djava.security.egd=file:/dev/./urandom -jar app.jar
depends_on:
- "cassandra"
image: myrepo/springbootsample
networks:
default:
driver: bridge
docker-compose is used to handle multiple images. I guess you are thinking it will merge two images into one, which will not happen.
docker run is used to run only one image at a time, this was the limitation because of that docker-compose was introduced.
docker-compose up does docker run, docker network create/add etc. commands to create you an environment. For use,
docker-compose build will build all your images present in the docker-compose.yml file.
docker-compose push will push all your images to the hub.
docker-compose pull will download those images from the hub if present.
and finally, if you want to run those images, use docker-compose up. If the images are not present it will download those images first from the hub.

Opening a shell into a Java image

I'm building a postgres+java container, and I'd like to open a shell into the java "service". That service exits immediately after starting, how can I do to open a shell into it?
I see it in docker ps -a but it has already exited.
The file I'm using is this .yaml with docker-compose
version: '3.1'
services:
db:
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: postgres
volumes:
- datavolume:/var/lib/postgresql
java:
image: openjdk:8
volumes:
datavolume:
A Docker container generally runs a single process. In the same way that just running a JVM without an application attached to it isn't really meaningful, running a Docker container with a JVM but no actual application added to it isn't that useful.
You should write a Dockerfile that adds your application's jar file to a base Java image; for instance
FROM openjdk:8
COPY app.jar /
CMD ["java", "-jar", "/app.jar"]
and then your docker-compose.yml file can have instructions to build and run this image
services:
java:
build: .
If you just want a shell in a copy of the image to poke around and see what's there, you can generally run
docker run --rm -it openjdk:8 sh
The standard openjdk Dockerfile doesn't explicitly declare any specific ENTRYPOINT or CMD so it will exit immediately when run. (It probably inherits a default /bin/sh, but with no command to run, that will also exit immediately.) You can declare some other command: in the Dockerfile to cause the "service" to not exit, but it's not really doing anything useful for you.

Docker: Start Tomcat after running Oracle and scripts executed

I am really new to Docker and enjoy it, however, I found some problems with running my application. I want to run my application which consists of 2 services:
I would like to start Oracle and run some DDL and DATA scripts which should take above 30 seconds
I would like to start Tomcat and launch my war file after the first step is finished as it won't start without it.
I've already read about: docker-wait and this is not what am i exactly waiting for as I should execute some scripts after my db would be available on specified port.
As I understand, the right way to start multiservises application is to use docker compose.
Here is my docker-compose.yml for now:
version: '2'
services:
web:
build: Server
ports:
- "8080:8080"
depends_on:
- oracle
oracle:
build: Oracle
ports:
- "1521:1521"
depends_on just lets me to order start of apps and nothing more.
For both Tomcat and Oracle I am using most popular images from Docker Hub.
How could I get the right way to start Tomcat after Oracle has started and scripts are executed?
depends_on only checks that the container is running, not that the service inside it is ready to accept requests. What you want is for your web service to start only when your oracle service is ready. You can use a script like wait-for-it to do this. Eg:
version: '2'
services:
web:
build: Server
ports:
- "8080:8080"
depends_on:
- oracle
command: wait-for-it.sh oracle:1521 --timeout=8 -s -q -- myservercmd
oracle:
build: Oracle
ports:
- "1521:1521"

Categories