Dockerized Web Server Not Reflecting Code Changes Despite Sync Confirmation using Docker compose watch

I am working on a Dockerized development environment for a project that involves multiple services defined in docker-compose.dev.yml. The web_server service builds successfully, and any code changes are synced within the container, as verified through docker exec. However, these changes are not reflected on the live site. I’ve noticed that in the Dockerfile configuration for the web_server, the frontend code may be pushed to the production stage during the build process. This setup could lead to the application running in a production environment inside the container, which typically doesn’t support hot reloading by default. This configuration could be the reason why changes are synced but not reflected on the live site, as hot reloading is usually only available in a development stage. When I use the rebuild option (sudo docker compose -f docker-compose.dev.yml -p danswer-stack up -d --build --force-recreate), the changes are reflected on the live site as expected. However, when I rely on the sync action configured in the docker-compose develop section, the code changes are synced to the container (verified via docker exec), but these changes do not appear on the live site. Please someone help me on this as I’m technically new to this would really appreciate it…

What I’ve Tried:

  1. Ensured the code changes are present within the container.
  2. Restarted the web_server container to force updates.
  3. Checked for caching issues by running the site in an incognito window.
  4. Verified that the service is set to development mode (NODE_ENV=development).
  5. Rebuilt the container with --no-cache and --force-recreate.
  6. Inspected logs for errors using docker logs, but found none that indicate an issue.
  7. Confirmed that my development server (e.g., Next.js) supports hot reloading.
  • Docker Compose File: Contains web_server, api_server, and other dependent services as mentioned in the original docker-compose.dev.yml in this path cd danswer/deployment/docker_compose.

Has anyone encountered a similar issue where changes are synced inside the container but do not reflect on the live site? Any advice on further troubleshooting steps or potential misconfigurations that might cause this would be appreciated.

  • web_server service with action set to rebuild working state:
  web_server:
    image: danswer/danswer-web-server:${IMAGE_TAG:-latest}
    build:
      context: ../../web
      dockerfile: Dockerfile
      args:
        - NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
        - NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA=${NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA:-false}
        - NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
        - NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
        - NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
        - NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN=${NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN:-}

        # Enterprise Edition only
        - NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
        # DO NOT TURN ON unless you have EXPLICIT PERMISSION from Danswer.
        - NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
    depends_on:
      - api_server
    restart: always
    environment:
      - INTERNAL_URL=http://api_server:8080
      - WEB_DOMAIN=${WEB_DOMAIN:-}
      - THEME_IS_DARK=${THEME_IS_DARK:-}
      - DISABLE_LLM_DOC_RELEVANCE=${DISABLE_LLM_DOC_RELEVANCE:-}

      # Enterprise Edition only
      - ENABLE_PAID_ENTERPRISE_EDITION_FEATURES=${ENABLE_PAID_ENTERPRISE_EDITION_FEATURES:-true}
      - NEXT_PUBLIC_CUSTOM_REFRESH_URL=${NEXT_PUBLIC_CUSTOM_REFRESH_URL:-}
    develop:
      watch:
        - action: rebuild
          path: ../../web
          ignore:
            - node_modules/
  • web_server service with action set to sync working condition but live changes cant be reflected:
  web_server:
    image: danswer/danswer-web-server:${IMAGE_TAG:-latest}
    build:
      context: ../../web
      dockerfile: Dockerfile
      args:
        - NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
        - NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA=${NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA:-false}
        - NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
        - NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS:-}
        - NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
        - NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN=${NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN:-}

        # Enterprise Edition only
        - NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
        # DO NOT TURN ON unless you have EXPLICIT PERMISSION from Danswer.
        - NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
    depends_on:
      - api_server
    restart: always
    environment:
      - INTERNAL_URL=http://api_server:8080
      - WEB_DOMAIN=${WEB_DOMAIN:-}
      - THEME_IS_DARK=${THEME_IS_DARK:-}
      - DISABLE_LLM_DOC_RELEVANCE=${DISABLE_LLM_DOC_RELEVANCE:-}

      # Enterprise Edition only
      - ENABLE_PAID_ENTERPRISE_EDITION_FEATURES=${ENABLE_PAID_ENTERPRISE_EDITION_FEATURES:-true}
      - NEXT_PUBLIC_CUSTOM_REFRESH_URL=${NEXT_PUBLIC_CUSTOM_REFRESH_URL:-}
      - NODE_ENV=development
    develop:
      watch:
        - action: sync
          path: ../../web
          target: /app
          ignore:
            - node_modules/
        - action: rebuild
          path: ../../web/package.json
  • Dockerfile within the web dir as same as in danswer github:
FROM node:20-alpine AS base

LABEL com.danswer.maintainer="founders@danswer.ai"
LABEL com.danswer.description="This image is the web/frontend container of Danswer which \
    contains code for both the Community and Enterprise editions of Danswer. If you do not \
    have a contract or agreement with DanswerAI, you are not permitted to use the Enterprise \
    Edition features outside of personal development or testing purposes. Please reach out to \
    founders@danswer.ai for more information. Please visit https://github.com/danswer-ai/danswer"

# Default DANSWER_VERSION, typically overriden during builds by GitHub Actions.
ARG DANSWER_VERSION=0.3-dev
ENV DANSWER_VERSION=${DANSWER_VERSION}
RUN echo "DANSWER_VERSION: ${DANSWER_VERSION}"

# Step 1. Install dependencies + rebuild the source code only when needed
FROM base AS builder
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# pull in source code / package.json / package-lock.json
COPY . .

# Install dependencies
RUN npm ci

# needed to get the `standalone` dir we expect later
ENV NEXT_PRIVATE_STANDALONE true

# Disable automatic telemetry collection
ENV NEXT_TELEMETRY_DISABLED 1

# Environment variables must be present at build time
# https://github.com/vercel/next.js/discussions/14030
# NOTE: if you add something here, make sure to add it to the runner as well
ARG NEXT_PUBLIC_DISABLE_STREAMING
ENV NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING}

ARG NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA
ENV NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA=${NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA}

# allow user to specify custom feedback options
ARG NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS
ENV NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS}

ARG NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS
ENV NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS}

ARG NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN
ENV NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN=${NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN}

ARG NEXT_PUBLIC_THEME
ENV NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME}

ARG NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED
ENV NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED}

ARG NEXT_PUBLIC_DISABLE_LOGOUT
ENV NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT}

RUN npx next build

# Step 2. Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

# Remove global node modules, since they are not needed by the actual app
# (all dependencies are copied over into the `/app` dir itself). These
# global modules may be outdated and trigger security scans.
RUN rm -rf /usr/local/lib/node_modules

# Not needed, set by compose 
# ENV NODE_ENV production  

# Disable automatic telemetry collection
ENV NEXT_TELEMETRY_DISABLED 1

# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs

# Add back in if we add anything to `public`
COPY --from=builder /app/public ./public

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

# Environment variables must be redefined at run time
# NOTE: if you add something here, make sure to add it to the builder as well
ARG NEXT_PUBLIC_DISABLE_STREAMING
ENV NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING}

ARG NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA
ENV NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA=${NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA}

# allow user to specify custom feedback options
ARG NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS
ENV NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_POSITIVE_PREDEFINED_FEEDBACK_OPTIONS}

ARG NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS
ENV NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS=${NEXT_PUBLIC_NEGATIVE_PREDEFINED_FEEDBACK_OPTIONS}

ARG NEXT_PUBLIC_THEME
ENV NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME}

ARG NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED
ENV NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED}

ARG NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN
ENV NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN=${NEXT_PUBLIC_DEFAULT_SIDEBAR_OPEN}

ARG NEXT_PUBLIC_DISABLE_LOGOUT
ENV NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT}

# Note: Don't expose ports here, Compose will handle that for us if necessary. 
# If you want to run this without compose, specify the ports to 
# expose via cli

CMD ["node", "server.js"]

Any help would be really appreciated :,)

I’m trying to use Docker Compose’s watch feature with the sync action to achieve hot reloading in my development setup. The goal is to see code changes reflected on the live site instantly without needing a full rebuild each time. While syncing does work (verified by checking inside the container), the changes do not appear on the live site unless I perform a full sudo docker compose -f docker-compose.dev.yml -p danswer-stack up -d --build --force-recreate. I want to configure docker-compose.dev.yml so that I can see modifications on the site in real-time using the watch sync feature without manual rebuilding in development mode.

  • In the attached code, you can see that I’ve set the action to rebuild, which typically takes around 275 seconds, sometimes up to 300 seconds. This timing was manageable now, earlier as the application grew, the rebuild duration increased to over 1000+ seconds. To address this, I applied Docker Compose’s new watch feature with the action set to sync to avoid lengthy rebuilds. However, despite using sync, hot reloading is not functioning as expected, even after multiple refresh attempts.

Forgive me if I missed something as I see many messages to which I’m trying to reply and it is already late, but I see you state that the syncing feature works in development when hot reloading is enabled and this is what this feature is for. So I don’t understand what the problem is with the production environment. If there is nothing to reload the code in the container, you will always need to rebuild the image.