# Build Zammad with CDR Link addon # Based on Zammad's upstream Dockerfile with addon injection steps. # Zammad source is expected at .aidocs/zammad/ relative to the repo root. ARG RUBY_VERSION=3.4.8 ARG NODE_VERSION=22 # --- Base stage: runtime dependencies --- FROM docker.io/library/ruby:$RUBY_VERSION-slim-trixie AS base WORKDIR /opt/zammad ENV RAILS_ENV="production" \ BUNDLE_DEPLOYMENT="1" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="test development" \ RAILS_LOG_TO_STDOUT="true" RUN apt-get update -qq && \ apt-get install -y postgresql-common && \ /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \ apt-get install --no-install-recommends -y curl libimlib2 libpq5 nginx gnupg postgresql-client-17 && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # --- Node binary --- FROM node:${NODE_VERSION}-trixie-slim AS node RUN npm -g install corepack && corepack enable pnpm && \ rm /usr/local/bin/yarn /usr/local/bin/yarnpkg # --- Build stage --- FROM base AS build SHELL ["/bin/bash", "-o", "errexit", "-o", "pipefail", "-c"] RUN apt-get update -qq && \ apt-get install --no-install-recommends -y build-essential git libimlib2-dev libpq-dev libyaml-dev && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Install Ruby gems COPY .aidocs/zammad/Gemfile .aidocs/zammad/Gemfile.lock ./ COPY .aidocs/zammad/vendor/ vendor/ RUN bundle install && \ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git # Install Node.js COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules COPY --from=node /usr/local/bin /usr/local/bin # Install node modules COPY .aidocs/zammad/package.json .aidocs/zammad/pnpm-lock.yaml ./ COPY .aidocs/zammad/.eslint-plugin-zammad/ .eslint-plugin-zammad/ RUN pnpm install --frozen-lockfile # Copy Zammad source COPY .aidocs/zammad/ . # --- CDR Link Addon --- RUN mkdir -p contrib/link/addons COPY docker/zammad/addons/ contrib/link/addons/ COPY docker/zammad/setup.rb contrib/link/setup.rb COPY docker/zammad/install.rb contrib/link/install.rb RUN ruby contrib/link/install.rb # OpenSearch compatibility: 'flattened' -> 'flat_object' RUN sed -i "s/'flattened'/'flat_object'/g" lib/search_index_backend.rb # Build version info ARG COMMIT_SHA="" RUN COMMIT_SHA="${COMMIT_SHA:-$(git rev-parse HEAD 2>/dev/null || echo unknown)}"; \ COMMIT_SHA_SHORT=$(echo "${COMMIT_SHA}" | cut -c 1-8); \ echo "$(tr -d '\n' < VERSION)-${COMMIT_SHA_SHORT}.docker" > VERSION; \ cat VERSION # Precompile all assets (Vite + Sprockets, including addon Vue/CoffeeScript) RUN touch db/schema.rb && \ ZAMMAD_SAFE_MODE=1 DATABASE_URL=postgresql://zammad:/zammad bundle exec rake assets:precompile RUN script/build/cleanup.sh # Precompile bootsnap for faster boot times RUN bundle exec bootsnap precompile --gemfile app/ lib/ # Inject addon registration into the entrypoint (runs during zammad-init) RUN sed -i '/^[[:space:]]*# es config/a\ echo "Installing addon packages..."\n\ bundle exec rails runner /opt/zammad/contrib/link/setup.rb\n\ bundle exec rake zammad:package:migrate\n\ ' bin/docker-entrypoint # Nginx embedded mode: add /link proxy location ARG EMBEDDED=false ARG LINK_HOST=http://link:3000 RUN if [ "$EMBEDDED" = "true" ] ; then \ sed -i '$ d' contrib/nginx/zammad.conf && \ echo "" >> contrib/nginx/zammad.conf && \ echo " location /link {" >> contrib/nginx/zammad.conf && \ echo " set \$link_url ${LINK_HOST}; proxy_pass \$link_url;" >> contrib/nginx/zammad.conf && \ echo " proxy_set_header Host \$host;" >> contrib/nginx/zammad.conf && \ echo " proxy_set_header X-Real-IP \$remote_addr;" >> contrib/nginx/zammad.conf && \ echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;" >> contrib/nginx/zammad.conf && \ echo " proxy_set_header X-Forwarded-Proto https;" >> contrib/nginx/zammad.conf && \ echo " }" >> contrib/nginx/zammad.conf && \ echo "}" >> contrib/nginx/zammad.conf; \ fi # --- Final stage --- FROM base RUN apt-get update -qq && \ apt-get upgrade -y && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives ENV POSTGRESQL_DB=zammad_production \ POSTGRESQL_HOST=postgresql \ POSTGRESQL_PORT=5432 \ POSTGRESQL_USER=zammad \ POSTGRESQL_PASS=zammad \ POSTGRESQL_OPTIONS=?pool=50 \ RAILS_TRUSTED_PROXIES=127.0.0.1,::1 RUN groupadd --system --gid 1000 zammad && \ useradd --create-home --home /opt/zammad --shell /bin/bash --uid 1000 --gid 1000 zammad RUN sed -i -e "s#user www-data;##g" \ -e 's#/var/log/nginx/\(access\|error\).log#/dev/stdout#g' \ -e 's#pid /run/nginx.pid;#pid /tmp/nginx.pid;#g' /etc/nginx/nginx.conf && \ mkdir -p /opt/zammad /var/log/nginx RUN mkdir -p "/opt/zammad/storage" "/opt/zammad/tmp" && \ chown -R 1000:1000 /etc/nginx /var/lib/nginx /var/log/nginx /opt/zammad COPY --chown=1000:1000 --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" COPY --chown=1000:1000 --from=build /opt/zammad /opt/zammad # Backwards compatibility RUN ln -s "/opt/zammad/bin/docker-entrypoint" /docker-entrypoint.sh USER 1000:1000 ENTRYPOINT ["/opt/zammad/bin/docker-entrypoint"] LABEL io.portainer.commands.rails-console="bundle exec rails c"