apachedocker-composewebsocketreverse-proxyapache2.4

TeamCity server WebSocket connection error in Docker image behind Apache proxy


I am running TeamCity server behind Apache proxy. My Apache configuration of virtual host teamcity.example.com.

HTTP:

<VirtualHost *:80> 
    ServerName teamcity.example.com
    ServerAlias www.teamcity.example.com
    Redirect / https://teamcity.example.com/
</VirtualHost>

HTTPS:

<IfModule mod_ssl.c>
<VirtualHost *:443> 
 
    ProxyPreserveHost On

    ProxyPreserveHost On
    ProxyRequests Off
    ServerName www.teamcity.example.com
    ServerAlias teamcity.example.com

    ProxyPass / http://localhost:8111/
    ProxyPassReverse / http://localhost:8111/

    # This doesn't work 
    ProxyPass           /app/subscriptions ws://localhost:8111/app/subscriptions connectiontimeout=240 timeout=1200
    ProxyPassReverse    /app/subscriptions ws://localhost:8111/app/subscriptions

    # This doesn't work         
    ProxyPass           / http://localhost:8111/ connectiontimeout=5 timeout=300
    ProxyPassReverse    / http://localhost:8111/

    SSLCertificateFile /etc/letsencrypt/live/teamcity.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/teamcity.example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

</VirtualHost>
</IfModule>

Apache modules are enabled:

sudo apachectl -M | grep proxy
 proxy_module (shared)
 proxy_http_module (shared)
 proxy_wstunnel_module (shared)

And my docker-compose.yaml

version: "3.5"
services:
  server:
    image: jetbrains/teamcity-server:latest
    container_name: teamcity_server
    networks:
      - teamcity_network
    ports:
      - "8111:8111"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - datadir:/data/teamcity_server/datadir
      - logs:/opt/teamcity/logs
    environment:
      - TEAMCITY_HTTPS_PROXY_ENABLED=true
  agent:
    image: jetbrains/teamcity-agent:2022.10.1-linux-sudo 
    container_name: teamcity_agent
    volumes:
      - agent_conf:/data/teamcity_agent/conf
    environment:
      - SERVER_URL=https://teamcity.example.com
networks:
  teamcity_network:
volumes:
  datadir:
  logs:
  agent_conf: 

TeamCity user interface reports WebSocket connection error:

WebSocket connection issues Some users cannot use optimized web UI updates via WebSocket protocol. The following addresses were used by the affected sessions: https://teamcity.example.com Most probably there is not appropriately configured proxy server between the client browsers and the TeamCity server.

And DeveloperTool console in Chrome:

WebSocket connection to 'wss://teamcity.example.com/app/subscriptions?browserLocationHost=https%3A%2F%2Fteamcity.example.com' failed: openSocket @ 6942286895631677648.js?v=1671191552738:648 open @ 6942286895631677648.js?v=1671191552738:742 start @ 6942286895631677648.js?v=1671191552738:907 (anonymous) @ projects?mode=builds:391

Q: What is wrong with Docker image or Apache configuration?


Solution

  • The solution is to place ProxyPass and ProxyPassReverse directives in proper order. This configuration works as expected.

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
    
            ProxyPreserveHost On
            ProxyRequests Off
    
            ServerName www.teamcity.example.com
            ServerAlias teamcity.example.com
    
            ProxyPass           /app/subscriptions ws://localhost:8111/app/subscriptions connectiontimeout=240 timeout=1200
            ProxyPassReverse    /app/subscriptions ws://localhost:8111/app/subscriptions
    
            ProxyPass               / http://localhost:8111/ connectiontimeout=5 timeout=300
            ProxyPassReverse        / http://localhost:8111/
    
            SSLCertificateFile /etc/letsencrypt/live/teamcity.example.com/fullchain.pem
            SSLCertificateKeyFile /etc/letsencrypt/live/teamcity.example.com/privkey.pem
            Include /etc/letsencrypt/options-ssl-apache.conf
    
    </VirtualHost>
    </IfModule>