Using CouchbaseLite Java in a Docker container (Linux)

I’m writing a Java application that will run in a Linux Docker container. I’m a little new at working with Docker, but I’ve managed to resolve the dependencies on the ICU libraries and zlib. The Java application uses CouchbaseLite 2.7.0, so I downloaded the binary and took all the .so shared library files from /support/linux/x86_64 and, within the Dockerfile, copy them to /usr/lib in the Docker container.

However, now when I run the container, I get an error saying that it can’t find “libLiteCore.so”:

Exception in thread “main” java.lang.IllegalStateException: Cannot load native library for Linux/amd64
at com.couchbase.lite.NativeLibrary.load(NativeLibrary.java:60)
at com.couchbase.lite.CouchbaseLite.init(CouchbaseLite.java:54)
at com.quirklogic.pdfconverter.Main.main(Main.java:53)
Caused by: java.lang.UnsatisfiedLinkError: /tmp/com.couchbase.lite.java/native/4869ec7df260e465e58a5086fe8d32f5/libLiteCoreJNI.so: Error loading shared library libLiteCore.so: No such file or directory (needed by /tmp/com.couchbase.lite.java/native/4869ec7df260e465e58a5086fe8d32f5/libLiteCoreJNI.so)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.couchbase.lite.NativeLibrary.load(NativeLibrary.java:55)
… 2 more

Technically, I could build it from here: Build and Deploy On Linux · couchbase/couchbase-lite-core Wiki · GitHub , but it’s not recommended. Is this the right way to use CouchbaseLite Java in a Docker container? I just need CouchbaseLite in this Java app; we already have Sync Gateway and everything else set up. This is just an app that will run on a server that will process requests from client apps.

Thanks!

It just occurred to me, actually, that the libLiteCore.so library is likely included within the Couchbase .jar file, and indeed it is. So the issue is clearly then that the app can’t locate the library, possibly because it’s looking for it relative to the working directory?

It turns out that the architecture of the Docker Linux container is “amd64”, and since all the binaries inside the Couchbase SDK .jar file are located within x86_64 folders, it’s not found when run inside the Docker container. Although copying out libLiteCore.so and placing it in the /usr/lib directory in the container solves the problem.

Interesting. We can look into supporting the alternative name.

Thanks

Filed https://issues.couchbase.com/browse/CBL-1661

Great!

I just hit another wall now though, and it seems to be an issue with web sockets in the Docker container. If I run the Java app from the IDE or the executable itself from the command line, everything works fine. However, when I run it within the Docker container, the app gets stuck here:

I/CouchbaseLite/REPLICATOR:Replicator{@450b4ee,<-,Database{@247240e5, name=‘[redacted]’},URLEndpoint{url=wss://[redacted]:443/data}]: status changed: (0, 0) @C4ReplicatorStatus{level=2, completed=0, total=0, #docs=0, domain=0, code=0, info=0}
I/CouchbaseLite/REPLICATOR:Replicator{@450b4ee,<-,Database{@247240e5, name=‘[redacted]’},URLEndpoint{url=wss://[redacted]:443/data}] is connecting, progress 0/0, error: null

The replicator never connects, and there are no further status updates. I’ve come across some info on exposing web sockets in a Docker container using EXPOSE in the Docker file or running with -p or -P to publish web sockets, but none have worked so far. Any ideas what needs to be done to enable the web socket connection of the replicator to work inside a Docker container?

Looks like a docker networking issue . Choose the option thats right for your setup. I’ve connected to sync gateway docker instance from a non-containerized client - no special setup was required for websockets - in my case, I needed to to ensure that sync gateway is on the same docker network

Thanks, I’ll read over the Docker networking link you sent.

One thing I forgot to mention, though, is that HTTP requests work fine because prior to starting up the replicator, the Java app makes an HTTP request to create a session with our cloud endpoint. So it seems to me the problem is specific to web sockets (since the replicator endpoint is wss://)?

@christianfloisand : can you start a new post for this issue? I’ve filed CBL-1661 to address the original post. This seems like a new and different issue. It will be much easier for us, at least, to manage, if you put the new issue in a new post?

@blake.meike For sure.

Be aware that container and host do have some interactions via the kernel so relying on architecture or values returned from uname -a will give you the host information. Practically it “should” be ok but just something to be aware of: linux kernel - $(uname -a) returning the same in docker host or any docker container - Stack Overflow

There are further complications with the delights of Java and native libraries, e.g. some issues with glibc in different base images: CentOS: Elastic Common Docker Base OS | Elastic Blog

I would expect usage of ldconfig or similar could resolve this issue with libraries being in different folders, that sounds like a config issue with the JRE and base image.