【问题标题】:Bad Gateway for WordPress containers behind Traefik reverse proxy in docker-composedocker-compose 中 Traefik 反向代理后面的 WordPress 容器的错误网关
【发布时间】:2022-12-23 17:38:49
【问题描述】:

首先,我想说我不是服务器管理员。我是一名网络程序员,负责设置开发服务器,但我不知道自己在做什么。我可能没有按照最佳实践或您可能做事的方式做事。不幸的是,使用 Traefik,有 3 种方法可以做所有事情,所以我遇到的 2/3 的答案与我的实现不兼容,我不知道如何让它们工作。此外,这不是我唯一的(甚至不是主要的)工作职责。

这是设置:

带有 Ubuntu 20.04 的 Linode 服务器上的单服务器 docker 环境

我有一个堆栈,其中配置了 Traefik、Traefik Hub、Portainer 和 WhoAmI,并且(大部分)工作正常。我没有让 DNS 挑战与 Let's Encrypt 一起工作,但我现在并不关心这个。我真的不需要通配符证书。

我创建了一个 mariadb 容器。我们主要是一家 WordPress 商店,我希望有一个容器来容纳我们使用的所有数据库,而不是在逐个环境的基础上配置数据库。

我创建了一个名为“maverick-net”的外部桥接网络,所有堆栈都连接到它。

我有一个自托管的 GitHub 运行器,用于监听对项目“dev”分支的更改。运行者拉下最新的 repo,将 GitHub 秘密写入本地 .env 文件,运行composer install,然后运行docker-compose up -d。 (这就是超长绑定安装路径背后的原因。)

我试图让这些 WordPress 项目的代码尽可能地可重用,所以在不同的文件中有很多 .env 变量。在某些时候,我可能会将它们移到 docker secrets,但此时它是一个开发服务器,并不那么重要。

我的问题是我无法启动和运行 WordPress 站点,而且我一直遇到“Bad Gateway”错误。当我从 traefik 容器内卷曲 URL 时,我得到...等待它...“Bad Gateway”。

显然我缺少了一些东西,但几周来我一直在用头撞砖墙,尝试不同的方法来让它运行,我需要帮助。总的来说,关于 docker 网络一定有一些我没有得到的东西,因为我的 wp-cli 容器从来没有能够连接到数据库,无论我是在同一个堆栈中启动它还是尝试连接到它特立独行的网络。

我的 traefik 堆栈(旁注,我真的很想将这些 command 条目拆分为静态和动态配置文件,但这是另一天的任务):

version: "3.9"

secrets:
  linode_token:
    file: "../secrets/linode_token.secret"

services:

  traefik:
    container_name: traefik
    image: "traefik:latest"
    command:
      - --log.level=DEBUG
      - --log.filePath=./traefik.log
      - --accessLog=true
      - --accessLog.filePath=./access.log
      - --accessLog.bufferingSize=100
      - --accessLog.filters.statusCodes=400-499
      - --api
      - --api.dashboard=true
      - --api.insecure=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker
      - --providers.docker.watch=true
      - --providers.docker.exposedbydefault=false
      - --certificatesresolvers.leresolver.acme.dnsChallenge=true
      - --certificatesresolvers.leresolver.acme.dnsChallenge.provider=linodev4
      - --certificatesresolvers.leresolver.acme.httpchallenge=true
      - --certificatesresolvers.leresolver.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.leresolver.acme.email=xxxxxxxxxxx@xxxxxxxxx.xxx
      - --certificatesresolvers.leresolver.acme.storage=./acme.json
      #- --certificatesresolvers.leresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.leresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
      - --experimental.hub=true
      - --hub.tls.insecure=true
      - --metrics.prometheus.addrouterslabels=true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ~/certs-data/acme.json:/data/letsencrypt/acme.json
      - ./static.yml:/static.yml:ro
      - ./configs:/configs
      - ~/certs-data/:/data/letsencrypt/
    secrets:
      - "linode_token"
    environment:
      TZ: America/Chicago
      LINODE_TOKEN_FILE: "/run/secrets/linode_token"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=maverick-net"
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.http.routers.traefik.tls.certresolver=leresolver"
      - "traefik.http.routers.traefik.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=traefik-auth"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=XXXX:$$apr1$$XXXXX$$XXXXXXXXXXXXXXX"
      - "traefik.http.routers.api.entrypoints=websecure"
    networks:
      - maverick-net

  hub-agent:
    image: ghcr.io/traefik/hub-agent-traefik:experimental
    pull_policy: always
    container_name: hub-agent
    restart: on-failure
    command:
      - run
      - --hub.token=XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
      - --auth-server.advertise-url=http://hub-agent
      - --traefik.host=traefik
      - --traefik.tls.insecure=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    depends_on:
      - traefik
    networks:
      - maverick-net

  portainer:
    image: portainer/portainer-ce:latest
    command: -H unix:///var/run/docker.sock
    container_name: portainer
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    labels:
      # Frontend
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.services.frontend.loadbalancer.server.port=9000"
      - "traefik.http.routers.frontend.service=frontend"
      - "traefik.http.routers.frontend.tls.certresolver=leresolver"
    networks:
      - maverick-net

  whoami:
    image: "traefik/whoami"
    container_name: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=leresolver"
    networks:
      - maverick-net

volumes:
  portainer_data:
networks:
  maverick-net:
    external: true

我的 mariadb 堆栈:

version: "3"

networks:
  # enable connection with Traefik
  maverick-net:
    external: true

services:
  mariadb:
    container_name: mariadb
    image: mariadb:10.7
    restart: always
    volumes:
      - "/home/xxxxxxxxxx/docker/mariadb/data:/var/lib/mysql"
    expose:
      - "3306"
    env_file: .env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PWD}
      MYSQL_USER: ${ADMIN_DB_USER}
      MYSQL_PASSWORD: ${ADMIN_DB_PWD}
    networks:
      - maverick-net

最后是我的 WordPress 堆栈:

version: '3.8'

networks:
  maverick-net:
    external: true
# volumes:
#   db_data:

services:

  # mariadb:
  #   container_name: ${WORDPRESS_DB_NAME}-db
  #   image: mariadb:10.7
  #   restart: always
  #   volumes:
  #     - "db_data:/var/lib/mysql"
  #   env_file: .env
  #   environment:
  #     MYSQL_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
  #     MYSQL_USER: ${ADMIN_DB_USER}
  #     MYSQL_PASSWORD: ${ADMIN_DB_PWD}

  wordpress:
    container_name: ${WORDPRESS_DB_NAME}-wp
    image: wordpress:6.0.2-fpm
    volumes:
      - type: bind
        source: ${PROJECT_ROOT}/${WORDPRESS_DB_NAME}/${PROJECT_NAME}/${PROJECT_NAME}/wp
        target: /var/www/html
    restart: always
    env_file: .env
    environment:
      WORDPRESS_DB_HOST: mariadb
      MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
      WORDPRESS_DATABASE_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DATABASE_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      WORDPRESS_DATABASE_NAME: ${WORDPRESS_DB_NAME}
    labels:
      # The labels are useful for Traefik only
      - "traefik.enable=true"
      - "traefik.docker.network=maverick-net"
      # Get the routes from https
      - "traefik.http.routers.${WORDPRESS_DB_NAME}.rule=Host(`${DEV_URL}`)"
      - "traefik.http.routers.${WORDPRESS_DB_NAME}.entrypoints=websecure"
      - "traefik.http.routers.${WORDPRESS_DB_NAME}.tls.certresolver=leresolver"
    networks:
      - maverick-net

  wordpress-cli:
    container_name: ${WORDPRESS_DB_NAME}-cli
    image: wordpress:cli
    volumes:
      - type: bind
        source: ${PROJECT_ROOT}/${WORDPRESS_DB_NAME}/${PROJECT_NAME}/${PROJECT_NAME}/wp
        target: /var/www/html
    env_file: .env
    environment:
      WORDPRESS_DB_HOST: mariadb
      MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
      WORDPRESS_DATABASE_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DATABASE_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      WORDPRESS_DATABASE_NAME: ${WORDPRESS_DB_NAME}
    networks:
      - maverick-net
    depends_on:
      - wordpress

【问题讨论】:

    标签: wordpress docker traefik


    【解决方案1】:

    我也在想办法做到这一点。

    据我所知,您可以使用它们的服务名称连接到同一网络中的容器。

    因此,例如,您正试图从 Traefik 容器卷曲到 Wordpress 容器。

    curl 'http://wordpress/'
    

    应该管用。

    在另一个项目中,我使用带有 php-fpm 的 nginx 容器。 我需要将我的 curl 请求发送到 nginx 容器,因为 php-fpm 容器不直接处理服务器请求:

    // does not work
    curl 'http://php-debug/index.html'
    // result
    curl: (7) Failed to connect to php-debug port 80: Connection refused
    
    // https also does not work
    curl 'https://php-fpm/index.html'
    // result
    curl: (7) Failed to connect to php-fpm port 443: Connection refused
    
    // This does work
    curl 'http://nginx/index.html'
    // result
    <HTML...
    
    

    由于某种原因 https: curl 请求失败,但在 http 上我得到了正确的结果,所以对于本地开发我认为没问题。

    如果您对更受管理的解决方案感兴趣,可以查看 warden.dev。它也包含一个 Wordpress 模板(我成功地将其用于本地开发)。我一直在专门使用这个。如果您对如何在此解决方案上设置 WP CLI 有疑问,请随时与我联系。

    它带有 portainer、traefik、ssl 和 dns 以及 mailhog。 配置非常简单,我可以在一个小时内设置一个新项目并连接到我的 IDE 中的数据库和容器。

    https://docs.warden.dev/environments/types.html#wordpress

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      相关资源
      最近更新 更多