Доступ к контейнерному API, размещенному на цифровой капле океана, с удаленного компьютера

Я пытаюсь подключиться к развернутому стеку служб для создания докеров в капле DigitalOcean Docker. Он содержит контейнер MySQL с базой данных и контейнер go / alpine с API. Я использую настраиваемую мостовую сеть, к которой подключаются 2 контейнера. Проблема также возникла при попытке развернуть стек локально на моем Mac и получить доступ к контейнеру API через localhost: port. Я не использую докер-машину, так как предполагаю, что она нужна только для развертывания с несколькими хостами. Стек успешно развернут. Контейнер сервера, похоже, может подключиться к контейнеру БД. Мне интересно, может ли проблема быть в правилах брандмауэра хоста?

Я попытался запустить приложение локально с сервером mysql, работающим на моем компьютере, и оно действительно работает, поэтому я не думаю, что причина в неисправном коде. Мне не удалось заставить его работать ни с базовым HTTP-сервером, ни с https с самозаверяющими сертификатами (оба работают на моем локальном компьютере).

docker-compose.yml

version: "3.7"

networks:
  net:
    attachable: true

services:
  db:
    build: ./db
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ENV=local
    networks:
      - net
  server:
    build: ./server
    ports:
      - "80:5000"
      - "443:5001"
    networks:
      - net
    tty: true
    links:
      - db:db

iptables -L с развернутым стеком:

Chain INPUT (policy DROP)
target     prot opt source               destination         
ufw-before-logging-input  all  --  anywhere             anywhere            
ufw-before-input  all  --  anywhere             anywhere            
ufw-after-input  all  --  anywhere             anywhere            
ufw-after-logging-input  all  --  anywhere             anywhere            
ufw-reject-input  all  --  anywhere             anywhere            
ufw-track-input  all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ufw-before-logging-forward  all  --  anywhere             anywhere            
ufw-before-forward  all  --  anywhere             anywhere            
ufw-after-forward  all  --  anywhere             anywhere            
ufw-after-logging-forward  all  --  anywhere             anywhere            
ufw-reject-forward  all  --  anywhere             anywhere            
ufw-track-forward  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ufw-before-logging-output  all  --  anywhere             anywhere            
ufw-before-output  all  --  anywhere             anywhere            
ufw-after-output  all  --  anywhere             anywhere            
ufw-after-logging-output  all  --  anywhere             anywhere            
ufw-reject-output  all  --  anywhere             anywhere            
ufw-track-output  all  --  anywhere             anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.24.0.2           tcp dpt:mysql
ACCEPT     tcp  --  anywhere             172.24.0.3           tcp dpt:5001
ACCEPT     tcp  --  anywhere             172.24.0.3           tcp dpt:5000

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

Chain ufw-after-forward (1 references)
target     prot opt source               destination         

Chain ufw-after-input (1 references)
target     prot opt source               destination         
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:netbios-ns
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:netbios-dgm
ufw-skip-to-policy-input  tcp  --  anywhere             anywhere             tcp dpt:netbios-ssn
ufw-skip-to-policy-input  tcp  --  anywhere             anywhere             tcp dpt:microsoft-ds
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:bootps
ufw-skip-to-policy-input  udp  --  anywhere             anywhere             udp dpt:bootpc
ufw-skip-to-policy-input  all  --  anywhere             anywhere             ADDRTYPE match dst-type BROADCAST

Chain ufw-after-logging-forward (1 references)
target     prot opt source               destination         

Chain ufw-after-logging-input (1 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

Chain ufw-after-logging-output (1 references)
target     prot opt source               destination         

Chain ufw-after-output (1 references)
target     prot opt source               destination         

Chain ufw-before-forward (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere             icmp destination-unreachable
ACCEPT     icmp --  anywhere             anywhere             icmp time-exceeded
ACCEPT     icmp --  anywhere             anywhere             icmp parameter-problem
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
ufw-user-forward  all  --  anywhere             anywhere            

Chain ufw-before-input (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ufw-logging-deny  all  --  anywhere             anywhere             ctstate INVALID
DROP       all  --  anywhere             anywhere             ctstate INVALID
ACCEPT     icmp --  anywhere             anywhere             icmp destination-unreachable
ACCEPT     icmp --  anywhere             anywhere             icmp time-exceeded
ACCEPT     icmp --  anywhere             anywhere             icmp parameter-problem
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
ACCEPT     udp  --  anywhere             anywhere             udp spt:bootps dpt:bootpc
ufw-not-local  all  --  anywhere             anywhere            
ACCEPT     udp  --  anywhere             224.0.0.251          udp dpt:mdns
ACCEPT     udp  --  anywhere             239.255.255.250      udp dpt:1900
ufw-user-input  all  --  anywhere             anywhere            

Chain ufw-before-logging-forward (1 references)
target     prot opt source               destination         

Chain ufw-before-logging-input (1 references)
target     prot opt source               destination         

Chain ufw-before-logging-output (1 references)
target     prot opt source               destination         

Chain ufw-before-output (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ufw-user-output  all  --  anywhere             anywhere            

Chain ufw-logging-allow (0 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW ALLOW] "

Chain ufw-logging-deny (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             ctstate INVALID limit: avg 3/min burst 10
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

Chain ufw-not-local (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type MULTICAST
RETURN     all  --  anywhere             anywhere             ADDRTYPE match dst-type BROADCAST
ufw-logging-deny  all  --  anywhere             anywhere             limit: avg 3/min burst 10
DROP       all  --  anywhere             anywhere            

Chain ufw-reject-forward (1 references)
target     prot opt source               destination         

Chain ufw-reject-input (1 references)
target     prot opt source               destination         

Chain ufw-reject-output (1 references)
target     prot opt source               destination         

Chain ufw-skip-to-policy-forward (0 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain ufw-skip-to-policy-input (7 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            

Chain ufw-skip-to-policy-output (0 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain ufw-track-forward (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             ctstate NEW
ACCEPT     udp  --  anywhere             anywhere             ctstate NEW

Chain ufw-track-input (1 references)
target     prot opt source               destination         

Chain ufw-track-output (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             ctstate NEW
ACCEPT     udp  --  anywhere             anywhere             ctstate NEW

Chain ufw-user-forward (1 references)
target     prot opt source               destination         

Chain ufw-user-input (1 references)
target     prot opt source               destination         
           tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
ufw-user-limit  tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW recent: UPDATE seconds: 30 hit_count: 6 name: DEFAULT side: source mask: 255.255.255.255
ufw-user-limit-accept  tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:2375
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:2376

Chain ufw-user-limit (1 references)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 5 LOG level warning prefix "[UFW LIMIT BLOCK] "
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain ufw-user-limit-accept (1 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            

Chain ufw-user-logging-forward (0 references)
target     prot opt source               destination         

Chain ufw-user-logging-input (0 references)
target     prot opt source               destination         

Chain ufw-user-logging-output (0 references)
target     prot opt source               destination         

Chain ufw-user-output (1 references)
target     prot opt source               destination 

ОБНОВЛЕНИЕ:

У меня есть 3 файла json с конфигурациями и учетными данными для разных сред, которые анализируются в объект конфигурации со следующим форматом (учетные данные заменены по очевидным причинам):

{
  "server": {
    "certificate": "<HTTPS_CERT>.pem",
    "key": "<HTTPS_KEY.pem",
    "ip": "127.0.0.1",
    "port": "5000",
    "protocol": "http://",
    "file_protocol": "bfile://"
  },
  "database": {
    "address": "db",
    "port": "3306",
    "name": "brieefly",
    "user": "<USERNAME>",
    "password": "<PASSWORD>"
  },
  "auth": {
    "public": "<JWT_AUTH_KEY>.rsa.pub",
    "private": "<JWT_AUTH_PRIV_KEY>.rsa"
  }
}

Затем конфигурация передается объекту db и объекту маршрутизатора:

db:

// connect to db - this succeeds

func Connect(config *config.Config) (*DB, *err.Error) {
    connectionString := fmt.Sprintf("%s:%s@(%s:%s)/%s?parseTime=true",
        config.Database.User,
        config.Database.Password,
        config.Database.Address,
        config.Database.Port,
        config.Database.Name)
    log.Debug(connectionString)
    db, sqlErr := sql.Open("mysql", connectionString)
    if sqlErr != nil {
        return nil, err.New(sqlErr, err.ErrConnectionFailure, nil)
    }
    sqlErr = db.Ping()
    if sqlErr != nil {
        return nil, err.New(sqlErr, err.ErrConnectionFailure, nil)
    }
    return &DB{db}, nil
}

.
.
.

роутер:

.
.
.

// Run - starts the server
func (r *Router) Run() *err.Error {
    path := config.MyPath(r.config)
    var httpErr error

    if r.config.Environment == config.Local {
        httpErr = http.ListenAndServe(path, r.mux)
    } else {
        httpErr = http.ListenAndServeTLS(path, r.config.TLSCert(), r.config.TLSKey(), r.mux)
    }

    return err.New(httpErr, err.ErrInternal, nil)
}

.
.
.

основная функция:

// since the db container needs time to start mysql server daemon, the app is retrying the connection infinitely until it succeds, *router.Run()* is a blocking operation.

func main() {
    retry.PerformInfinite(retry.DefaultOptions(), func() *err.Error {
        log.Info("Configuring...")
        c, cErr := config.NewConfig(config.Local)
        if cErr != nil {
            log.Error(cErr)
            return cErr
        }
        log.Info("Configuration successful.")

        log.Info("Connecting to database...")
        db, dbErr := db.Connect(c)
        if dbErr != nil {
            log.Error(dbErr)
            return dbErr
        }
        log.Info("Connected.")

        router := net.NewRouter(db, c)


        log.Info("Server is running.")
        log.Info("Accepting standard input -> ")
        rtErr := router.Run()
        if rtErr != nil {
            log.Error(dbErr)
            return rtErr
        }

        return nil
    })
}


person d.kowalsky92    schedule 03.06.2019    source источник
comment
Вы должны иметь возможность запускать это в установке Docker Desktop, вообще не беспокоясь о конфигурации брандмауэра. (За исключением IIRC, настройка Mac не позволяет вам выполнять привязку к портам с низким уровнем, и вам нужно выбрать другие номера портов.) Можете ли вы показать бит приложения, который привязывается к сетевому сокету?   -  person David Maze    schedule 03.06.2019
comment
Обновил исходный вопрос.   -  person d.kowalsky92    schedule 03.06.2019
comment
Если вы установите server.ip на 0.0.0.0, он работает лучше? (Как правило, в Docker, если вы ** привяжете ** (2) к 127.0.0.1, служба будет недоступна извне собственного контейнера.)   -  person David Maze    schedule 03.06.2019
comment
Омг, это работает, большое спасибо, чувак!   -  person d.kowalsky92    schedule 03.06.2019


Ответы (1)


В Docker обычно адрес localhost 127.0.0.1 означает «этот контейнер». Если вы запустите серверный процесс и попросите его прослушивать 127.0.0.1, он будет принимать только соединения, происходящие из одного и того же контейнера. Вы почти всегда хотите настроить серверы на прослушивание волшебного адреса 0.0.0.0 «все интерфейсы», после чего они смогут принимать соединения от других контейнеров и хоста.

В вашей настройке это просто включает изменение значения конфигурации "server": {"ip": "0.0.0.0"}.

person David Maze    schedule 03.06.2019