I have a simple Java server app with a Gradle build. It works perfectly with gradle run on my host machine. However, I want to build this in a docker image and run as a docker container.
I'm using docker-machine (version 0.13.0):
docker-machine create --driver virtualbox --virtualbox-memory 6000 default
docker-machine start
eval $(docker-machine env default)
I have the following Dockerfile image build script in ./serverapp/Dockerfile:
FROM gradle:4.3-jdk-alpine
ADD . /code
WORKDIR /code
CMD ["gradle", "--stacktrace", "run"]
I can build perfectly:
➜ docker build -t my-server-app .
Sending build context to Docker daemon 310.3kB
Step 1/4 : FROM gradle:4.3-jdk-alpine
---> b803ec92baec
Step 2/4 : ADD . /code
---> Using cache
---> f458b0be79dc
Step 3/4 : WORKDIR /code
---> Using cache
---> d98d04eda627
Step 4/4 : CMD ["gradle", "--stacktrace", "run"]
---> Using cache
---> 869262257870
Successfully built 869262257870
Successfully tagged my-server-app:latest
When I try to run this image:
➜ docker run --rm my-server-app
FAILURE: Build failed with an exception.
* What went wrong:
Could not create service of type ScriptPluginFactory using BuildScopeServices.createScriptPluginFactory().
> Could not create service of type CrossBuildFileHashCache using BuildSessionScopeServices.createCrossBuildFileHashCache().
* Try:
Run with --info or --debug option to get more log output.
* Exception is:
org.gradle.internal.service.ServiceCreationException: Could not create service of type ScriptPluginFactory using BuildScopeServices.createScriptPluginFactory().
at org.gradle.internal.service.DefaultServiceRegistry$FactoryMethodService.invokeMethod(DefaultServiceRegistry.java:797)
<snip>
... 60 more
Caused by: org.gradle.api.UncheckedIOException: Failed to create parent directory '/code/.gradle/4.3' when creating directory '/code/.gradle/4.3/fileHashes'
at org.gradle.util.GFileUtils.mkdirs(GFileUtils.java:271)
at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:56)
Why would it have trouble creating that directory?
This should be a very easy task, can anyone tell me how they get this simple scenario working?
FYI, running current versions of everything. I'm using Gradle 4.3.1 on my host, and the official Gradle 4.3 base image from docker hub, I'm using the current version of JDK 8 on my host and the current version of docker, docker-machine, and docker-compose as well.
The fix was to specify --chown=gradle permissions on the /code directory in the Dockerfile. Many Docker images are designed to run as root, the base Gradle image runs as user gradle.
FROM gradle:4.3-jdk-alpine
ADD --chown=gradle . /code
WORKDIR /code
CMD ["gradle", "--stacktrace", "run"]
Ethan Davis suggested using /home/gradle rather than code. That would probably work as well, but I didn't think of that.
The docker image maintainer should have a simple getting started type reference example that shows the recommended way to get basic usage.
Based on the openjdk base image to the gradle image we can see that gradle projects are setup to run in /home/gradle. Check the code out here. gradle run is having trouble running in your new working directory, /code, because the .gradle folder is in the /home/gradle folder. If you copy/add your code into /home/gradle you should be able to run gradle run. This worked for me.
Related
I'm building a Docker image from a Dockerfile, but I dont know if when I execute the npm install command, the server is installing the dependencies from packege.json. I want to check in real time the progress of the dependencies installation, is it possible?
CMD:
docker build -t angular-frontend:prod .
OUTPUT:
Sending build context to Docker daemon 1.264 MB
Step 1 : FROM node:carbon
---> 99bbd77c18fe
Step 2 : WORKDIR /app
---> Running in 1d914a408725
---> fca47246ff16
Removing intermediate container 1d914a408725
Step 3 : COPY package.json /app/
---> 793227e711d4
Removing intermediate container 1f9c5341747e
Step 4 : RUN npm install
---> Running in ddee013be29c
What do I want:
See whats happening inside the container. Any hints?
This is not a Docker problem. Docker outputs the logs during build. For instance, if you do RUN composer update in your Dockerfile, then you get the output. For example, here's our RUN composer update output during Dockerfile build on codeship:
See? The output is right there! So, what you need is to tell your npm to log verbosely:
RUN npm install --loglevel verbose
This should output the logs in real time and also save your log into npm-debug.log file.
I am using jenkins image to create a docker container. For now I am just trying to create a new directory and copy a couple of files. The image build process runs fine but when I start the container I cannot see the files and the directory.
Here is my dockerfile
FROM jenkins:2.46.1
MAINTAINER MandeepSinghGulati
USER jenkins
RUN mkdir /var/jenkins_home/aws
COPY aws/config /var/jenkins_home/aws/
COPY aws/credentials /var/jenkins_home/aws/
I found a similar question here but it seems different because I am not creating the jenkins user. It already exists with home directory /var/jenkins_home/. Not sure what I am doing wrong
Here is how I am building my image and starting the container:
➜ jenkins_test docker build -t "test" .
Sending build context to Docker daemon 5.632 kB
Step 1/6 : FROM jenkins:2.46.1
---> 04c1dd56a3d8
Step 2/6 : MAINTAINER MandeepSinghGulati
---> Using cache
---> 7f76c0f7fc2d
Step 3/6 : USER jenkins
---> Running in 5dcbf4ef9f82
---> 6a64edc2d2cb
Removing intermediate container 5dcbf4ef9f82
Step 4/6 : RUN mkdir /var/jenkins_home/aws
---> Running in 1eb86a351beb
---> b42587697aec
Removing intermediate container 1eb86a351beb
Step 5/6 : COPY aws/config /var/jenkins_home/aws/
---> a9d9a28fd777
Removing intermediate container ca4a708edc6e
Step 6/6 : COPY aws/credentials /var/jenkins_home/aws/
---> 9f9ee5a603a1
Removing intermediate container 592ad0031f49
Successfully built 9f9ee5a603a1
➜ jenkins_test docker run -it -v $HOME/jenkins:/var/jenkins_home -p 8080:8080 --name=test-container test
If I run the command without the volume mount, I can see the copied files and the directory. However with the volume mount I cannot see the same. Even if I empty the directory on the host machine. Is this the expected behaviour? How can I copy over files to the directory being used as a volume ?
Existing volumes can be mounted with
docker container run -v MY-VOLUME:/var/jenkins_home ...
Furthermore, the documentation of COPY states:
All new files and directories are created with a UID and GID of 0.
So COPY does not reflect your USER directive. This seems to be the second part of your problem.
I'm Test Automation engineer and working in big product company. Companies big monolithic project being divided and parts are departuring into clouds. As part of such redesign Test Automation projects should also get cloudy. Our typical TA project based on groovy, selenium, testng and maven. Now I want to try the option of putting whole TA maven project into Docker image\container. Its works well, but on the very first run it starts download dependencies into local .m2 repository. I want to speed up and have this task done on a creation image stage.
Here is a my DOCKERFILE:
FROM maven:3.3-jdk-8
LABEL description="Embedded portal-web-testing"
MAINTAINER NNN
COPY ./settings.xml /root/.m2/
COPY ./acceptance-tests ./acceptance-tests
WORKDIR acceptance-tests
RUN mvn dependency:go-offline --debug >log
RUN ls /root/.m2/
#RUN mvn test
ENTRYPOINT ["bash"]
And here is a log:
Step 1 : FROM maven:3.3-jdk-8
---> 7addddbdd730
Step 2 : LABEL description "Embedded portal-web-testing"
---> Running in 1d195ccb9c57
---> f5372b024ca0
Removing intermediate container 1d195ccb9c57
Step 3 : MAINTAINER NNN
---> Running in 03ebbffda680
---> cb12da3d8ec6
Removing intermediate container 03ebbffda680
Step 4 : COPY ./settings.xml /root/.m2/
---> 164999e1f63a
Removing intermediate container 1e1778d2533b
Step 5 : COPY ./acceptance-tests ./acceptance-tests
---> 7d93fff4193e
Removing intermediate container a5d04eb30591
Step 6 : WORKDIR acceptance-tests
---> Running in f15111475fc6
---> beb4d090362b
Removing intermediate container f15111475fc6
Step 7 : RUN mvn dependency:go-offline --debug >log
---> Running in 2c09f1869143
---> 62326c2bb073
Removing intermediate container 2c09f1869143
Step 8 : RUN ls /root/.m2/
---> Running in 91b602f529da
settings.xml
---> b7bc32199ab3
Removing intermediate container 91b602f529da
Step 9 : ENTRYPOINT bash
---> Running in 3167f5a6d923
---> 94b3e0b146da
Removing intermediate container 3167f5a6d923
Successfully built 94b3e0b146da
On Step 7 surely files being downloaded, but looks like not stored.
Following console command shows that there are no updates in local .m2 folder:
root#37f5a0d04232:/acceptance-tests# ls /root/.m2
settings.xml
If I try to run same command again from command line inside a container (when image is created and container had started):
root#37f5a0d04232:/acceptance-tests# mvn dependency:go-offline
Massive downloads starts and repository folder finally appeared under .m2
root#37f5a0d04232:/acceptance-tests# ls /root/.m2
repository settings.xml
I struggle to understand why changes caused by maven command from Dockerbuild file did not stored as docker layer.
I am using Docker 1.12 and maven 3.3.3
/root/.m2 is a volume that is why it gets cleared when docker container is launched. This can be avoided by caching the content in a custom directory and then copying it to /root/.m2 when container is launched.
Fortunately maven image is pre-baked with all the copying logic so you just have to point repository as:
RUN mvn -B -f /tmp/pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
The entry-point will take care of setting local repository for you. It helped me hope it helps you as well.
Also, for reference visit.
All, i'm trying to persistently copy files from my host to an image so those files are available with every container launched based on that image. Running on debian wheezy 64bit as virtualbox guest.
the Dockerfile is fairly simple (installing octave image):
FROM debian:jessie
MAINTAINER GG_Python <[redacted]#gmail.com>
RUN apt-get update
RUN apt-get update
RUN apt-get install -y octave octave-image octave-missing-functions octave-nan octave-statistics
RUN mkdir /octave
RUN mkdir /octave/libs
RUN mkdir /octave/libs/jsonlab
COPY ~/octave/jsonlab/loadjson.m /octave/libs/jsonlab/.
I'm getting the following trace after issuing a build command: docker build -t octave .
Sending build context to Docker daemon 423.9 kB
Sending build context to Docker daemon
Step 0 : FROM debian:jessie
---> 58052b122b60
Step 1 : MAINTAINER GG_Python <[..]#gmail.com>
---> Using cache
---> 90d2dd2f7ee8
Step 2 : RUN apt-get update
---> Using cache
---> 4c72c25cd829
Step 3 : RUN apt-get update
---> Using cache
---> b52f0bcb9f86
Step 4 : RUN apt-get install -y octave octave-image octave-missing-functions octave-nan octave-statistics
---> Using cache
---> f0637ab96d5e
Step 5 : RUN mkdir /octave
---> Using cache
---> a2d278b2819b
Step 6 : RUN mkdir /octave/libs
---> Using cache
---> 65efbbe01c99
Step 7 : RUN mkdir /octave/libs/jsonlab
---> Using cache
---> e41b80901266
Step 8 : COPY ~/octave/jsonlab/loadjson.m /octave/libs/jsonlab/.
INFO[0000] ~/octave/jsonlab/loadjson.m: no such file or directory
Docker absolutely refuses to copy this file from the host into the image. Needless to say a the file loadjson.m is there (cat displays), all my attempts to change the path (relative, absolute, etc.) failed. Any advice why this simple task is problematic?
At the time I originally wrote this, Docker didn’t expand ~ or $HOME. Now it does some expansions inside the build context, but even so they are probably not what you want—they aren’t your home directory outside the context. You need to reference the file explicitly, or package it relative to the Dockerfile itself.
Docker can only copy files from the context, the folder you are minus any file listed in the dockerignore file.
When you run 'docker build' docker tars the context and it sends it to the docker daemon you are connected to. It only lets you copy files inside of the context because the daemon might be a remote machine.
I couldn't get COPY to work until I understood the context (I was trying to copy a file from outside of the context)
The docker build command builds an image from a Dockerfile and a context. The build’s context is the files at a specified location PATH. The PATH is a directory on your local filesystem.
A context is processed recursively. So, a PATH includes any subdirectories.
The build is run by the Docker daemon, not by the CLI. The first thing a build process does is send the entire context (recursively) to the daemon. In most cases, it’s best to start with an empty directory as context and keep your Dockerfile in that directory. Add only the files needed for building the Dockerfile.
Warning: Do not use your root directory, /, as the PATH as it causes the build to transfer the entire contents of your hard drive to the Docker daemon.
Reference:
https://docs.docker.com/engine/reference/builder/#usage
I had similar issue. I solved it by checking two things:
Inside your, docker-compose.yaml check context of the service, docker will not copy any file outside of this directory. For example if the context is app/ then you cannot copy anything from ../app
Check .dockerignore to be sure that you are not ignoring the file you want to copy.
I got it working by first checking what the context was,
setting an absolute path before the source file in
your Dockerfile to get that information:
# grep COPY Dockerfile
COPY /path/to/foo /whatever/path/in/destination/foo
Building with that:
docker build -t bar/foo .
you'll get an error, which states the context-path that Docker
is apparently looking into for its files, e.g.
it turns out to be:
/var/lib/docker/tmp # I don't remember
Copying(!) your set of build-files in that directory (here: /var/lib/docker/tmp),
cd into it, build from there.
See if that works, and don't forget to do some housekeeping cleaning up
the tmp, deleting your files before the next visit(or).
HTH
Michael
Got this error using a Dockerfile for a linux container on a Windows machine:
#24 1.160 Skipping project "/src/Common/MetaData/Metadata.csproj" because it was not found.
Restore worked perfectly on the host machine.
Turned out to be the error mentioned here:
https://stackoverflow.com/a/68592423/3850405
A .csproj file did not match casing in Visual Studio vs the file system.
I'm playing around with Google's Dart docker image. I'm trying to build a Hello World app that listens on port 80. I'm running it on Ubuntu Server 14 on Azure.
If I run the google/dart-hello, it all works fine, and I can connect on port 8080.
The google/dart-hello image is based on the google/dart-runtime image, which is in turn, based on google/dart. The base image adds Dart; google/dart-runtime adds a Dockerfile which expects to execute bin/server.dart and expose port 8080, and google/dart-hello supplies the bin/server.dart (and pubspec.yaml) to make it work. google/dart-runtime isn't useful on its own, because it doesn't contain a bin/server.dart or pubspec.yaml.
So, google/dart-runtime is a good base if your server is at bin/server.dart and you want to listen on port 8080. As I want to listen on port 80, I'm using the google/dart image as a base, hoping to squash what's in google/dart-runtime and google/dart-hello into my container, but changed to port 80.
You can find the sources repos for the three Google images here:
google/dart
google/dart-runtime (Dockerfile)
google/dart-hello (Dockerfile)
So, I've taken the Dockerfile from google/dart-runtime and the files from google/dart-hello, so I have the following:
FROM google/dart
WORKDIR /app
ONBUILD ADD pubspec.yaml /app/
ONBUILD ADD pubspec.lock /app/
ONBUILD RUN pub get
ONBUILD ADD . /app
ONBUILD RUN pub get
CMD []
ENTRYPOINT ["/usr/bin/dart", "/app/bin/server.dart"]
EXPOSE 80
In the same directory as this Dockerfile, I have the following files:
bin/server.dart
pubspec.yaml
pubspec.lock
I'm building the image with:
sudo docker build --no-cache -t dart-test .
And here's the output:
danny#linux:~/dart_test$ sudo docker build --no-cache -t dart-test .
Sending build context to Docker daemon 5.632 kB
Sending build context to Docker daemon
Step 0 : FROM google/dart
---> cd92c7fff717
Step 1 : WORKDIR /app
---> Running in d163d2597eba
---> 2802d6769b76
Removing intermediate container d163d2597eba
Step 2 : ONBUILD ADD pubspec.yaml /app/
---> Running in 7b8be2a481c2
---> 096cbe12a2cd
Removing intermediate container 7b8be2a481c2
Step 3 : ONBUILD ADD pubspec.lock /app/
---> Running in 6ae0243b0dee
---> 80f20ebafa87
Removing intermediate container 6ae0243b0dee
Step 4 : ONBUILD RUN pub get
---> Running in 621d4ce5c7f1
---> 89a509d41b11
Removing intermediate container 621d4ce5c7f1
Step 5 : ONBUILD ADD . /app
---> Running in 4de26a33487f
---> b69c65f12441
Removing intermediate container 4de26a33487f
Step 6 : ONBUILD RUN pub get
---> Running in f7cc689f6f81
---> 2ccc79ea6d04
Removing intermediate container f7cc689f6f81
Step 7 : CMD []
---> Running in 10bd31eb6679
---> f828267f00b5
Removing intermediate container 10bd31eb6679
Step 8 : ENTRYPOINT ["/usr/bin/dart", "/app/bin/server.dart"]
---> Running in 013d3ca0f25d
---> a63b59f9fd05
Removing intermediate container 013d3ca0f25d
Step 9 : EXPOSE 80
---> Running in 4301c572e598
---> 75a4317c135c
Removing intermediate container 4301c572e598
Successfully built 75a4317c135c
However, if I try to run this (using sudo docker run --rm -i -t dart-test), I get the following error:
danny#linux:~/dart_test$ sudo docker run -i -t --rm dart-test
Unhandled exception:
Uncaught Error: FileSystemException: Cannot open file, path = '/app/bin/server.dart' (OS Error: No such file or directory, errno = 2)
If I replace the dart execution in the Dockerfile with /bin/bash instead, then when I build and run, I get put into bash at /app/ but the folder is empty.
I've tried this with both the 0.9(?) version and 1.2 (one that came from apt-get docker.io and the other from the more-involved instructions on the Docker website), since I noticed a mention of an ADD fix in the release notes. Both do the same.
I can find lots of info online that people often pipe Dockerfile into STDIN which means there's no context, but you can see in my output that 5KB of data is being sent; though it's possible this is just the Dockerfile and nothing else I guess? They are in the same directory, here's a listing:
danny#linux:~/dart_test$ dir
bin Dockerfile pubspec.lock pubspec.yaml
The ONBUILD instruction is only useful when you create a base image that will be used later by another Dockerfile (see the documentation).
Here because you write the final Dockerfile, you just need to remove the ONBUILD instructions (but keep the raw instructions ADD, RUN, etc).
In your Dockerfile you need to remove the ONBUILD prefixes from your instructions. The ONBUILD prefix is a way to defer execution of certain instructions until this image is referenced by another Dockerfile. Those instructions are stored as part of the metadata for the image that you created but the instructions themselves are not executed until that image is referenced in the FROM field of another Dockerfile.
What you really want is this:
FROM google/dart
WORKDIR /app
ADD pubspec.yaml /app/
ADD pubspec.lock /app/
RUN pub get
ADD . /app
RUN pub get
CMD []
ENTRYPOINT ["/usr/bin/dart", "/app/bin/server.dart"]
EXPOSE 80
The docker image google/dart-runtime is intended to be a base image for your Dart server application. So in your project the Dockerfile should have just the following content
FROM google/dart-runtime
The when you run docker build the ONBUILD commands in the base image will be executed.
If you look at the Dockerfile for google/dart-hello you will see that it has just that one line.