How to build binaries outside of Dockerfile for docker-compose build - java

I am new to docker-compose and probably don't understand the ideology behind.
Short question -- I see there is docker-compose build command. I'd like to trigger a (gradle) script outside of the Dockerfile file as part of running it.
Let's say that I have a java web service inside Docker that I build in advance by gradle.
I don't add gradle agent to the Dockerfile (as I am expected to keep it small, right?), I only COPY binaries
FROM openjdk:17-jdk-alpine
RUN apk add --no-cache bash
VOLUME /var/log/app/
WORKDIR /app
ARG EXTRACTED
COPY ${EXTRACTED}/application/ ./
...
ENTRYPOINT ["java","org.springframework.boot.loader.JarLauncher"]
And so I build this image by a script
./gradlew build
java -Djarmode=layertools -jar build/libs/*.jar extract --destination build/libs-extracted/
docker build --build-arg EXTRACTED=build/libs-extracted -t my-server .
I can define the following compose.yml. How do I trigger gradle inside of it? Or, same as with my single Dockerfile, I am expected to wrap docker-compose build into a build script?
version: '3.1'
services:
db:
image: postgres:alpine
restart: always
my-server:
image: my-server
restart: always
depends_on:
- db
Maybe I am asking for a hack, but actually I am happy to take another approach if it's cleaner

I discovered multi-stage Dockerfile feature that addresses my task, and I can use it for both individual Dockerfile builds and docker-compose builds.
https://stackoverflow.com/a/61131308/1291049.
I will probably lose gradle daemon optimisations though.

Change your docker compose file:
version: '3.1'
services:
db:
image: postgres:alpine
restart: always
my-server:
build:
context: ./my-server
dockerfile: Dockerfile
restart: always
depends_on:
- db

Related

How can I access the volume I created in docker compose via dockerfile?

I have created a volume in docker compose and want to copy files into it. I need docker file for this. However, I don't know how to access the volume I created in docker compose via dockerfile. How can I do it?
docker-compose.yml
version: '3'
services:
postgres:
image: postgres
hostname: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
pgadmin:
image: dpage/pgadmin4
restart: always
ports:
- "5433:80"
environment:
PGADMIN_DEFAULT_EMAIL: test#gmail.com
PGADMIN_DEFAULT_PASSWORD: test
depends_on:
- postgres
web:
build:
context: ../
dockerfile: spring/Dockerfile
ports:
- "8080:8080"
depends_on:
- postgres
volumes:
- ./test-volume:/opt/_LIB/
Dockerfile
FROM ...
RUN rm -rf /var/lib/jetty/webapps/*
COPY spring/target/*.war /var/lib/jetty/webapps/
EXPOSE 8080
#CMD ["java", "-jar", "$JETTY_HOME/start.jar"]
[How can I] access the volume I created in docker compose via dockerfile?
You can't. It doesn't exist yet. Everything in the Compose build: block happens before any other option in the Compose file is considered; you don't get to see volumes:, or environment: variables, or access other containers on networks: (even the automatically-provided default network).
The way the postgres image handles this is through an entrypoint wrapper script that creates the database if it doesn't exist. You can write a similar script:
#!/bin/sh
# entrypoint.sh
# If the data files don't exist yet, copy them in
if [ ! -f /opt/_LIB/data.txt ]; then
java -cp "$JETTY_HOME/start.jar" com.example.tools.SeedData /opt/_LIB
fi
# Run the main container command
exec "$#"
Replace the java command with whatever invocation would copy the data files from somewhere else in the image into the volume; even just a cp -r is fine, so long as the source data is somewhere other than the data directory. You can similarly change the logic to overwrite the old content if it exists, or if you have some way to merge the old and new files, you can do that too.
In your Dockerfile you can then leave your CMD as-is, but make sure to COPY this script into your image and make it the ENTRYPOINT.
FROM ...
RUN rm -rf /var/lib/jetty/webapps/*
COPY spring/target/*.war /var/lib/jetty/webapps/
COPY entrypoint.sh /usr/local/bin # <-- ADD
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] # <-- ADD
CMD ["java", "-jar", "/var/lib/jetty/webapps/start.jar"] # unmodified
The ENTRYPOINT line must use JSON-array syntax (which in turn means it can't include environment-variable references; I've corrected this in the CMD). The script needs to be executable (run chmod +x entrypoint.sh on the host system if needed).
(There is one corner case around Docker named volumes that some questions will try to take advantage of, but I don't generally recommend it. In your example the /opt/_LIB container directory uses a bind-mounted host directory so this trick won't work; it also doesn't work if you ever want to change the content in the image, or if you're deploying to an environment that's not native Docker.)

docker-compose failed to build on windows 10

I'm trying to deploy my spring boot application with docker compose but get this error:
Step 14/15 : COPY ${JAR_FILE} manager.jar
ERROR: Service 'manager' failed to build : When using COPY with more than one source file, the destination must be a directory and end with a /
But if I do a docker build using the Dokerfile it works correctly. The question is, why fail with docker-compose up?.
C:\Push\Workspace\manager>docker build --tag "docker-manager:latest" .
[+] Building 7.3s (8/8) FINISHED
I have tried looking for examples but I am using windows 10
The Dockerfile:
FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} example.jar
ENTRYPOINT ["java", "-jar", "example.jar"]
The docker-compose.yml
services:
oracle:
image: container-registry-london.oracle.com/database/enterprise:12.2.0.1
ports:
- "8080:8080"
- "1521:1521"
manager:
build: .
ports:
- "8181:8181"
depends_on:
- oracle
links:
- oracle
restart: always
I am guessing there might be mulitple jar files in your target folder.
In stead of using the *.jar , please use full name of the jar and then rebuild the dokcer compose file with --build flag.
ARG JAR_FILE=target/test-0.0.1-SNAPSHOT.jar
Then build with
docker-compose up --build

Docker&Java: building doesn't reflect the new files

I've just started to use Docker and I don't know why the Wildfly's docker container doesn't have the latest files even though it copies the war. I have a JS file which I've changed things in it, but whenever I access 127.0.0.1:8080/static/js/myjs.js I still get the older one even though I've sudo mvn clean install the app and then build the image.
I've a docker-compose file which looks like this:
version: "3"
services:
app:
build:
context: .
dockerfile: ./docker/docker-app/Dockerfile
ports:
- "8080:8080"
links:
- "db:task_book_db"
depends_on:
- "db"
db:
image: mysql:5.7.22
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=sample_db
- MYSQL_USER=sample_usr
- MYSQL_PASSWORD=sample_pw
ports:
- "3306:3306"
start_dependencies:
image: dadarek/wait-for-dependencies
depends_on:
- "db"
I do sudo docker-compose run --rm start_dependencies && sudo docker-compose up --build app and whenever I've changed something, I just stop the app container then I do sudo docker-compose up --build app again. I've read about volumes but I'm not sure how to use them yet.
As mentioned in the comments:
This issue might be because of browser cache. Try accessing the 127.0.0.1:8080/static/js/myjs.js
after clearing the cache.

docker error with multiple backend image install

Dockerfile
FROM python:3.6
ENV PYTHONUNBUFFERED 1
WORKDIR /usr/src/rango
COPY ./ /usr/src/rango
RUN pip install -r requirements.txt
here is my docker-compose file
services:
backend:
container_name: backend
build: ./
command: python manage.py runserver 0.0.0.0:8000
working_dir: /usr/src/rango
ports:
- "8000:8000"
tty: true
links:
- java
- elasticsearch
- node
#java
java:
image: openjdk:9-jre
#elastic search
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.5.0
ports:
- "9200:9200"
node:
image: node:10.13.0
Command i am using :
sudo docker-compose up
when i am running command i am getting error as
backend_node_1_26e7640d2fbb exited with code 0
backend_java_1_b1fbf7e151d7 exited with code 0
both node and java are not running .
i am using elastic search so i need java
plaese have look into my screenshot i have shared below.
A dockers images are self-reliant in terms of the language runtime that they run on, meaning that they include everything that's needed to run the particular process (excluding external dependencies, such as database or other services).
Therefore, ElasticSearch images does not require a Java container, and similarly the Node container is not needed. They are exiting with 0 exit status (indicating that they run successfully to their completion) as you haven't specified a command to execute (and nor is there a default one defined in the base image).
In summary, you can remove the java and node services from your compose file.

How to copy files from other location into Docker image

I am trying to copy files from other location (in windows from D drive that is shared drive also) to my image.
But it is giving me error.
Step 5/8 : ADD ${APP_PATH}/${ARTIFACT}-${VERSION} /opt/tomcat/webapps/${ARTIFACT}-${VERSION}
ADD failed: stat /var/lib/docker/tmp/docker-builder990684261/d:/Application_Build/spring-tournament-portal-0.0.1-SNAPSHOT: no such file or directory
Scenario:
I am trying to make test,build,release phase cycle with the help of docker.
So My Multistage docker file's first version looked like this
FROM maven as build
WORKDIR /usr/local
RUN mkdir app
COPY . /usr/local/app/spring-tournament-portal/
WORKDIR /usr/local/app/spring-tournament-portal
RUN mvn -e package
FROM tomcat
ENV PORT 8080
ENV VERSION 0.0.1-SNAPSHOT
ENV ARTIFACT spring-tournament-portal
ENV JPDA_ADDRESS 8000
ENV JPDA_TRANSPORT dt_socket
COPY --from=build /usr/local/app/${ARTIFACT}/target/${ARTIFACT}-${VERSION} /usr/local/tomcat/webapps/${ARTIFACT}-${VERSION}
WORKDIR /usr/local/tomcat/bin
CMD ["catalina.sh jpda run"]
EXPOSE ${PORT}
But on every build maven fetches its dependency. So it was taking too much time.
So i made another approach. I created two docker files(One for build and other for release).
Over here the role of build docker file does is copy all source code into an image only. So that when i will create container, I could easily create volume for maven dependency to avoid redownloading:-
FROM indiver/tournament-base
RUN apt-get update && \
apt-get install -y \
-o APT::Install-Recommend=false -o APT::Install-Suggests=false \
maven
WORKDIR /usr/local
COPY . /spring-tournament-portal/
WORKDIR /spring-tournament-portal
COPY ./docker/dev/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["sh", "/usr/local/bin/entrypoint.sh"]
RUN ["chmod", "+x", "/usr/local/bin/entrypoint.sh"]
Here is entrypoint.sh file
#!/bin/bash
echo "$#" Phase is executing.....
mvn clean "$#"
When i run the image after building docker file with the help of docker-compose.xml. I set volume for dependency folder.
Here is docker compose.xml
version: "2"
services:
test-service:
build:
context: ../../
dockerfile: ./docker/dev/Dockerfile
container_name: "test-service"
command: 'test'
volumes:
- .m2:/root/.m2
build-service:
build:
context: ../../
dockerfile: ./docker/dev/Dockerfile
container_name: "build-service"
command: 'package'
env_file:
- ./EnvironmentConstant.env
volumes:
- .m2:/root/.m2
database-service:
container_name: "database-service"
env_file:
- ./EnvironmentConstant.env
image: mysql
ports:
- "3306:3306"
volumes:
- ./dev-mysql:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
So it does not need to redownload the dependency again that is in .m2 volume.
After that i need to create release image having content of build prepared by maven. But container of build service is already stopped. So i need to use docker cp command to get my prepared build.
docker cp build-service:/spring-tournament-portal/target/spring-tournament-portal-0.0.1-SNAPSHOT D:/Application_Build
Now i want build that is in Application_Build folder should be copied into my release image.
So my release docker file looks like
FROM indiver/tournament-release
ENV APP_PATH=d:/Application_Build
ENV ARTIFACT=spring-tournament-portal
ENV VERSION=0.0.1-SNAPSHOT
ADD ${APP_PATH}/${ARTIFACT}-${VERSION} /opt/tomcat/webapps/${ARTIFACT}-${VERSION}
WORKDIR /opt/tomcat/bin
ENTRYPOINT ["catalina.sh", "jpda", "run"]
EXPOSE ${PORT}
But As i have mentioned above it is giving me error
Step 5/8 : ADD ${APP_PATH}/${ARTIFACT}-${VERSION} /opt/tomcat/webapps/${ARTIFACT}-${VERSION} ADD failed: stat /var/lib/docker/tmp/docker-builder990684261/d:/Application_Build/spring-tournament-portal-0.0.1-SNAPSHOT: no such file or directory.
I tried to copy by COPY and ADD command. But nothing is working. How can i achieve this.
If It can be achieved this with the help of other relatively easy flow. It would be helpful as well.
The Dockerfile reference says:
ADD obeys the following rules:
The path must be inside the context of the build.
...
Overall your approach seems to be too complicated to me and a very non micro-services way of doing things.
I would suggest that you copy your dependencies into the binary that you are creating to create a self contained fat (uber) jar, which you can copy to the docker image, the way spring boot does.
You approach for having separate docker files for different environments is also problematic and could result in unexpected conditions in production.
So I too faced this similar problem .
You can try the below listed command and replace the Square brackets with your path:
"docker cp /[Your Source Directory] [ContainerId]:/[Destination Path]"

Categories

Resources