Access denied creating admin user

I am trying to add Nextcloud to my docker-compose.yml file and have it behind Traefik. I can reach the setup page, but after entering entering a username and password for the admin (and the database user, password, name, and host), I get this error:

Error while trying to create admin user: Failed to connect to the database: An exception occurred in driver: SQLSTATE[HY000] [1045] Access denied for user ‘nextcloud’@’’ (using password: YES)

This is my first stack using a database and I am not sure how to get it setup.

My .env file looks like this:

DOCKERDIR=/path/to/config
DOMAINNAME=mydomain.com
MYSQL_ROOT_PASSWORD=<password>
MYSQL_PASSWORD=<another password>
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud

A snippet of my docker-compose.yml file looks like this:

version: "3.3"

    ########################### NETWORKS
    networks:
      t2_proxy:
        external:
          name: t2_proxy
      default:
        driver: bridge

    ########################### SERVICES
    services:
    # All services / apps go below this line

    # Traefik 2 - Reverse Proxy
      traefik:
        container_name: traefik
        image: traefik:chevrotin # the chevrotin tag refers to v2.2.x but introduced a breaking change in 2.2.2
        restart: unless-stopped
        command: # CLI arguments
          - --global.checkNewVersion=true
          - --global.sendAnonymousUsage=false
          - --entryPoints.http.address=:80
          - --entryPoints.https.address=:443
            # Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
          - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22
          - --entryPoints.traefik.address=:8080
          - --api=true
    #      - --api.insecure=true
    #      - --serversTransport.insecureSkipVerify=true
          - --log=true
          - --log.level=DEBUG # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
          - --accessLog=true
          - --accessLog.filePath=/traefik.log
          - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
          - --accessLog.filters.statusCodes=400-499
          - --providers.docker=true
          - --providers.docker.endpoint=unix:///var/run/docker.sock
    #      - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`)
          - --providers.docker.exposedByDefault=false
          # Add dns-cloudflare as default certresolver for all services. Also enables TLS and no need to specify on individual services
          - --entrypoints.https.http.tls.certresolver=dns-cloudflare
          - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME
          - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME
          - --providers.docker.network=t2_proxy
          - --providers.docker.swarmMode=false
          - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
    #      - --providers.file.filename=/path/to/file # Load dynamic configuration from a file.
          - --providers.file.watch=true # Only works on top level files in the rules folder
    #      - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
          - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
          - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
          - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
          - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
        networks:
          - t2_proxy
          - default
        security_opt:
          - no-new-privileges:true
        ports:
          - target: 80
            published: 80
            protocol: tcp
            mode: host
          - target: 443
            published: 443
            protocol: tcp
            mode: host
          - target: 8080
            published: 8080
            protocol: tcp
            mode: host
        volumes:
          - $DOCKERDIR/traefik2/rules:/rules 
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - $DOCKERDIR/traefik2/acme/acme.json:/acme.json # cert location - you must touch this file and change permissions to 600
          - $DOCKERDIR/traefik2/traefik.log:/traefik.log # for fail2ban - make sure to touch file before starting container
          - $DOCKERDIR/shared:/shared
        environment:
          - CF_API_EMAIL=$CLOUDFLARE_EMAIL
          - CF_API_KEY=$CLOUDFLARE_API_KEY
        labels:
          - "traefik.enable=true"
          # HTTP-to-HTTPS Redirect
          - "traefik.http.routers.http-catchall.entrypoints=http"
          - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
          - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
          - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
          # HTTP Routers
          - "traefik.http.routers.traefik-rtr.entrypoints=https"
          - "traefik.http.routers.traefik-rtr.rule=HostHeader(`traefik.$DOMAINNAME`)"
          - "traefik.http.routers.traefik-rtr.tls.certResolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs
          ## Services - API
          - "traefik.http.routers.traefik-rtr.service=api@internal"
         ## Middlewares    
          - "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file"

      mariadb:
        env_file: .env
        image: mariadb
        networks:
          - default
        volumes:
          - $DOCKERDIR/mariadb:/var/lib/mysql
          - /etc/localtime:/etc/localtime:ro
        environment:
          - MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
          - MYSQL_PASSWORD=$MYSQL_PASSWORD
          - MYSQL_DATABASE=$MYSQL_DATABASE
          - MYSQL_USER=$MYSQL_USER
        ports:
          - 3306:3306
        restart: unless-stopped
        volumes:
          - $DOCKERDIR/mariadb:/var/lib/mysql

      redis:
        image: redis:5
        networks:
          - default
        restart: unless-stopped
        volumes:
          - $DOCKERDIR/redis:/data

      nextcloud:
        depends_on:
          - mariadb
          - redis
          - traefik
        image: nextcloud:latest
        labels:
          - traefik.enable=true
          - traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent=true
          - traefik.http.middlewares.nextcloud-caldav.redirectregex.regex=^https://(.*)/.well-known/(card|cal)dav
          - traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement=https://$${1}/remote.php/dav/
          - traefik.http.middlewares.nextcloud-https.redirectscheme.scheme=https
          - traefik.http.routers.nextcloud-http.entrypoints=https
          - traefik.http.routers.airsonic.rule=Host(`cloud.$DOMAINNAME`)
          - traefik.http.routers.nextcloud-http.middlewares=nextcloud-https@docker
          - traefik.http.routers.nextcloud.entrypoints=https
          - traefik.http.routers.nextcloud.rule=Host(`cloud.$DOMAINNAME`)
          - traefik.http.routers.nextcloud.middlewares=nextcloud-caldav@docker
          - traefik.http.routers.nextcloud.tls=true
          - traefik.http.routers.nextcloud.tls.certresolver=default
        networks:
          - default
        restart: unless-stopped
        volumes:
          - $DOCKERDIR/nextcloud/html:/var/www/html
          - /etc/localtime:/etc/localtime:ro

Any thoughts?