First, I have dockerized a datasource, and I have linked it to a network.
Follow the guideline just here : https://github.com/SimonGirardSfeir/MySQL-Docker
Create a network
docker network create -d bridge mybridge
Link the image of the database to the network
docker run -d --net=mybridge --name=db docker-mysql
I go to the database in the shell to add the appropriate properties (username, password, name of the database), it works ok.
Now, it is perfectly ok.
Now, I am trying to link a Spring boot application with the following properties
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://db:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
And the Dockerfile is the following :
# Start with a base image containing Java runtime
FROM java:8-jre
# Add a volume pointing to /tmp
VOLUME /tmp
# Make port 8080 available to the world outside this container
EXPOSE 8080
# The application's jar file
ARG JAR_FILE=build/libs/mysql-0.0.1-SNAPSHOT.jar
# Add the application's jar to the container
ADD ${JAR_FILE} mysql.jar
RUN apt-get update
RUN apt-get install mysql-client -y
RUN apt-get install libmysql-java -y
# Run the jar file
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/mysql.jar"]
I build from the Dockerfile, it is ok.
Hence, I launch the following command
docker run --net=mybridge --name=app myappimage
But, the program is unable to connect to the database and the logs show:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
I don't understand where is the problem.
My sources are :
https://docs.docker.com/v17.03/engine/tutorials/networkingcontainers/#add-containers-to-a-network
https://spring.io/guides/gs/accessing-data-mysql/
https://github.com/moby/moby/issues/25562
Related
I have a simple Micronaut server I am trying to launch on Heroku by building it with a heroku.yml but for some reason when I check the logs the process exits as soon as it starts. The docker image runs just fine locally and nothing else prints out in the logs so I can't find out why.
Here is my Dockerfile
FROM node as build-frontend
WORKDIR /app
COPY frontend/myfrontend/package.json .
COPY frontend/myfrontend/public ./public
COPY frontend/myfrontend/src ./src
RUN npm install .
RUN npm run build
FROM gradle:6.8.2-jre11 AS build-env
# Set the working directory to /home
WORKDIR /home
COPY --chown=gradle:gradle backend ./
COPY --from=build-frontend /app/build /home/src/main/resources/public
# Compile the application.
RUN ./gradlew assemble
FROM openjdk:11.0.10-jre-slim-buster
# Set the working directory to /home
WORKDIR /home
# Copy the compiled files over.
COPY --from=build-env /home/build/libs/myjar-0.1-all.jar /home/myjar.jar
# Starts the java app
# Using EntryPoing to pass env. variables as describe in this article
ENTRYPOINT exec java -XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0 -noverify -XX:+AlwaysPreTouch -jar myjar.jar
Here is my heroku.yml
setup:
addons:
- plan: heroku-postgresql
as: DATABASE
build:
docker:
web: Dockerfile
run:
web: "exec java -XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0 -noverify -XX:+AlwaysPreTouch -jar myjar.jar"
and finally my Micronaut application.yml which just sets some configs
micronaut:
application:
name: mypackage
router:
static-resources:
default:
enabled: true
paths:
- classpath:public
mapping: /**
server:
port: ${PORT:8080}
cors:
enabled: true
datasources:
default:
driverClassName: org.postgresql.Driver
dbUrl: jdbc:postgresql://mydbhost.com:port/dbname?sslmode=require
dbUsername: dbuser
dbPassword: dbpasswd
scan:
packages: mypackage
netty:
default:
allocator:
max-order: 3
When I just do docker build -t test-image:latest . and docker run -p 80:8080 test-image:latest I can connect just fine on localhost and the docker container runs the micronaut server. If it fails for some reason I see an output in the container logs detailing why. When I upload this to heroku (through a github deployment) All i see in the logs are
2023-01-09T22:25:50.145942+00:00 heroku[web.1]: Starting process with command `/bin/sh -c exec\ java\ -XX:\+UseContainerSupport\ -XX:MaxRAMPercentage\=80.0\ -noverify\ -XX:\+AlwaysPreTouch\ -jar\ myjar.jar`
2023-01-09T22:25:51.381760+00:00 heroku[web.1]: Process exited with status 0
2023-01-09T22:25:51.439962+00:00 heroku[web.1]: State changed from starting to crashed
I have tried:
To run it locally connected to the heroku addon postgres database, works just fine
Simplifying the build as much as possible
Removing the default on the port (to ensure it picks up $PORT), and running it locally with export PORT=8080 set (works just fine, docker container picks up the env port like we expect in heroku)
And I cannot figure out why it just quits immediately on Heroku. editted: originally thought it had to do with the port value but but I figured out how to give micronaut a port through the command line and it still doesn't work on Heroku (works locally)
edit:
I tried changing my application.yml to this with the DB hardcoded and still nothing. Just does not seem to work. App still crashes and there is nothing to indicate why in the logs
setup:
config:
PORT: $PORT
MICRONAUT_SERVER_PORT: $PORT
build:
docker:
web: Dockerfile
run:
web: "exec java -Dmicronaut.server.port=$PORT -XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0 -noverify -XX:+AlwaysPreTouch -jar myjar.jar"
I still have no extra output from Heroku. No stacktrace or stderr or stdout at all.
Well, it isn't much of an answer. And nothing in the Heroku docs points me to why this works but removing ENTRYPOINT exec java -XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0 -noverify -XX:+AlwaysPreTouch -jar myjar.jar from my Dockerfile works. With entrypoint removed I see logs again and can see my micronaut server starting. With ENTRYPOINT defined in my Dockerfile I just get what I posted about above "Process starting" followed immediately by process crashed
I have a backend that runs on Spring and I had to create a Docker container.
To do this, I created a .jar file using Maven by running this mvn package then I did the docker run build command to create my container.
Here is the first content of my DockerFile.
FROM openjdk:17-jdk-alpine
COPY target/dwh_webservices-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 443
ENTRYPOINT ["java", "-jar", "/app.jar"]
I want to point out that my Container is perfectly functional with this first method.
However, it's a pain to have to run the command every time. Moreover, I would like to make pipelines and automate the creation of the .JAR with Maven. So I decided to integrate the creation of the .JAR in the Dockerfile.
For that, I followed this question that explains the Multi-stage and I created this Dockerfile :
#
# Build stage
#
FROM maven:3.8.3-openjdk-17 as build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package
#
# Package stage
#
FROM openjdk:17-jdk-alpine
COPY --from=build /home/app/target/dwh_webservices-0.0.1-SNAPSHOT.jar /usr/local/lib/app.jar
EXPOSE 443
ENTRYPOINT ["java", "-jar", "/app.jar"]
And when I run it, I have this error that appears:
com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host BACKENDSERV, port 1433 has failed. Error: "BACKENDSERV Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.
Since it's the exact same source code plus the fact that the first .jar is working, then it should also work. Why, when using the second method, does the application fail to access the host?
What causes this change?
Hi I need to dockerize a system. the way I have to do this like below
steps:
up dynamodb local instance ( just for up ).
run a custom script to create tables ( have to go through this to create the tables ).
then run the system.
I wrote a compose file also. the way I did that was, like below
version: "3"
services:
dynamodb:
image: amazon/dynamodb-local
ports:
- "8000:8000"
networks:
- custom-network
volumes:
- "db-data:/home/dynamodblocal/data"
app:
container_name: my-app
build:
context: .
dockerfile: Dockerfile
args:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
URL: ${URL}
env_file:
- docker.env
depends_on:
- dynamodb
networks:
- custom-network
volumes:
db-data:
networks:
custom-network:
docker file as below. ( sorry had to hide sensitive details )
FROM debian:buster
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG URL
RUN echo "deb http://ftp.us.debian.org/debian sid main" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install openjdk-8-jdk maven awscli -y
RUN aws s3 cp ${URL} db-updater.jar
RUN echo local > input
# there are few lines of configs that wrote to input file
RUN cat input | java -jar db-updater.jar http://dynamodb:8000
WORKDIR /opt/app
COPY . .
RUN mvn package
EXPOSE 8080
CMD ["java","-cp","./app/target/app-1.0.0.jar:./app/target/lib/*"]
my problem is looks like dynamodb do not start before the script run. so script throws a error as can't connect to server.
if I could write a custom a dynamodb with executed script that is also great. please help
Commands in a Dockerfile can never interact with other Docker containers. The general pattern is that an image is built once and reused, so you could delete and recreate your DynamoDB container, or run the same image on a different system, and the database setup wouldn't have happened. Mechanically, the Dockerfile runs in an environment where it's not connected to the Compose networking system, so attempts at connecting between containers will generally fail with a "no such host" error.
A typical pattern is to use an entrypoint script to do first-time setup when the container launches. For example, you could write a simple shell script:
#!/bin/sh
# Seed the database
java -jar db-updater.jar http://dynamodb:8000 < input
# Run whatever the main container command is
exec "$#"
You can then include this in your Dockerfile:
COPY entrypoint.sh . # probably included in the `COPY . .` line
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array syntax
# replaces `RUN java -jar db-updater.jar`
CMD ["java", "-cp", ...] # as in the current Dockerfile
If you only need this to run once when you first set up the container stack, you could also seed the data on your host.
# Outside Docker
aws s3 cp ... db-updater.jar
./make-seed-data.sh > input
# Start the DynamoDB container (only)
docker-compose up -d dynamodb
# Load the seed data
java -jar db-updater.jar -url http://localhost:8000 < input
# Now start the rest of the application
docker-compose up -d
This would let you remove the code to build the input file and download the updater tool from your Dockerfile. It would also let you remove the AWS credentials from the build sequence (very important: it may be possible to find them in plain text looking at the image's docker history).
I have a simple Dockerfile in my spring boot as follow. I am able to build the image successfully locally, and can push using my credentials.
But my build keeps failing on every attempt to build automatically.
FROM openjdk:8-jdk-alpine
LABEL maintainer="xxxxx#xxx.com"
VOLUME /tmp
EXPOSE 8080
ARG JAR_FILE=target/jollof.jar
ADD ${JAR_FILE} jollof.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-
jar","/jollof.jar"]
From docker hub, I got this from the log.
Building in Docker Cloud's infrastructure...
Cloning into '.'...
Warning: Permanently added the RSA host key for IP address 'xxx.xx.xxx.xxx' to
the list of known hosts.
....
....
Step 6/7 : ADD ${JAR_FILE} jollof.jar
ADD failed: stat /var/lib/docker/tmp/docker-
builder674045875/target/jollof.jar:
no such file or directory
Unlike your local environment, Docker Hub fetches then builds your project in a fresh environment, so that the file target/jollof.jar that is intended to be copied is not available in the docker context. Hence the error you observe.
So I'd suggest refactoring your Dockerfile so that mvn package or so is done in the Dockerfile itself (which is a best practice to adopt, for the sake of reproducibility). Note that this configuration will be working for Docker Hub's automated builds as well as the builds in your local environment.
For example, below is an example Dockerfile that inspired by the that of this SO answer How to convert a Spring-Boot web service into a Docker image? as well as the Dockerfile of your post:
FROM maven:3.6-jdk-8 as maven
WORKDIR /app
COPY ./pom.xml ./pom.xml
RUN mvn dependency:go-offline -B
COPY ./src ./src
# TODO: jollof-* should be replaced with the proper prefix
RUN mvn package && cp target/jollof-*.jar app.jar
# Rely on Docker's multi-stage build to get a smaller image based on JRE
FROM openjdk:8-jre-alpine
LABEL maintainer="xxxxx#xxx.com"
WORKDIR /app
COPY --from=maven /app/app.jar ./app.jar
# VOLUME /tmp # optional
EXPOSE 8080 # also optional
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
I put the Dockerfile into the project root.
meaning there's a ./target directory and therein, maven generates a spring-boot-web-0.0.1-SNAPSHOT.jar file.
I now want to add that to a docker image:
FROM centos
RUN yum install -y java # `-y` defaults questions to 'yes'
VOLUME /tmp # where Spring Boot will store temporary files
WORKDIR / # self-explanatory
ADD /target/spring-boot-web-0.0.1-SNAPSHOT.jar myapp.jar # add fat jar as "myapp.jar"
RUN sh -c 'touch ./myapp.jar' # updates dates on the application (important for caching)
EXPOSE 8080 # provide a hook into the webapp
# run the application; the `urandom` gets tomcat to start faster
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/myapp.jar"]
This ADD fails:
ADD failed: stat /var/lib/docker/tmp/docker-builder119635304/myapp.jar: no such file or directory
The solution seems to be moving the comments to their own lines as they will break the commands if they're in the same line as them.
This Dockerfile works prefectly fine:
# a linux runtime environment
FROM centos
# install java; `-y` defaults questions to 'yes'
RUN yum install -y java
# where Spring Boot will store temporary files
VOLUME /tmp
# self-explanatory
WORKDIR /
# add fat jar as "myapp.jar"
ADD /target/spring-boot-web-0.0.1-SNAPSHOT.jar myapp.jar
# updates dates on the application (important for caching)
RUN sh -c 'touch ./myapp.jar'
# provide a hook into the webapp
EXPOSE 8080
# run the application; the `urandom` gets tomcat to start faster
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/myapp.jar"]