-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Notes
Docker Notes
The Oracle XE Docker Container has a few important considerations:
- It's over 1.5GB download
- It may take a minute to run "db setup" the first time
- To avoid the "db setup" time cost each time you run, it may not be practical to run the container fresh each time like most containers, and instead you may want to cache the built database files on a mount (this makes things more complicated though).
- Connect to container:
docker exec -it --user oracle oracle bash
- Access SQL CLI
sqlplus / as sysdba
- Execute script
@/container-entrypoint-initdb.d/01_users.sql
Note: On Linux the "db setup" step results in the directory oradata at the volume mount point being created with root permission, then later the container will attempt to write to that directory as a different user (and fail). This isn't an issue on Windows. The workaround for now is to create the ordata directory in advance with sudo chmod 777 oradata permissions. The owner must also be "oracle:oinstall", which corresponds to uid/gid 54321:54321: chown -R 54321:54321 oradata. The errors that you get if you don't do this are not intuitive. This appears to be a hotly debated topic in Docker, with some complex workarounds like custom entrypoint scripts / base containers that accept UID arguments to run the container with same UID as host user.
Note: The "IF NOT EXISTS" clause doesn't work in Oracle, so if you need to re-run a script that has already been run at startup/setup try to ignore the already exists errors.
Note: Oracle has several official images, but they require login to access from DockerHub, or are older versions with painful management on oracle private repo: https://container-registry.oracle.com/
We need to add both configuration and a deployment artifact to the Wildfly container. We can either:
- build a new container based off of a published wildfly container with copies of our config and deployment artifact already included or
- mount configuration and deployment artifact at runtime (bind volume).
Building your own container means any changes require re-building the container, whereas mounting configuration directories / files is more dynamic. For development, having to rebuild the entire container each time is a no-go so it seems volume bind mount is the way to go.
However, Windows bind mounts into Linux Container of Wildfly configuration and artifacts doesn't work, likely due to the hacky way Windows Subsystem for Linux (WSL) version 2 filesystem and Linux filesystem inside container communicate - the timestamps reported are often off by a tiny bit (milliseconds?), but enough to fool the Wildfly deployment scanner into deploying the artifact non-stop in an endless loop. This phenomenon is hinted at in the Microsoft WSL 2 Issue tracker, in the Docker Desktop for Windows issue tracker, and Wildfly Container issue tracker. It's not exactly a bug in that there are literally two separate "computers" running and their notion of time isn't absolutely exactly synced perfectly (and even the tiniest bit off confuses the heck out of the deployment scanner - container time may always differ by 1 millisecond in the future, which causes re-deployment loop). The solution so far is literally to just use Linux. Even on Windows - use Linux. This means run Docker Desktop from within WSL 2, which thankfully some IDE's running in Windows support doing (Visual Studio Code and IntelliJ for example).
It would be nice to simply volume mount just the standalone.xml file itself. Docker allows single file mounts. However, Wildfly occasionally will overwrite the standalone.xml with standalone.xml.tmp at runtime. This results in:
java.nio.file.FileSystemException: /opt/jboss/wildfly/standalone/configuration/standalone.xml: Device or resource busy
The workaround is to mount the parent configurations directory. Not great because it means you now must provide ALL the configuration files.
See: Wildfly Docker standalone.xml mount
Our Gradle build creates the war file in the build/libs directory. We could simply mount build/libs as the bind volume, but this is problematic if you run Gradle "clean" target, as it will delete the build directory entirely. This confuses the heck out of docker (when you delete the root of the volume mount). To avoid this, we use a war.doLast directive to copy the war to a directory that isn't deleted on clean.