Dockerfile-api
Rama master · réplica de lectura del repositorio original.
# node:26-trixie-slim -- Node.js 26 (LTS) on Debian trixie-slim.
# Multi-arch manifest list digest, resolved 2026-10-27.
FROM node:26-trixie-slim@sha256:36793bcbb160a6a16cede1e62b93f84e26b78a972a8a4c0b879c1c12f22761ec AS builder-base
ENV NODE_OPTIONS="--max-old-space-size=2048"
# Build dependencies live only in build stages and are never shipped
RUN apt-get update && \
apt-get install -y curl wget git make gcc g++ unzip xz-utils build-essential sudo \
python3 python3-setuptools zlib1g-dev libssl-dev libncurses-dev libgdbm-dev libnss3-dev libsqlite3-dev \
libreadline-dev libffi-dev libbz2-dev ca-certificates
# Python 3.12 from source for the ab-testing cmdstanpy models.
# pip>=26.2.2 and certifi>=2026.10.19 drop the distrusted emSign roots.
RUN cd /usr/src && \
wget -q https://www.python.org/ftp/python/3.12.15/Python-3.12.15.tar.xz && \
tar -xf Python-3.12.15.tar.xz && \
cd Python-3.12.15 && \
./configure --enable-optimizations --enable-shared && \
make -j"$(nproc)" && \
make altinstall && \
ldconfig && \
python3.12 -c "import ssl" && \
python3.12 -m pip install --no-cache-dir --upgrade "pip>=26.2.2" "certifi>=2026.10.19" setuptools wheel && \
rm -rf /usr/src/Python*
FROM builder-base AS ab-models
ARG COUNTLY_PLUGINS=mobile,web,desktop,plugins,density,locale,browser,sources,views,logger,systemlogs,populator,reports,crashes,push,star-rating,slipping-away-users,compare,server-stats,dbviewer,times-of-day,compliance-hub,alerts,onboarding,consolidate,remote-config,hooks,dashboards,sdk,data-manager,guides
# CmdStan pinned to the release cmdstanpy 1.2.5 was fixed against
ARG CMDSTAN_VERSION=2.36.0
ENV CMDSTAN=/opt/cmdstan/cmdstan-${CMDSTAN_VERSION}
WORKDIR /opt/countly
# ab-testing is EE-only. Bracketing every separator makes the path one glob, so
# these COPYs resolve to nothing instead of failing in a CE-only build context.
COPY plugins[/]ab-testing[/]api[/]bayesian[/]requirements_docker.txt ./plugins/ab-testing/api/bayesian/
# Install the python stack only when the ab-testing plugin is enabled
RUN set -eux; \
echo "$COUNTLY_PLUGINS" | tr ',' '\n' | grep -qx ab-testing \
|| { mkdir -p plugins/ab-testing/api/bayesian; touch plugins/ab-testing/api/bayesian/.ab_disabled; exit 0; }; \
python3.12 -m pip install --no-cache-dir -r plugins/ab-testing/api/bayesian/requirements_docker.txt
COPY plugins[/]ab-testing[/]api[/]bayesian[/]*.py ./plugins/ab-testing/api/bayesian/
COPY plugins[/]ab-testing[/]api[/]bayesian[/]models[/]*.py ./plugins/ab-testing/api/bayesian/models/
COPY plugins[/]ab-testing[/]api[/]bayesian[/]models[/]stan_models[/]*.stan ./plugins/ab-testing/api/bayesian/models/stan_models/
# Install CmdStan and compile the seven variant models
RUN set -eux; \
if [ -f plugins/ab-testing/api/bayesian/.ab_disabled ]; then exit 0; fi; \
CMDSTAN= CMDSTAN_VERSION="${CMDSTAN_VERSION}" CMDSTAN_DIR=/opt/cmdstan CMDSTAN_BUILD_CORES="$(nproc)" \
python3.12 plugins/ab-testing/api/bayesian/models/cmdstanpy_model.py; \
for i in 2 3 4 5 6 7 8; do test -x "plugins/ab-testing/api/bayesian/models/stan_models/model_${i}_variants"; done
# Prune CmdStan to the runtime minimum, preserving RPATH-relative layout
RUN set -eux; \
D="/opt/cmdstan-min/cmdstan-${CMDSTAN_VERSION}"; mkdir -p "$D/bin"; \
if [ ! -d "$CMDSTAN" ]; then exit 0; fi; \
cp "$CMDSTAN/bin/stansummary" "$CMDSTAN/bin/diagnose" "$CMDSTAN/bin/stanc" "$D/bin/"; \
cp "$CMDSTAN/makefile" "$D/makefile"; \
find "$CMDSTAN/stan/lib/stan_math/lib" -name 'libtbb*.so*' -print | while read -r lib; do \
rel="${lib#"$CMDSTAN"/}"; mkdir -p "$D/$(dirname "$rel")"; cp -a "$lib" "$D/$rel"; done; \
find "$D" -name 'libtbb*.so*' | grep -q .
FROM builder-base AS builder
ARG COUNTLY_PLUGINS=mobile,web,desktop,plugins,density,locale,browser,sources,views,logger,systemlogs,populator,reports,crashes,push,star-rating,slipping-away-users,compare,server-stats,dbviewer,times-of-day,compliance-hub,alerts,onboarding,consolidate,remote-config,hooks,dashboards,sdk,data-manager,guides
# Countly Enterprise:
#ARG COUNTLY_PLUGINS=mobile,web,desktop,plugins,density,locale,browser,sources,views,license,drill,funnels,retention_segments,flows,cohorts,surveys,remote-config,ab-testing,formulas,activity-map,concurrent_users,revenue,logger,systemlogs,populator,reports,crashes,push,geo,block,users,star-rating,slipping-away-users,compare,server-stats,dbviewer,crash_symbolication,crashes-jira,groups,white-labeling,alerts,times-of-day,compliance-hub,onboarding,active_users,performance-monitoring,config-transfer,consolidate,data-manager,hooks,dashboards,heatmaps,sdk,guides,journey_engine,content
ARG GEOIP=empty
ARG TARGETARCH
ENV COUNTLY_CONTAINER="api" \
COUNTLY_DEFAULT_PLUGINS="${COUNTLY_PLUGINS}" \
npm_config_allow_git=root \
npm_config_dangerously_allow_all_scripts=true \
PUPPETEER_CACHE_DIR=/opt/countly/.cache/puppeteer
WORKDIR /opt/countly
COPY . .
COPY --from=ab-models /opt/countly/plugins/ab-testing/api/bayesian ./plugins/ab-testing/api/bayesian
# Chrome for Testing has no Linux arm64 build, so arm64 skips Puppeteer's download
# and uses Debian's chromium from the runtime stage (see bin/docker/cmd.sh)
RUN if [ "$TARGETARCH" = "arm64" ]; then export PUPPETEER_SKIP_DOWNLOAD=true; fi && \
./bin/docker/modify.sh && \
cp -n ./api/config.sample.js ./api/config.js && \
cp -n ./frontend/express/config.sample.js ./frontend/express/config.js && \
HOME=/tmp npm install -g npm@11.19.0 && \
HOME=/tmp npm install && \
HOME=/tmp npm_config_build_from_source=true npm install argon2 && \
./bin/docker/preinstall.sh && \
bash /opt/countly/bin/scripts/detect.init.sh && \
npm remove -y --no-save mocha should supertest && \
# CE builds carry only a stub ab-testing dir from the ab-models COPY; drop it
{ [ -f plugins/ab-testing/package.json ] || rm -rf plugins/ab-testing; } && \
rm -rf test /tmp/* /var/tmp/* /root/.npm && \
chown -R 1001:0 /opt/countly && \
chmod -R g=u /opt/countly
FROM node:26-trixie-slim@sha256:36793bcbb160a6a16cede1e62b93f84e26b78a972a8a4c0b879c1c12f22761ec AS runtime
ARG COUNTLY_PLUGINS=mobile,web,desktop,plugins,density,locale,browser,sources,views,logger,systemlogs,populator,reports,crashes,push,star-rating,slipping-away-users,compare,server-stats,dbviewer,times-of-day,compliance-hub,alerts,onboarding,consolidate,remote-config,hooks,dashboards,sdk,data-manager,guides
ARG CMDSTAN_VERSION=2.36.0
ARG TARGETARCH
EXPOSE 3001
HEALTHCHECK --start-period=400s CMD bash -c '\
if [ "$COUNTLY_CONFIG_API_API_SSL_ENABLED" = "true" ] || [ "$COUNTLY_CONFIG_API_API_SSL_ENABLED" = "\"true\"" ]; then \
curl -k --fail https://localhost:3001/o/ping || exit 1; \
else \
curl --fail http://localhost:3001/o/ping || exit 1; \
fi'
ENV COUNTLY_CONTAINER="api" \
COUNTLY_DEFAULT_PLUGINS="${COUNTLY_PLUGINS}" \
COUNTLY_CONFIG_API_API_WORKERS="1" \
COUNTLY_CONFIG_API_API_HOST="0.0.0.0" \
NODE_OPTIONS="--max-old-space-size=2048 --no-node-snapshot" \
HOME=/tmp \
CMDSTAN=/opt/cmdstan/cmdstan-${CMDSTAN_VERSION} \
PUPPETEER_CACHE_DIR=/opt/countly/.cache/puppeteer
# Runtime-only packages: init, ops tools, Chrome and Python shared libs
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
tini curl procps iputils-ping net-tools ca-certificates \
sudo telnet xz-utils apt-transport-https lsb-release \
libffi8 libbz2-1.0 liblzma5 libsqlite3-0 libreadline8 libncursesw6 \
libgbm1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcairo2 libcups2 \
libdbus-1-3 libexpat1 libfontconfig1 libgdk-pixbuf-2.0-0 libglib2.0-0 \
libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 \
libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 \
libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
fonts-liberation xdg-utils && \
if [ "$TARGETARCH" = "arm64" ]; then apt-get install -y --no-install-recommends chromium; fi && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
echo "Etc/UTC" > /etc/timezone
WORKDIR /opt/countly
# ab-models /usr/local carries python 3.12 + cmdstanpy stack; builder adds npm@11
COPY --from=ab-models /usr/local /usr/local
COPY --from=builder /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=ab-models /opt/cmdstan-min /opt/cmdstan
COPY --from=builder /opt/countly /opt/countly
RUN ldconfig && \
ln -sf /usr/local/bin/python3.12 /usr/bin/python3 && \
ln -sf /opt/countly/bin/commands/countly.sh /usr/bin/countly && \
chown 1001:0 /opt/countly && chmod g=u /opt/countly && \
mkdir -p /.npm && chown -R 1001:0 /.npm && chmod -R g=u /.npm
USER 1001:0
ENTRYPOINT ["/usr/bin/tini", "-v", "--"]
CMD ["/opt/countly/bin/docker/cmd.sh"]