traefik 和 php fpm 的网关超时

Gateway timeout with traefik and php fpm

我在使用 traefik 设置 mailcow 时遇到问题,遇到网关超时。我对 nextcloud 也有这个问题,所以我真的很感兴趣,是什么导致了这些网关超时问题。

我想这与端口 9000 和 php-fpm upstream 或某事有关。

但我想确切地知道,以及如何处理它。

我的traefik.toml:

debug = true
checkNewVersion = true
defaultEntryPoints = ["http", "https"]

[web]
address = ":8080"
[web.auth.basic]
users = ["admin:undecipherablestring"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]

[acme]
email = "email@address.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true

[[acme.domains]]
  main = "main.com"
  sans = ["monitor.main.com", "ports.main.com", "git.main.com", "cloud.main.com", "mail.main.com"]

我的 traefik docker-compose.yml:

version: '2'
services:
  proxy:
    image: traefik
    container_name: traefik
    restart: always
    command: |- 
      --docker 
      --docker.domain=docker.localhost 
      --logLevel=DEBUG
    networks:
      - webgateway
    labels:
      - "traefik.frontend.rule=Host: monitor.main.com"
      - "traefik.port=8080"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik.toml:/traefik.toml
      - ./acme.json:/acme.json
      - acme:/opt/traefik/acme

networks:
  webgateway:
    driver: bridge

volumes:
  acme:
    driver: local

我的邮箱docker-compose.yml

version: '2.1'
services:

    unbound-mailcow:
      image: mailcow/unbound:1.0
      build: ./data/Dockerfiles/unbound
      command: /usr/sbin/unbound
      depends_on:
        mysql-mailcow:
          condition: service_healthy
      healthcheck:
        test: ["CMD", "nslookup", "google.com", "127.0.0.1"]
        interval: 30s
        timeout: 3s
        retries: 10
      volumes:
        - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro
      restart: always
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.254
          aliases:
            - unbound

    mysql-mailcow:
      image: mariadb:10.1
      command: mysqld --max_allowed_packet=128M
      healthcheck:
        test: ["CMD", "mysqladmin", "ping", "--host", "localhost", "--silent"]
        interval: 5s
        timeout: 5s
        retries: 10
      volumes:
        - mysql-vol-1:/var/lib/mysql/
        - ./data/conf/mysql/:/etc/mysql/conf.d/:ro
      environment:
        - MYSQL_ROOT_PASSWORD=${DBROOT}
        - MYSQL_DATABASE=${DBNAME}
        - MYSQL_USER=${DBUSER}
        - MYSQL_PASSWORD=${DBPASS}
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.250
          aliases:
            - mysql

    redis-mailcow:
      image: redis:alpine
      depends_on:
        unbound-mailcow:
          condition: service_healthy
      volumes:
        - redis-vol-1:/data/
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.249
          aliases:
            - redis

    clamd-mailcow:
      image: mailcow/clamd:1.1
      build: ./data/Dockerfiles/clamd
      restart: always
      environment:
        - SKIP_CLAMD=${SKIP_CLAMD:-n}
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          aliases:
            - clamd

    rspamd-mailcow:
      image: mailcow/rspamd:1.3
      build: ./data/Dockerfiles/rspamd
      command: > 
        /bin/bash -c "
        sleep 5;
        /usr/bin/rspamd -f -u _rspamd -g _rspamd
        "
      depends_on:
        - nginx-mailcow
      volumes:
        - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:ro
        - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:ro
        - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro
        - dkim-vol-1:/data/dkim
        - rspamd-vol-1:/var/lib/rspamd
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      hostname: rspamd
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.253
          aliases:
            - rspamd

    php-fpm-mailcow:
      image: mailcow/phpfpm:1.0
      build: ./data/Dockerfiles/phpfpm
      command: "php-fpm -d date.timezone=${TZ}"
      depends_on:
        - redis-mailcow
      volumes:
        - ./data/web:/web:ro
        - ./data/conf/rspamd/dynmaps:/dynmaps:ro
        - dkim-vol-1:/data/dkim
      environment:
        - DBNAME=${DBNAME}
        - DBUSER=${DBUSER}
        - DBPASS=${DBPASS}
        - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
        - IMAP_PORT=${IMAP_PORT:-143}
        - IMAPS_PORT=${IMAPS_PORT:-993}
        - POP_PORT=${POP_PORT:-110}
        - POPS_PORT=${POPS_PORT:-995}
        - SIEVE_PORT=${SIEVE_PORT:-4190}
        - SUBMISSION_PORT=${SUBMISSION_PORT:-587}
        - SMTPS_PORT=${SMTPS_PORT:-465}
        - SMTP_PORT=${SMTP_PORT:-25}
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          aliases:
            - phpfpm

    sogo-mailcow:
      image: mailcow/sogo:1.3
      build: ./data/Dockerfiles/sogo
      depends_on:
        unbound-mailcow:
          condition: service_healthy
      environment:
        - DBNAME=${DBNAME}
        - DBUSER=${DBUSER}
        - DBPASS=${DBPASS}
        - TZ=${TZ}
        - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
      volumes:
        - ./data/conf/sogo/:/etc/sogo/
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.252
          aliases:
            - sogo

    dovecot-mailcow:
      image: mailcow/dovecot:1.4
      build: ./data/Dockerfiles/dovecot
      depends_on:
        unbound-mailcow:
          condition: service_healthy
      volumes:
        - ./data/conf/dovecot:/usr/local/etc/dovecot
        - ./data/assets/ssl:/etc/ssl/mail/:ro
        - ./data/conf/sogo/:/etc/sogo/
        - vmail-vol-1:/var/vmail
        - crypt-vol-1:/mail_crypt/
      environment:
        - DBNAME=${DBNAME}
        - DBUSER=${DBUSER}
        - DBPASS=${DBPASS}
      ports:
        - "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
        - "${IMAP_PORT:-143}:143"
        - "${IMAPS_PORT:-993}:993"
        - "${POP_PORT:-110}:110"
        - "${POPS_PORT:-995}:995"
        - "${SIEVE_PORT:-4190}:4190"
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      hostname: ${MAILCOW_HOSTNAME}
      networks:
        mailcow-network:
          aliases:
            - dovecot

    postfix-mailcow:
      image: mailcow/postfix:1.2
      build: ./data/Dockerfiles/postfix
      depends_on:
        unbound-mailcow:
          condition: service_healthy
      volumes:
        - ./data/conf/postfix:/opt/postfix/conf
        - ./data/assets/ssl:/etc/ssl/mail/:ro
        - postfix-vol-1:/var/spool/postfix
        - crypt-vol-1:/var/lib/zeyple
      environment:
        - DBNAME=${DBNAME}
        - DBUSER=${DBUSER}
        - DBPASS=${DBPASS}
      ports:
        - "${SMTP_PORT:-25}:25"
        - "${SMTPS_PORT:-465}:465"
        - "${SUBMISSION_PORT:-587}:587"
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      hostname: ${MAILCOW_HOSTNAME}
      networks:
        mailcow-network:
          aliases:
            - postfix

    memcached-mailcow:
      image: memcached:alpine
      depends_on:
        unbound-mailcow:
          condition: service_healthy
      restart: always
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      networks:
        mailcow-network:
          aliases:
            - memcached

    nginx-mailcow:
      depends_on:
        - sogo-mailcow
        - php-fpm-mailcow
      image: nginx:mainline-alpine
      healthcheck:
        test: ["CMD", "ping", "php-fpm-mailcow", "-c", "5"]
        interval: 5s
        timeout: 5s
        retries: 10
      command: /bin/sh -c "envsubst < /etc/nginx/conf.d/templates/listen_plain.template > /etc/nginx/conf.d/listen_plain.active &&
        envsubst < /etc/nginx/conf.d/templates/listen_ssl.template > /etc/nginx/conf.d/listen_ssl.active &&
        envsubst < /etc/nginx/conf.d/templates/server_name.template > /etc/nginx/conf.d/server_name.active &&
        nginx -g 'daemon off;'"
      environment:
        - HTTPS_PORT=${HTTPS_PORT:-443}
        - HTTP_PORT=${HTTP_PORT:-80}
        - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
      volumes:
        - ./data/web:/web:ro
        - ./data/conf/rspamd/dynmaps:/dynmaps:ro
        - ./data/assets/ssl/:/etc/ssl/mail/:ro
        - ./data/conf/nginx/:/etc/nginx/conf.d/:rw
      expose:
        - "${HTTP_PORT:-80}"      
      #ports:
        #- "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}"
        #- "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"
      restart: always
      dns:
        - 172.622.1.254
      dns_search: mailcow-network
      labels:
      - "traefik.frontend.rule=Host: ${MAILCOW_HOSTNAME}"
      - "traefik.backend=mailcow"
      - "traefik.port=80"
      - "traefik.frontend.entryPoints=http,https"
      - "traefik.docker.network=traefik"
      networks:
        mailcow-network:
          ipv4_address: 172.22.1.251
          aliases:
            - nginx
        traefik:

    acme-mailcow:
      depends_on:
        - nginx-mailcow
      image: mailcow/acme:1.12
      build: ./data/Dockerfiles/acme
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      environment:
        - ADDITIONAL_SAN=${ADDITIONAL_SAN}
        - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
        - DBNAME=${DBNAME}
        - DBUSER=${DBUSER}
        - DBPASS=${DBPASS}
        - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n}
        - SKIP_IP_CHECK=${SKIP_IP_CHECK:-n}
      volumes:
        - ./data/web/.well-known/acme-challenge:/var/www/acme:rw
        - ./data/assets/ssl:/var/lib/acme/:rw
        - ./data/assets/ssl-example:/var/lib/ssl-example/:ro
        - /var/run/docker.sock:/var/run/docker.sock:ro
      # do not restart the container too often. Things get worse when we hit let's encrypt's ratelimit.
      restart: on-failure:1
      networks:
        mailcow-network:
          aliases:
            - acme

    fail2ban-mailcow:
      image: mailcow/fail2ban:1.5
      build: ./data/Dockerfiles/fail2ban
      depends_on:
        - dovecot-mailcow
        - postfix-mailcow
        - sogo-mailcow
        - php-fpm-mailcow
        - redis-mailcow
      restart: always
      privileged: true
      environment:
        - TZ=${TZ}
        - SKIP_FAIL2BAN=${SKIP_FAIL2BAN:-no}
      network_mode: "host"
      dns:
        - 172.22.1.254
      dns_search: mailcow-network
      volumes:
        - /lib/modules:/lib/modules:ro

    ipv6nat:
      image: robbertkl/ipv6nat
      restart: always
      privileged: true
      network_mode: "host"
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - /lib/modules:/lib/modules:ro

networks:
  mailcow-network:
    driver: bridge
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: 172.22.1.0/24
        - subnet: fd4d:6169:6c63:6f77::/64
  traefik:
    external:
      name: traefik_webgateway

volumes:
  vmail-vol-1:
  mysql-vol-1:
  dkim-vol-1:
  redis-vol-1:
  rspamd-vol-1:
  postfix-vol-1:
  crypt-vol-1:

我认为这个问题已经被 traefik 社区解决了。你可以检查这个:https://github.com/containous/traefik/pull/1873

我想我遇到的问题可能与您 are/were 遇到的问题类似。看看这个 GitHub 问题:https://github.com/containous/traefik/issues/979

如果你的问题和我的一样,这里是问题所在:

Traefik 在 "front facing" 网络上,您的一项服务也是如此,但该服务也是 "back facing" 网络的一部分。默认情况下,Traefik 不知道将请求发送到哪个网络...因此它将它们发送到两个 IP 地址选项中随机选择的一个(在创建该容器时选择)。如果 Traefik 不是该网络的一部分,它将无法到达该容器,并且会给您一个网关超时。

解决方案:向您的容器添加一个标签,以直接向 Traefik 指定它应该在哪个网络上进行通信:

 labels:
      - "traefik.enable=true"
      - "traefik.docker.network=<folder prefix>webgateway"
      - "traefik.backend=<backend service"
      - "traefik.frontend.rule=Host:<host setting>"

专业提示:使用 docker network ls 找出网络的 实际 名称是什么,因为它不是 docker-compose 在文件。实际的网络名称是基于它所在的文件夹的名称作为前缀的运行。(我不知道为什么,我不喜欢它,但这就是我们生活的世界)

因此我上面的例子中的<folder prefix>

我所做的是在与 docker-compose.yml 相同的目录中的名为 .env 的文件中定义项目名称的变量(以所有 containers/networks/etc 的前缀结尾)。它应该只包含字符,不能包含空格、破折号等。

COMPOSE_PROJECT_NAME=myproject

然后,在您的应用程序标签中,使用变量名附加创建的网络,并以“_”分隔:

 - "traefik.docker.network=${COMPOSE_PROJECT_NAME}_mynetwork"

FWIW,如果您在 traefik 服务定义中的提供程序部分定义了网络,则无需将其添加到您以后添加的每个服务中。

示例:

version: "3.3"

services:
  traefik:
    image: "traefik:v2.2"
    container_name: "traefik"
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.network=traefik"     <=========
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8090:8080"
    networks:
      - traefik
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

    networks:
      traefik:
        external: true

您应该在 compose 文件之外创建 traefik 网络。