Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
**/target/
**/logs/
**/*.log
**/*.log.*
**/dynamodb-local-metadata.json
**/heap-dumps/

**/*.tar.gz
**/*.tar.bz2
**/*.zip

.idea/
.vscode/
.cursor/
.DS_Store

.git/
.gitignore

docker/README.md
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,41 @@ The Phoenix DynamoDB REST service is fully compatible with AWS SDKs. You can con
port 8842 with zk-quorum localhost:2181.
Alternative to `-z <zk-quorum>` is env variable `ZOO_KEEPER_QUORUM`.

#### One-shot Docker setup (recommended for first-time users)

Skip steps 1-2 above with the bundled Docker cluster. From a fresh clone:

**Prerequisites:** Docker Desktop running; `jq` and `curl` on `PATH`
(`brew install jq` on macOS).

```bash
# 1. Bring up the full stack at the versions pinned in pom.xml and BLOCK
# until every container reports healthy (REST is ~30-60s on cold start).
# First time: ~8-12 min total -- most of that is Maven downloading
# ~1.5 GB of dependencies into the BuildKit cache mount. Subsequent
# runs reuse the cache and rebuild in seconds.
docker compose -f docker/docker-compose.yml up -d --build --wait

# 2. Validate it works end-to-end (CRUD + UpdateItem + BatchWriteItem + streams).
bash docker/scripts/smoke.sh
# -> "Result: 21 checks PASSED across 18 API calls"

# 3. Use it. The DynamoDB-compatible endpoint is at http://localhost:8842 .
# Point any AWS SDK at it (Java/Python/Node.js snippets in
# phoenix-ddb-rest/README.md), or hit it with curl:
curl -s -X POST http://localhost:8842/ \
-H 'Content-Type: application/x-amz-json-1.0' \
-H 'X-Amz-Target: DynamoDB_20120810.ListTables' -d '{}'

# 4. Tear down when you're done.
docker compose -f docker/docker-compose.yml down -v
```

See [`docker/README.md`](docker/README.md) for the full reference: port
mappings, the developer inner loop for code changes, the smoke-test
breakdown, troubleshooting, and how to run the REST server outside
Docker against the dockerized cluster.

### Building Distribution Tarball

To build a distribution tarball that includes all components:
Expand Down
63 changes: 63 additions & 0 deletions docker/Dockerfile.hbase-phoenix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# syntax=docker/dockerfile:1
FROM eclipse-temurin:8-jdk-jammy

ARG HBASE_VERSION=2.5.14
ARG HBASE_FLAVOR=hadoop3
ARG PHOENIX_HBASE_LINE=2.5
ARG PHOENIX_VERSION=5.3.1

ENV HBASE_VERSION=${HBASE_VERSION} \
HBASE_FLAVOR=${HBASE_FLAVOR} \
PHOENIX_HBASE_LINE=${PHOENIX_HBASE_LINE} \
PHOENIX_VERSION=${PHOENIX_VERSION} \
JAVA_HOME=/opt/java/openjdk \
HBASE_HOME=/opt/hbase \
HBASE_CONF_DIR=/opt/hbase/conf \
PHOENIX_HOME=/opt/phoenix \
HBASE_MANAGES_ZK=false \
PATH=/opt/hbase/bin:/opt/phoenix/bin:/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
bash curl ca-certificates netcat-openbsd procps tini less; \
rm -rf /var/lib/apt/lists/*

RUN set -eux; \
mkdir -p "${HBASE_HOME}"; \
curl -fSL --retry 5 --retry-delay 5 \
"https://archive.apache.org/dist/hbase/${HBASE_VERSION}/hbase-${HBASE_VERSION}-${HBASE_FLAVOR}-bin.tar.gz" \
-o /tmp/hbase.tar.gz; \
tar -xzf /tmp/hbase.tar.gz -C "${HBASE_HOME}" --strip-components=1; \
rm /tmp/hbase.tar.gz; \
mkdir -p /var/log/hbase /var/run/hbase

# phoenix-server JAR is copied into HBase's lib so the coprocessors and
# the IndexedWALEditCodec are visible to both the master and every RS.
RUN set -eux; \
mkdir -p "${PHOENIX_HOME}"; \
curl -fSL --retry 5 --retry-delay 5 \
"https://archive.apache.org/dist/phoenix/phoenix-${PHOENIX_VERSION}/phoenix-hbase-${PHOENIX_HBASE_LINE}-${PHOENIX_VERSION}-bin.tar.gz" \
-o /tmp/phoenix.tar.gz; \
tar -xzf /tmp/phoenix.tar.gz -C "${PHOENIX_HOME}" --strip-components=1; \
rm /tmp/phoenix.tar.gz; \
cp "${PHOENIX_HOME}/phoenix-server-hbase-${PHOENIX_HBASE_LINE}-${PHOENIX_VERSION}.jar" "${HBASE_HOME}/lib/"

# Kept below the tarball downloads to preserve their (multi-hundred-MB) cache.
# python3 is required by /opt/phoenix/bin/sqlline.py.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends python3; \
rm -rf /var/lib/apt/lists/*; \
ln -sf /usr/bin/python3 /usr/local/bin/python

COPY conf/hbase/hbase-site.xml ${HBASE_HOME}/conf/hbase-site.xml
COPY conf/hbase/hbase-env.sh ${HBASE_HOME}/conf/hbase-env.sh

COPY scripts/hbase-entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

WORKDIR /opt

ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
CMD ["help"]
97 changes: 97 additions & 0 deletions docker/Dockerfile.phoenix-adapters
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# syntax=docker/dockerfile:1
#
# Build context: project root (the Maven reactor needs every module).
#
FROM maven:3.9-eclipse-temurin-8 AS builder

WORKDIR /workspace

# Copy poms first to maximise dep-layer cache hits on rebuild.
COPY pom.xml ./
COPY phoenix-ddb-utils/pom.xml phoenix-ddb-utils/pom.xml
COPY phoenix-ddb-rest/pom.xml phoenix-ddb-rest/pom.xml
COPY phoenix-ddb-assembly/pom.xml phoenix-ddb-assembly/pom.xml
COPY coverage-report/pom.xml coverage-report/pom.xml

# `|| true` because the cross-module reactor can't resolve siblings yet;
# this step is only here to warm ~/.m2.
RUN --mount=type=cache,target=/root/.m2 \
mvn -B -q -DskipTests \
-pl phoenix-ddb-utils,phoenix-ddb-rest,phoenix-ddb-assembly -am \
dependency:go-offline || true

COPY phoenix-ddb-utils phoenix-ddb-utils
COPY phoenix-ddb-rest phoenix-ddb-rest
COPY phoenix-ddb-assembly phoenix-ddb-assembly
COPY coverage-report coverage-report
COPY bin bin
COPY conf conf
COPY README.md DDB_API_REFERENCE.md ./

RUN --mount=type=cache,target=/root/.m2 \
mvn -B -DskipTests \
-pl phoenix-ddb-assembly -am \
clean package

RUN set -eux; \
# If the assembly module ever ships an additional *-bin.tar.gz (e.g.
# with a classifier), fail loudly rather than silently picking one.
count=$(find phoenix-ddb-assembly/target -maxdepth 1 -type f -name 'phoenix-adapters-*-bin.tar.gz' | wc -l); \
if [ "$count" -ne 1 ]; then \
echo "Expected exactly one phoenix-adapters-*-bin.tar.gz, found $count:" >&2; \
find phoenix-ddb-assembly/target -maxdepth 1 -type f -name 'phoenix-adapters-*-bin.tar.gz' >&2; \
exit 1; \
fi; \
tarball=$(find phoenix-ddb-assembly/target -maxdepth 1 -type f -name 'phoenix-adapters-*-bin.tar.gz'); \
cp "$tarball" /tmp/phoenix-adapters-bin.tar.gz

FROM eclipse-temurin:8-jdk-jammy

ENV JAVA_HOME=/opt/java/openjdk \
PHOENIX_ADAPTERS_HOME=/opt/phoenix-adapters \
PHOENIX_ADAPTERS_CONF_DIR=/opt/phoenix-adapters/conf \
PHOENIX_ADAPTERS_LOG_DIR=/var/log/phoenix-adapters \
PHOENIX_ADAPTERS_PID_DIR=/var/run/phoenix-adapters \
PHOENIX_REST_PORT=8842 \
ZOO_KEEPER_QUORUM=zookeeper:2181 \
HBASE_MASTER_HOST=hbase-master \
HBASE_MASTER_PORT=16000

RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
bash curl ca-certificates netcat-openbsd tini procps; \
rm -rf /var/lib/apt/lists/*; \
mkdir -p "${PHOENIX_ADAPTERS_LOG_DIR}" "${PHOENIX_ADAPTERS_PID_DIR}"

COPY --from=builder /tmp/phoenix-adapters-bin.tar.gz /tmp/phoenix-adapters-bin.tar.gz

RUN set -eux; \
mkdir -p "${PHOENIX_ADAPTERS_HOME}"; \
tar -xzf /tmp/phoenix-adapters-bin.tar.gz -C "${PHOENIX_ADAPTERS_HOME}" --strip-components=1; \
rm /tmp/phoenix-adapters-bin.tar.gz; \
chmod -R +x "${PHOENIX_ADAPTERS_HOME}/bin"; \
# The assembly ships a mix of hadoop-common 3.3.6 (declared in pom.xml)
# and hadoop-hdfs/yarn/mapreduce 3.4.x (transitive from phoenix-core-client
# via hbase-server:2.5.14-hadoop3). The 3.4.x jars register FileSystem
# impls that reference `WithErasureCoding`, a class only present in
# hadoop-common 3.4.x. When HBase returns a remote exception during
# bootstrap, the client's classloader tries to enumerate FileSystem
# impls, hits NoClassDefFoundError, and poisons the JVM. The REST
# server only talks to HBase via RPC and never opens HDFS directly,
# so we strip the 3.4.x hadoop client jars to break the cycle.
rm -f "${PHOENIX_ADAPTERS_HOME}/lib/hadoop-hdfs-"*.jar \
"${PHOENIX_ADAPTERS_HOME}/lib/hadoop-hdfs-client-"*.jar \
"${PHOENIX_ADAPTERS_HOME}/lib/hadoop-yarn-"*.jar \
"${PHOENIX_ADAPTERS_HOME}/lib/hadoop-mapreduce-client-"*.jar \
"${PHOENIX_ADAPTERS_HOME}/lib/hadoop-distcp-"*.jar

# Client-side WAL codec / RPC controller must match the server cluster.
COPY docker/conf/phoenix-adapters/hbase-site.xml ${PHOENIX_ADAPTERS_CONF_DIR}/hbase-site.xml

COPY docker/scripts/phoenix-adapters-entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

EXPOSE 8842

ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
Loading
Loading