Please note: this question mentions Java and Java keystores, but in reality has nothing to do with Java and should be answerable by anyone with sufficient knowledge of Docker and writing Dockerfiles.
I have a web service (myservice
) that is a JVM application that has been Dockerized. The Dockerfile
for it looks like this:
FROM openjdk:8-jdk-alpine as myenv
COPY application.yml application.yml
COPY ${KS_FILE} mykeystore.p12
COPY build/libs/myservice.jar myservice.jar
EXPOSE 9200
ENTRYPOINT [ \
"java", \
"-Dspring.config=.", \
"-Dkeystore.file=mykeystore.p12", \
"-jar", \
"myservice.jar" \
]
For the record, mykeystore.p12
is a file (not a directory!) that stores the SSL certificate that the service will serve back to any clients attempting to make a connection with it. Specifically it is an encrypted Java keystore but that is way outside the scope of this question, and is besides the point. All that matters is that you understand it is a file, not a directory. I have the file stored on my local machine.
I have the following .env
file in the root of this project as well:
MYENV=local
KS_FILE=../apprunner/certs/mykeystore.p12
Hence, ../apprunner/certs/mykeystore.p12
is a relative path to a location on my file system where mykeystore.p12
lives, and I want that URI stored in the .env
file and used as an environment variable from inside the Dockerfile
.
I build the image like so:
docker build -t myorg/myservice .
And I run a container of that image like so:
docker run -d -p9200:9200 --name myservice --net myrunner_default --env-file .env myorg/myservice
When I SSH into the running container, I do see mykeystore.p12
on the local file system, except...
Its a directory! Not a file!
$ docker exec -it 8391601f451b /bin/sh
/ # ls -al
total 62936
drwxr-xr-x 1 root root 4096 Feb 1 21:24 .
drwxr-xr-x 1 root root 4096 Feb 1 21:24 ..
-rwxr-xr-x 1 root root 0 Feb 1 21:24 .dockerenv
-rw-r--r-- 1 root root 1510 Jan 29 16:27 application.yml
drwxr-xr-x 2 root root 4096 May 9 2019 bin
drwxr-xr-x 7 root root 4096 Jan 30 22:50 mykeystore.p12
-rw-r--r-- 1 root root 64371878 Jan 29 16:27 myservice.jar
drwxr-xr-x 5 root root 340 Feb 1 21:24 dev
drwxr-xr-x 1 root root 4096 Feb 1 21:24 etc
... etc.
And its got lots of weird, unexpected stuff in it, like source files from other directories in my project!
Clearly, something is wrong with either the use of ${KS_FILE}
from inside my Dockerfile
, or with how the URI value is stored in my .env
file. Regardless, what do I have to change such that:
- I specify the file path and name of the
KS_FILE
env var in my.env
file; and - Between my
.env
andDockerfile
, that filepath + name are copied over as a file into the running container, such that when Ils -al
from inside the container, I see it as a file?
There are two problems here.
You can only copy files from your build directory
You cannot copy files that exist outside of your build directory (such as
../apprunner/certs/mykeystore.p12
). If you try reference this file directory in yourDockerfile
, like this:You will see the following error:
Environment variable expansion doesn't work that way
From the documentation:
Since you haven't declared any
ENV
statements in yourDockerfile
, that environment expands as an empty string, so you are getting, in effect:This will simply copy the contents of the build directory into
mykeystore.p12
.docker build
doesn't make use of a.env
file.This article might be helpful.