From inside the image: container-registry.oracle.com/database/instantclient:12.2.0.1
I am installing glibc-static with:
yum-config-manager --enable ol7_optional_latest && yum install glibc-static
Then I am getting the following error (note that it compiles fine when I'm not trying to statically compile it):
bash-4.2# go build --ldflags '-linkmode external -extldflags "-I/usr/include/oracle/12.2/client64 -L/usr/lib/oracle/12.2/client64/lib -lclntsh -static"' -a -o /go/bin/oracle_ld github.com/veqryn/personal/src/oracle
# github.com/veqryn/personal/src/oracle
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -lclntsh
/usr/bin/ld: cannot find -lclntsh
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libpthread.a(libpthread.o): In function `sem_open':
(.text+0x6823): warning: the use of `mktemp' is dangerous, better use `mkstemp'
collect2: error: ld returned 1 exit status
bash-4.2#
bash-4.2# ls -la /usr/lib/oracle/12.2/client64/lib
total 219708
drwxr-xr-x 2 root root 4096 Apr 5 00:02 .
drwxr-xr-x 4 root root 4096 Apr 5 00:02 ..
-rw-rwxr-- 1 root root 342 Jan 26 13:14 glogin.sql
lrwxrwxrwx 1 root root 17 Apr 5 00:02 libclntsh.so -> libclntsh.so.12.1
-rw-rwxr-- 1 root root 71638263 Jan 26 13:14 libclntsh.so.12.1
lrwxrwxrwx 1 root root 21 Apr 5 00:02 libclntshcore.so -> libclntshcore.so.12.1
-rw-rwxr-- 1 root root 8033199 Jan 26 13:14 libclntshcore.so.12.1
-rw-rwxr-- 1 root root 2981501 Jan 26 13:14 libipc1.so
-rw-rwxr-- 1 root root 539065 Jan 26 13:14 libmql1.so
-rw-rwxr-- 1 root root 6568149 Jan 26 13:14 libnnz12.so
lrwxrwxrwx 1 root root 15 Apr 5 00:02 libocci.so -> libocci.so.12.1
-rw-rwxr-- 1 root root 2218687 Jan 26 13:14 libocci.so.12.1
-rw-rwxr-- 1 root root 124771800 Jan 26 13:14 libociei.so
-rw-rwxr-- 1 root root 158543 Jan 26 13:14 libocijdbc12.so
-rw-rwxr-- 1 root root 380996 Jan 26 13:14 libons.so
-rw-rwxr-- 1 root root 116563 Jan 26 13:14 liboramysql12.so
-rw-rwxr-- 1 root root 1559466 Jan 26 13:14 libsqlplus.so
-rw-rwxr-- 1 root root 1641005 Jan 26 13:14 libsqlplusic.so
-rw-r--r-- 1 root root 3984814 Jan 26 13:15 ojdbc8.jar
-rw-rwxr-- 1 root root 312974 Jan 26 13:14 ottclasses.zip
-rw-r--r-- 1 root root 37494 Jan 26 13:15 xstreams.jar
bash-4.2# printenv | sort
GOPATH=/go
GOROOT=/usr/local/go
GO_VERSION=1.8.3
HOME=/root
HOSTNAME=oracle-golang
LD_LIBRARY_PATH=/usr/lib/oracle/12.2/client64/lib
NLS_LANG=American_America.AL32UTF8
ORACLE_HOME=/usr/lib/oracle/12.2/client64
ORACLE_INCLUDE=/usr/include/oracle/12.2/client64
PATH=/go/bin:/usr/local/go/bin:/usr/lib/oracle/12.2/client64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/oracle/12.2/client64/bin
PKG_CONFIG_PATH=/usr/include/oracle/12.2/client64:/usr/lib64/pkgconfig:/usr/share/pkgconfig
PWD=/
SHLVL=1
TERM=xterm
_=/usr/bin/printenv
go build --ldflags '-linkmode external -extldflags "-static"' -a -o /go/bin/oracle_ld github.com/veqryn/personal/src/oracle gives the same error
CGO_LDFLAGS=-L/usr/lib/oracle/12.2/client64/lib -lclntsh -static CGO_CFLAGS=-I/usr/include/oracle/12.2/client64 go build -a -o /go/bin/oracle_ld github.com/veqryn/personal/src/oracle gives the same error
Have you looked at https://github.com/go-goracle/goracle/tree/v2.0.0 ?
You can build ODPI-C as a library and then stick it where Instant Client is (or other location in LD_LIBRARY_PATH)
I'll give a try, thx!
So odpi-c still requires and uses the oracle instant client libraries, so I don't think odpi-c will help...
@veqryn can you clarify your deployment goals, i.e. define 'fix it'?
Applications and even the OS needs various system libraries. Instant Client and ODPI-C can be thought of as similar generic libraries that need to be installed before you install Go.
We statically compile our deployment binaries, and then deploy them into production (ie: kubernetes cluster, etc) on containers that don't have anything else:
FROM scratch
ADD mystaticbinary
ENTRYPOINT ["/mystaticbinary"]
We also use alpine as a base container, which requires its binaries to be static or compiled for musl-c, not glibc.
FROM alpine:3.6
ADD mystaticbinary
ENTRYPOINT ["/mystaticbinary"]
Besides making extremely small container images (ie: 6mb instead of 600mb), it eliminates the attack surface area of all the packages that are normally installed on larger images.
The binary created can be deployed to any container or linux os and run, which is great for portability.
@veqryn Thanks for the succinct business case.
I'm intrigued why the Go community seems to have a focus on static builds. Have you seen https://stackoverflow.com/questions/38785691/trying-to-build-static-cgo-executable-with-oracle-libraries-on-linux-ubuntu ? It's definitely not a 'Supported' configuration! I'd be interested to know whether you get it working.
Not only am I missing the relink tool, but resolving missing symbols by hand is probably above my ability at this point.
It is unfortunate there is not an easier way to get the static version of oracle's libraries...
Hey @gvenzl, can you ping someone from the instant client team to take a look at this?
@cjbj is the PM for the Instant client and by reading through that thread has provided a sufficient answer. Even if Oracle was to provide a static version of the client libraries in a future release, it doesn't solve the immediate issue of insufficient knowledge on how to resolve the missing symbols.
@cjbj, is there anything more that you can do for @veqryn? Any further blog articles, how-to's, etc. on this topic?
Are you saying that if Oracle was to provide a static version of the client libraries, they wouldn't include the symbols with them?
I don't think I've ever had this problem with any other libraries I've statically compiled into my golang binaries.
Nope, I'm saying that even if Oracle decides to provide a static link library in the future you would still have to wait for that release to happen which won't help you now.
Oh ok, I misread. An Oracle provided static client library would be something to look forward to, for sure.
Just reading through some history about linking & licensing my team pointed out, I wouldn't hold your breath for Instant Client static libraries. Note the Linux doc (referring to the full Oracle install which does have some static libs for various reasons) says:
You must use the dynamic Oracle client libraries to link the client code on Linux. Do not link the static Oracle client libraries.
Understood.
What would it take to get that changed in the future (ie: next few years), so that what I'm trying to do would be possible?
@cjbj we could skip the static libraries if you guys did a pure go client :-)
Would be great if we had a oracle client in pure Go.
The 200mb required only for oracle instant client libs are insane, specially in cloud environments, not to mention that is a terrible pratice copy those .so to our docker images.
@arthurpessoa Your point is well known and we'll continue to make improvements but it's only half as bad now as you state :) The minimal Instant Client Basic (with non OCI files removed) is less than 90MB on Linux 64-bit.
What these client libraries give you is a common, highly tested layer that does things like:
It would be a significant engineering effort to try and reimplement this kind of functionality in each database driver (Python cx_Oracle, Node.js node-oracledb etc), not to mention make each of those drivers more complex, introduce new sets of errors, and make each driver significantly bigger.
@cjbj you guys do have a platform independent JDBC Thin driver written in pure Java. As I understand it doesn't have all the features and performance characteristics of the full driver. What are the chances of something like the JDBC Thin Driver in pure Go?
@oxplot that's a big question and a big topic. What features would you be willing to give up?
@cjbj for me personally, I'd give up all Oracle specific features and keep as much of the security related ones (e.g. encrypted connection, etc.). Basically, making it safe and useful for majority of use cases. Unfortunately I have very little knowledge of specific features and how crucial each of them are in the overall working of the driver.
@oxplot what datatypes are you using? What's the ratio of writes to reads? I guess in reality this doesn't matter because everyone's use case is different! But it's still interesting to know if you care to share.
@cjbj As for types, mostly the standard SQL ones, like integer/number/varchar/date/time and sometimes blobs. I'd say the read to write ratio is average 1:1. We use oracle for data migration and most of the heavy lifting is done in the migration scripts.
@oxplot thank you.
@cjbj this is another vote for getting to a statically compiled binary.
Statically compiled binaries are actually more portable in my experience across various Linux distributions.
Static compilation typically isn't important to dev teams. It is important to operations teams in production. It simplifies operations and deployments, and also makes it easier for multiple versions to exist in an environment. Long term maintenance is simplified.
We have strategically chosen Go for this precise reason: simplified operations and deployment especially when we do not have full control over operating environments.
It is not true that it is easy to install software or dependencies on servers that are not fully owned by you.
@theonewolf I don't think that this is going to happen, this is a long time request from the community and has never been prioritized. Hopefully in a near future we'll at least be able to use java's drivers in golang through graal abstractions. Meanwhile we're using more "oracledb" friendly languages for our legacy integrations, and all other microservices are using databases with better driver interoperability.
@arthurpessoa yeah I agree with you. We had a deployment issue hit us which would have been completely avoided if we were statically compiled.
I might investigate some really tricky techniques to achieve a better hybrid approach, or something even exotic to get a solid static binary (slightly different than a normal one though). It is valuable to us to get things more tighter for production deployments (other than moving to full containers / VMs which aren't always possible).
@arthurpessoa what languages are you using?
To complete the circle, @theonewolf and I had a discussion today at https://github.com/go-goracle/goracle/issues/65#issuecomment-464224123
@arthurpessoa: to be expand on my request for information, the more information the better so that we can make a good business case. Without details about the actual business impact, any request becomes toothless. So if you can share platforms, numbers, plans etc that would help. My email is in my profile.
Most helpful comment
@cjbj this is another vote for getting to a statically compiled binary.
Statically compiled binaries are actually more portable in my experience across various Linux distributions.
Static compilation typically isn't important to dev teams. It is important to operations teams in production. It simplifies operations and deployments, and also makes it easier for multiple versions to exist in an environment. Long term maintenance is simplified.
We have strategically chosen Go for this precise reason: simplified operations and deployment especially when we do not have full control over operating environments.
It is not true that it is easy to install software or dependencies on servers that are not fully owned by you.