Skip to content

Commit 2bbd7de

Browse files
[DOCKER] UC server container displays welcome message (unitycatalog#392)
This PR changes how the UC server docker image is built (uses the faster `sbt server/package`) and copies the jars required to start it (to `jars` directory). After unitycatalog@4b7aaa3, I thought I'd work on changes that would make the behaviour of the UC server when started consistent regardless whether it's in or outside Docker container (namely the welcome message at the start and no warnings). A Dockerized UC runs in the foreground and containers are removed once stopped.
1 parent c130ea8 commit 2bbd7de

7 files changed

+86
-104
lines changed

Dockerfile

+22-39
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,18 @@ ARG unitycatalog_user_basedir="${unitycatalog_home}/${unitycatalog_user_home}"
1414
# and will cause the process to fail when attempting to compile
1515
# and generate the Uber-Jar. Therefore it is important to choose
1616
# a size large enough for the compiler to run.
17-
ARG sbt_args="-J-Xmx5G"
17+
ARG sbt_args="-J-Xmx2G"
1818
# FIXME Pass it from the outside
1919
ARG unitycatalog_version="0.2.0-SNAPSHOT"
20-
ARG server_assembly_jar="${unitycatalog_repo}/${unitycatalog_jar}/unitycatalog-server-assembly-${unitycatalog_version}.jar"
20+
ARG jars_directory="server/target/jars"
2121

22-
# ###### STAGE 1 ###### #
23-
# Building the Uber-Jar #
24-
#########################
25-
26-
FROM eclipse-temurin:22-jdk-alpine AS assemble_server
22+
FROM eclipse-temurin:17-jdk-alpine AS package_server
2723

2824
ARG unitycatalog_repo
2925
ARG sbt_args
26+
ARG jars_directory
3027

31-
# Install any required packages
28+
# Install required packages
3229
RUN <<EOF
3330
set -ex;
3431
apk update;
@@ -37,20 +34,19 @@ RUN <<EOF
3734
rm -R /var/cache/apk/*;
3835
EOF
3936

40-
# If the WORKDIR doesn't exist, it will be created
41-
# https://docs.docker.com/reference/dockerfile/#workdir
4237
WORKDIR "${unitycatalog_repo}"
4338

4439
COPY . .
4540

46-
# Builds server/target/unitycatalog-server-assembly-0.2.0-SNAPSHOT.jar
47-
RUN build/sbt ${sbt_args} server/assembly
41+
# Builds server/target/unitycatalog-server-0.2.0-SNAPSHOT.jar
42+
RUN build/sbt ${sbt_args} server/package
4843

49-
# ###### STAGE 2 ###### #
50-
# Running the UC server #
51-
#########################
44+
# As a side effect all the required jars to build the UC server
45+
# are listed in server/target/classpath that is generated at build time
46+
# Copy the jar files into a single directory
47+
RUN ./docker/copy_jars_from_classpath.sh ${jars_directory}
5248

53-
FROM eclipse-temurin:22-jre-alpine AS build_uc
49+
FROM eclipse-temurin:17-jdk-alpine AS build_uc
5450

5551
ARG unitycatalog_uid
5652
ARG unitycatalog_home
@@ -63,8 +59,8 @@ ARG unitycatalog_user_name
6359
ARG unitycatalog_user_home
6460
ARG unitycatalog_user_basedir
6561
ARG sbt_args
66-
ARG server_assembly_jar
6762
ARG unitycatalog_version
63+
ARG jars_directory
6864

6965
EXPOSE 8081
7066

@@ -79,21 +75,18 @@ EOF
7975
# Define the shell used within the container
8076
SHELL ["/bin/bash", "-i", "-c", "-o", "pipefail"]
8177

82-
ENV SERVER_ASSEMBLY_JAR="${unitycatalog_jars}/unitycatalog-server-assembly-${unitycatalog_version}.jar"
8378
ENV UC_SERVER_BIN="${unitycatalog_home}/${unitycatalog_bin}/start-uc-server"
8479

85-
# Create the UC directories
86-
RUN <<-EOF
80+
RUN <<-EOF
8781
set -ex;
8882
mkdir -p "${unitycatalog_jars}";
8983
mkdir -p "${unitycatalog_home}/${unitycatalog_etc}";
9084
mkdir -p "${unitycatalog_home}/${unitycatalog_bin}";
9185
mkdir -p "${unitycatalog_home}/${unitycatalog_user_home}";
9286
EOF
9387

94-
9588
# Create system group and user for Unity Catalog
96-
# ENsure the user created has their HOME pointing to the volume
89+
# Ensure the user created has their HOME pointing to the volume
9790
# created to persist user data and the sbt cached files that
9891
# are created as a result of compiling the unity catalog.
9992
# This also ensures that the container can run independently from
@@ -115,11 +108,12 @@ VOLUME "${unitycatalog_home}"
115108

116109
WORKDIR "$unitycatalog_home"
117110

118-
# Copy the Uber-Jar from the previous stage
119-
COPY --from=assemble_server "${server_assembly_jar}" "${unitycatalog_jars}/"
111+
COPY --from=package_server "${server_jar}" "${unitycatalog_jars}/"
120112

121113
# Copy the etc folder which contains the config files and the data folder
122-
COPY --from=assemble_server "${unitycatalog_repo}/${unitycatalog_etc}" "${unitycatalog_home}/${unitycatalog_etc}/"
114+
COPY --from=package_server "${unitycatalog_repo}/${unitycatalog_etc}" "${unitycatalog_home}/${unitycatalog_etc}/"
115+
116+
COPY --from=package_server "${unitycatalog_repo}/${jars_directory}" "${unitycatalog_jars}/"
123117

124118
# Create the script that executes the server
125119
# FIXME It could be already created and simply copied over
@@ -129,27 +123,16 @@ COPY <<-"EOF" "${UC_SERVER_BIN}"
129123
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
130124
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
131125

132-
if [ -z "$SERVER_ASSEMBLY_JAR" ]; then
133-
echo "Server jar '${SERVER_JAR}' not found. Exiting..."
134-
exit 1
135-
fi
136-
137-
# Create relative path to jar so that it is able to find the
138-
# configuration files in etc/conf/...
139-
relative_path_to_jar="${SERVER_ASSEMBLY_JAR//"$ROOT_DIR/"/}"
140-
141-
# FIXME Use cp until mainClass in build.sbt is merged to main
142-
# from which this Dockerfile clones the sources from to build the Docker image
143-
# SERVER_JAVA_COMMAND="java -jar $relative_path_to_jar $@"
144126
SERVER_CLASS_NAME="io.unitycatalog.server.UnityCatalogServer"
145-
SERVER_JAVA_COMMAND="java -cp $relative_path_to_jar ${SERVER_CLASS_NAME} $@"
127+
# A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.
128+
# A class path entry that contains * will not match class files.
129+
SERVER_JAVA_COMMAND="java -cp "jars/classes:jars/*" ${SERVER_CLASS_NAME} $@"
146130

147131
cd ${ROOT_DIR}
148132

149133
exec ${SERVER_JAVA_COMMAND}
150134
EOF
151135

152-
153136
# Set ownership of directories and Unity Catalog home directory to a less
154137
# priviledged user
155138
RUN <<-"EOF"

docker/README.md

+30-36
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ Before you can build the Docker image, install the following tools:
1111

1212
## Building Unity Catalog Server Image
1313

14+
> [!NOTE]
15+
>
16+
> On [Mac computers with Apple silicon](https://support.apple.com/en-us/116943), you may want to change [DOCKER_DEFAULT_PLATFORM](https://docs.docker.com/reference/cli/docker/#environment-variables) environment variable before building the images as follows:
17+
>
18+
> ```bash
19+
> export DOCKER_DEFAULT_PLATFORM=linux/amd64
20+
> ```
21+
1422
[build-uc-server-docker](./bin/build-uc-server-docker) builds the Docker image of Unity Catalog Localhost Reference Server.
1523
1624
```bash
@@ -19,7 +27,8 @@ Before you can build the Docker image, install the following tools:
1927
2028
> [!NOTE]
2129
>
22-
> `build-uc-server-docker` runs the entire sbt build while creating the Docker image.
30+
> `build-uc-server-docker` runs `sbt server/package` build while creating the Docker image.
31+
> That gives all the required jars files part of the image.
2332
2433
`build-uc-server-docker` creates an image named `unitycatalog` with the version from [version.sbt](../version.sbt).
2534

@@ -28,8 +37,8 @@ docker images unitycatalog
2837
```
2938

3039
```text
31-
REPOSITORY TAG IMAGE ID CREATED SIZE
32-
unitycatalog 0.2.0-SNAPSHOT 8b68b233813b About a minute ago 427MB
40+
REPOSITORY TAG IMAGE ID CREATED SIZE
41+
unitycatalog 0.2.0-SNAPSHOT 5771da356693 7 minutes ago 2.58GB
3342
```
3443

3544
## Running Unity Catalog Server Container
@@ -41,36 +50,31 @@ Once the Docker image of Unity Catalog's Localhost Reference Server is built, yo
4150
```
4251

4352
```text
44-
Container unitycatalog does not exist. Creating it...
45-
fbf8a0d2fc6a82f81134c4c50fb4c777399e7095706cb65ff6fe0c158ec43ef4
46-
The container unitycatalog is running with the following parameters:
47-
{
48-
"Command": "\"/bin/bash bin/start…\"",
49-
"CreatedAt": "2024-08-26 18:10:48 +0200 CEST",
50-
"ID": "fbf8a0d2fc6a",
51-
"Image": "unitycatalog:0.2.0-SNAPSHOT",
52-
"Labels": "",
53-
"LocalVolumes": "1",
54-
"Mounts": "3e4bcb63d68a91…",
55-
"Names": "unitycatalog",
56-
"Networks": "bridge",
57-
"Ports": "0.0.0.0:8081->8081/tcp",
58-
"RunningFor": "Less than a second ago",
59-
"Size": "32.8kB (virtual 427MB)",
60-
"State": "running",
61-
"Status": "Up Less than a second"
62-
}
53+
❤️ Starting unitycatalog:0.2.0-SNAPSHOT.
54+
💡 Use Ctrl+C to stop and remove the container.
55+
###################################################################
56+
# _ _ _ _ _____ _ _ #
57+
# | | | | (_) | / ____| | | | | #
58+
# | | | |_ __ _| |_ _ _ | | __ _| |_ __ _| | ___ __ _ #
59+
# | | | | '_ \| | __| | | | | | / _` | __/ _` | |/ _ \ / _` | #
60+
# | |__| | | | | | |_| |_| | | |___| (_| | || (_| | | (_) | (_| | #
61+
# \____/|_| |_|_|\__|\__, | \_____\__,_|\__\__,_|_|\___/ \__, | #
62+
# __/ | __/ | #
63+
# |___/ v0.2.0-SNAPSHOT |___/ #
64+
###################################################################
6365
```
6466

6567
`start-uc-server-docker` starts the Unity Catalog server to listen to `8081`.
6668

69+
In another terminal, execute the following command to learn more about the container.
70+
6771
```bash
6872
docker container ls --filter name=unitycatalog --no-trunc --format 'table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.Ports}}'
6973
```
7074

7175
```text
7276
CONTAINER ID IMAGE COMMAND PORTS
73-
fbf8a0d2fc6a82f81134c4c50fb4c777399e7095706cb65ff6fe0c158ec43ef4 unitycatalog:0.2.0-SNAPSHOT "/bin/bash bin/start-uc-server" 0.0.0.0:8081->8081/tcp
77+
1e15b648d6c2669eb83ac12991323ca288e27d9201c4ecbc8dc15ea2bfa6c389 unitycatalog:0.2.0-SNAPSHOT "/bin/bash bin/start-uc-server" 0.0.0.0:8081->8081/tcp
7478
```
7579

7680
Use the regular non-dockerized Unity Catalog CLI to access the server and list the catalogs.
@@ -102,21 +106,11 @@ docker images unitycatalog-cli
102106
```
103107

104108
```text
105-
REPOSITORY TAG IMAGE ID CREATED SIZE
106-
unitycatalog-cli 0.2.0-SNAPSHOT 52502d16934f About a minute ago 1.48GB
109+
REPOSITORY TAG IMAGE ID CREATED SIZE
110+
unitycatalog-cli 0.2.0-SNAPSHOT c13a37c4e91e 13 seconds ago 1.62GB
107111
```
108112

109-
> [!NOTE]
110-
> In case you run into the following build exception, restart the CLI docker image build.
111-
> ```text
112-
> ❯ ./docker/bin/build-uc-cli-docker
113-
> ...
114-
> [error] java.lang.RuntimeException: Failed to find name hashes for io.unitycatalog.cli.utils.CliUtils
115-
> ...
116-
> [error] (cli / Compile / compileIncremental) Failed to find name hashes for io.unitycatalog.cli.utils.CliUtils
117-
> ```
118-
119-
## Access Unity Catalog Localhost Reference Server
113+
## Access Unity Catalog Server
120114

121115
[start-uc-cli-docker](./bin/start-uc-cli-docker) uses the `unitycatalog-cli` image to run Unity Catalog CLI in a Docker container.
122116

docker/bin/build-uc-cli-docker

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ echo "Changing directory to $project_dir"
1212
cd "$project_dir" || exit
1313

1414
if [[ -r "$docker_file" ]]; then
15-
echo "Building $image_tag from Dockerfile $docker_file"
15+
echo "Building $image_tag using the build definition from $docker_file"
1616
docker buildx build \
1717
--progress=plain \
1818
--no-cache \

docker/bin/build-uc-server-docker

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ script_dir=$(dirname "$0")
55
project_dir=$(dirname "$(dirname "$(realpath "$script_dir")")")
66
docker_file="Dockerfile"
77
container_name="unitycatalog"
8-
container_version=$(< "$project_dir/version.sbt" cut -d '"' -f2)
8+
container_version=$(cut -d '"' -f2 "$project_dir/version.sbt")
99
image_tag=$container_name:$container_version
1010

1111
echo "Changing directory to $project_dir"
1212
cd "$project_dir" || exit
1313

1414
if [[ -r "$docker_file" ]]; then
15-
echo "Building $image_tag from Dockerfile $docker_file"
15+
echo "Building $image_tag using the build definition from $docker_file"
1616
docker buildx build \
1717
--progress=plain \
1818
--no-cache \

docker/bin/start-uc-server-docker

+10-24
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,13 @@
33
script_dir=$(dirname "$0")
44
project_dir=$(dirname "$(dirname "$(realpath "$script_dir")")")
55
container_name="unitycatalog"
6-
container_version=$(< "$project_dir/version.sbt" cut -d '"' -f2)
7-
8-
container_details=$(docker container ls -a -q --filter "name=$container_name")
9-
container_running=$(docker ps -q --filter "name=$container_name")
10-
11-
if [ -z "$container_details" ]; then
12-
echo "Container $container_name does not exist. Creating it..."
13-
docker run \
14-
--tty \
15-
--publish 8081:8081 \
16-
--detach \
17-
--name "$container_name" \
18-
"$container_name:$container_version"
19-
else
20-
if [ -n "$container_running" ]; then
21-
echo "Container $container_name already running, skipping."
22-
else
23-
echo "Container $container_name already exists, starting it."
24-
docker start $container_name
25-
fi
26-
fi
27-
28-
echo "The container $container_name is running with the following parameters:"
29-
docker ps --format '{{json .}}' | jq -r --arg CONTAINER_NAME "$container_name" 'select(.Names == $CONTAINER_NAME)'
6+
container_version=$(cut -d '"' -f2 "$project_dir/version.sbt")
7+
8+
echo "❤️ Starting $container_name:$container_version."
9+
echo "💡 Use Ctrl+C to stop and remove the container."
10+
docker run \
11+
--rm \
12+
--tty \
13+
--publish 8081:8081 \
14+
--name "$container_name" \
15+
"$container_name:$container_version"

docker/copy_jars_from_classpath.sh

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
JARS_DIR="server/target/jars"
4+
if [ "$1" != "" ]; then
5+
JARS_DIR="$1"
6+
fi
7+
8+
echo "Creating $JARS_DIR directory"
9+
mkdir -p "$JARS_DIR"
10+
11+
ONE_SINGLE_CLASSPATH_LINE=$(< server/target/classpath)
12+
13+
IFS=':' read -ra JARS <<< "$ONE_SINGLE_CLASSPATH_LINE"
14+
for jar_file in "${JARS[@]}"
15+
do
16+
# -R recursively copies two classes directories into one classes output directory
17+
# happily, -R works with files too
18+
cp -R "$jar_file" "$JARS_DIR"
19+
done

uc-cli.dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ ARG cli_assembly_jar="${unitycatalog_repo}/${unitycatalog_jar}/unitycatalog-cli-
2323
# Building the Uber-Jar #
2424
#########################
2525

26-
FROM eclipse-temurin:22-jdk-alpine AS assemble_cli
26+
FROM eclipse-temurin:17-jdk-alpine AS assemble_cli
2727

2828
ARG unitycatalog_repo
2929
ARG sbt_args
@@ -50,7 +50,7 @@ RUN build/sbt ${sbt_args} cli/assembly
5050
# Running the UC server #
5151
#########################
5252

53-
FROM eclipse-temurin:22-jre-alpine AS build_cli
53+
FROM eclipse-temurin:17-jdk-alpine AS build_cli
5454

5555
ARG unitycatalog_uid
5656
ARG unitycatalog_home

0 commit comments

Comments
 (0)