I run docker compose to dockerize my Spring Boot app and MySQL database. The dockerization process return successful state but when I run my Spring Boot image, it always return this error:
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate
[com.google.api.client.googleapis.auth.oauth2.GoogleCredential]:
Factory method ‘googleCredential’ threw exception with message:
src/main/resources/keys/uploadfiles.p12 (No such file or directory)
Although my project run smoothly on on my host system, it keep throwing that error on docker container.
Here is my dockerfile:
FROM maven:3.8.3-openjdk-17 as BUILD
WORKDIR /app
COPY . .
RUN mvn install:install-file -Dfile=jdf.jar -DgroupId=cue.lang -DartifactId=word-iterator -Dversion=1.0.0 -Dpackaging=jar
RUN mvn install:install-file -Dfile=VnCoreNLP-1.2.jar -DgroupId=vn.pipeline -DartifactId=vncorenlp -Dversion=1.2.0 -Dpackaging=jar
RUN mvn -f /app/pom.xml -B -DskipTests clean package
FROM openjdk:17-jdk
WORKDIR /app
ARG JAR_FILE_NAME=digital-library-0.0.1-SNAPSHOT.jar
COPY --from=BUILD /app/target/${JAR_FILE_NAME} /app/app.jar
EXPOSE 8080
CMD ["java", "-jar", "/app/app.jar"]
Here is my .dockerignore:
# Ignore everything
*
# Except the following files and folders
!.dockerignore
!jdf.jar
!pom.xml
!VnCoreNLP-1.2.jar
!models/
!src/
Here is my Spring Boot app config:
1st way:
@Bean
public GoogleCredential googleCredential() throws GeneralSecurityException, IOException {
.......................
return new GoogleCredential.Builder()
......................
.setServiceAccountPrivateKeyFromP12File(new File("src/main/resources/keys/uploadfiles.p12"))
.build();
}
2nd ways:
public GoogleCredential googleCredential() throws GeneralSecurityException, IOException, URISyntaxException {
.................
File p12File = Paths.get(getClass().getClassLoader().getResource("keys/uploadfiles.p12").toURI()).toFile();
return new GoogleCredential.Builder()
...............
.setServiceAccountPrivateKeyFromP12File(p12File)
.build();
}
The file is in right folder and correctly refered so I don’t know how to solve this.
2
Answers
I’d say, baking a private key into a Docker image is questionable due to security reasons. I would suggest keeping the private key file outside of the image as well as outside of your source code.
You can create an environment variable, say
GOOGLE_KEY_LOCATION
, and point it to some place in the file system (not in the project’s src).Build the image without the key file. When creating a container, mount a volume for the key file, e.g.,
-v /local/file/system/uploadfiles.p12:/app/uploadfiles.p12:ro
, and set the environment variable to the specified path in the container file system with-e GOOGLE_KEY_LOCATION=/app/uploadfiles.p12
.In your Java code, use
System.getenv("GOOGLE_KEY_LOCATION")
instead of a hardcoded file path.This approach might seem cumbersome, but it lets you keep your source code and docker image free of security-sensitive information and is flexible enough to replace key file without code or image modification.
It could also be that your container is running in a different environment than your host system, and the file paths are not absolute.
Modify your Dockerfile with: