getsentry / self-hosted

Sentry, feature-complete and packaged up for low-volume deployments and proofs-of-concept
https://develop.sentry.dev/self-hosted/
Other
7.76k stars 1.75k forks source link

Using external network for proxy #1555

Open misterx opened 2 years ago

misterx commented 2 years ago

Problem Statement

I have faced the issue when trying to use sentry behind nginx proxy. Here is part of nginx service configuration in docker-compose.yml:

services:
  nginx:
    <<: *restart_policy
#    ports:
#      - "$SENTRY_BIND:80/tcp"
    image: "nginx:1.22.0-alpine"

    volumes:
      - type: bind
        read_only: true
        source: ./nginx
        target: /etc/nginx
      - sentry-nginx-cache:/var/cache/nginx

    depends_on:
      - web
      - relay

    environment:
        - VIRTUAL_HOST=sentry.local

    networks:
        - default
        - frontend
networks:
  frontend:
    name: nginxproxy
    external: true

When I try to open Sentry from browser, I've got error: failed (111: Connection refused) while connecting to upstream ... in sentry nginx log. The same problem was reported in issue #482.

Solution Brainstorm

I've discovered that error appears when you have the service which named web in your external network and docker dns resolve incorrect ip for nginx upstream (returns ip for web from external network instead of internal). Would be better if web service will be renamed into something unique, like sentry_web (since service web is fairly common in many projects).

ethanhs commented 2 years ago

I think this does make sense, however I am surprised docker doesn't use internal DNS over external DNS...

We should probably audit all the references to web and make sure we include those when updating this name.

aminvakil commented 2 years ago

I think OP's question is very specific to their environment, it should work if the DNS server does not return an IP for web right?

misterx commented 2 years ago

@aminvakil Question is realted to docker internal dns. I've created some sandbox for that.

#front/docker-compose.yml
version: "3.7"

services:
    web:
        image: alpine
        command: >
            sh -c ' 
                echo my IP is: &&
                hostname -i &&
                sleep infinite
            '
        networks:
            proxy_network:
networks:
    proxy_network:
        external: true
#sentry/docker-compose.yml
version: "3.7"

services:
    web:
        image: alpine
        command: sleep infinite
        networks:
            internal:
    nginx:
        image: alpine
        command: > 
            sh -c ' 
            echo web IP is: &&
            ping -q -c 1 -t 1 web | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"
            '
        depends_on:
            -   web
        networks:
            internal:
            proxy_network:
networks:
    internal:
    proxy_network:
        external: true
> docker network create proxy_network
> docker-compose -f ./sentry/docker-compose.yml run nginx
web IP is:
172.22.0.2
> docker-compose -f ./front/docker-compose.yml up -d
> docker-compose -f ./sentry/docker-compose.yml run nginx
web IP is:
172.19.0.2

As you can see, when new web service appears in the external network, it has a higher priority than internal web service. So in the last case nginx will connect to wrong upstream,

aminvakil commented 2 years ago

Aha, thanks for clarification!

What's the reason behind not changing your external docker-compose name? I suppose If you choose a different name than web, problem is solved then, correct?

Herz3h commented 1 year ago

So is there a workaround for this ? I'm facing the same issue except I'm using Traefik as a reverse proxy.

It turns out, with Traefik I'm creating a docker network, where both PostHog and Sentry are connected and both have a service named web. Since it's they are both on same external network there is a conflict when sentry nginx tries to communicate with web service, it resolves ip of PostHog.

Workaround: I renamed every reference to web in the folder I cloned to web2 and it works fine now. But would be better if you changed the name from web to something more specific by default

EDIT: Never mind it seems like the web service name is hardcoded into the relay.....