Bad Gateway for WordPress containers behind Traefik reverse proxy in docker-compose

Viewed 44

Firstly, I'd like to say that I'm not a server admin. I'm a web programmer tasked with setting up a development server and I have no idea what I'm doing. I may not be doing things according to best practice or the way you might do them. Unfortunately, with Traefik, there are 3 ways to do everything and so 2/3 of the answers that I've come across aren't compatible with my implementation and I can't figure out how to make them work. Furthermore, this isn't my only (or even primary) job duty.

Here's the setup:

Single-server docker environment on a Linode server with Ubuntu 20.04

I have one stack with Traefik, Traefik Hub, Portainer, and WhoAmI configured and working (mostly) correctly. I don't have the DNS challenge working right with Let's Encrypt, but I don't really care about that at this point. I don't really need a wildcard certificate.

I created a mariadb container. We're mostly a WordPress shop and I'd like to have one container for all the databases we work with rather than configuring a database on an environment-by-environment basis.

I created an external bridge network, named "maverick-net" and all of the stacks are connected to it.

I have a self-hosted GitHub runner listening for changes to the "dev" branch of the project. The runner pulls down the latest repo, writes GitHub secrets to a local .env file, runs composer install and then docker-compose up -d. (That's the reason behind the obscenely-long bind mount paths.)

I'm trying to make the code for these WordPress projects reusable as much as possible, so there's a lot of .env variables in the different files. At some point I'll probably move those over to docker secrets, but at this point it's a development server and not as critical.

My issue is that I haven't been able to get a WordPress site up and running, and I keep hitting a "Bad Gateway" error. When I curl the URL from inside the traefik container, I get... wait for it... "Bad Gateway."

Clearly there's something I'm missing, but I've been slamming my head against a brick wall for weeks trying different approaches to get this running and I need help. There has to be something I'm not getting about docker networks in general because my wp-cli container never has been able to connect to the database, regardless of whether I start it in the same stack or if i try to connect to it on the maverick-net network.

My traefik stack (side note, I'd really like to split these command entries into static and dynamic config files, but that's a task for another day):

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

My mariadb stack:

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

And finally my WordPress stack:

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

0 Answers
Related