Multiple Wordpress with docker

1. Output of caddy version:

v2.6.1 h1:EDqo59TyYWhXQnfde93Mmv4FJfYe00dO60zMiEt+pzo=

2. How I run Caddy:

I use docker compose for running caddy along with another compose for running wordpress.

For the wordpress, I have the following docker-compose:

a. System environment:

OS: Debian 11
Docker version: Docker version 20.10.17, build 100c701
Docker compose: Docker Compose version v2.6.0

b. Command:

docker compose up -d

c. Service/unit/compose file:

caddy’s compose:

version: 3.8
services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    ports:
      - 80:80
      - 443:443
    networks:
      - caddy
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddyfiles:/etc/caddy/Caddyfile.d/
      - ./data:/data
      - ./config:/config
      - /var/www/docker-wordpress/http:/wordpress
    restart: unless-stopped
    environment:
      - PROJECT_NAME_URL=testing
      - PROJECT_DOMAIN=testing.example.com

networks:
  caddy:
    name: caddy

wordpress’ compose:

version: 3.8
services:
  database:
    # default port 3306
    image: mariadb:${MARIADB_VERSION:-latest}
    container_name: ${PROJECT_NAME:-wp}-database
    env_file:
      - .env
    restart: unless-stopped
    networks:
      - default
    environment:
      - MARIADB_DATABASE=${DB_NAME}
      - MARIADB_USER=${DB_USER}
      - MARIADB_PASSWORD=${DB_PASSWORD}
      - MARIADB_RANDOM_ROOT_PASSWORD='1'
    volumes:
      - ${MARIADB_LOCAL_DIR}:/var/lib/mysql
      - ${LOGS_FOLDER}:/var/log/mysql

  wordpress:
    # default port 9000 (FastCGI)
    image: wordpress:php${PHP_VERSION:-7.4}-fpm
    container_name: ${PROJECT_NAME:-default}-wp
    env_file:
      - .env
    restart: unless-stopped
    networks:
      - default
      - caddy
    depends_on:
      - database
    volumes:
      - ${WORDPRESS_LOCAL_DIR}:/var/www/html
      - ${WORDPRESS_PHP_CONFIG}:/usr/local/etc/php/conf.d/conf.ini
    environment:
      - WORDPRESS_DB_HOST=${DB_HOST}
      - WORDPRESS_DB_NAME=${DB_NAME}
      - WORDPRESS_DB_USER=${DB_USER}
      - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}

  wp-cli:
    user: "33"
    depends_on:
      - php
      - database
    image: 'wordpress:cli-php${PHP_VERSION:-7.4}'
    container_name: ${PROJECT_NAME:-wp}-cli
    volumes:
      - ${WORDPRESS_LOCAL_DIR}:/var/www/html
    working_dir: /var/www/html
    command: tail -f /dev/null
    restart: unless-stopped
    networks:
      - default
    environment:
      - WORDPRESS_DB_HOST=${DB_HOST}
      - WORDPRESS_DB_NAME=${DB_NAME}
      - WORDPRESS_DB_USER=${DB_USER}
      - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}
      
  memcached:
    image: memcached
    restart: unless-stopped
    container_name: ${PROJECT_NAME:-wp}-memcached
    entrypoint: memcached -m 256
    networks:
      - default

networks:
  caddy:
    name: caddy

d. My complete Caddy config:

{
	email redacted@example.com
}

import /etc/caddy/Caddyfile.d/*.Caddyfile

Relevant caddy file for wordpress (wordpress.Caddyfile):

{$PROJECT_DOMAIN} {
	root * /wordpress

	# List of disallowed paths
	@disallowed {
		path /xmlrpc.php
		path *.sql
		path /wp-content/uploads/*.php
	}
	rewrite @disallowed '/index.php'

	# Don't allow uploading of .php files to Uploads
	respond /uploads/*.php 404
	
	php_fastcgi wordpress:9000

	encode gzip
	file_server

	log {
		output file /data/wordpress.log {
			roll_size 100
			roll_local_time
			roll_keep 5
			roll_keep_for 720h
		}
	}
}

www.{$PROJECT_DOMAIN} {
	redir https://{$PROJECT_DOMAIN}{uri}
}

3. The problem I’m having:

The folder where the Wordpress code resides is binded to /wordpress in the Caddy docker-compose. But in the Wordpress it is in /var/www/html. When I use the shared configuration, entering the wordpress domain gets me “File not found.” page. This is because it looks at /wordpress instead of /var/www/html. However, If I modify the line - /var/www/docker-wordpress/http:/wordpress in the Caddy’s docker-compose to - /var/www/docker-wordpress/http:/var/www/html and the root to the same folder in the Caddyfile, then it works fine.

I want to do it this way because I will have multiple wordpress sites in different containers. So in the Caddy container there would be /wordpress1, /wordpress2. How coul I route the fastcgi to the root of the container? Is there a way to do this without binding the folders in Caddy’s container?

4. Error messages and/or full log output:

{
  "level": "error",
  "ts": 1664466833.900827,
  "logger": "http.log.access.log0",
  "msg": "handled request",
  "request": {
    "remote_ip": "1XX.XX4.1XX.XX",
    "remote_port": "11809",
    "proto": "HTTP/2.0",
    "method": "GET",
    "host": "testing.example.com",
    "uri": "/",
    "headers": {
      "Sec-Fetch-Site": [
        "none"
      ],
      "Sec-Fetch-Dest": [
        "document"
      ],
      "Cookie": [],
      "User-Agent": [
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36"
      ],
      "Sec-Gpc": [
        "1"
      ],
      "Accept": [
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
      ],
      "Sec-Fetch-Mode": [
        "navigate"
      ],
      "Sec-Fetch-User": [
        "?1"
      ],
      "Accept-Encoding": [
        "gzip, deflate, br"
      ],
      "Upgrade-Insecure-Requests": [
        "1"
      ],
      "Accept-Language": [
        "en-EN;q=0.5"
      ]
    },
    "tls": {
      "resumed": false,
      "version": 772,
      "cipher_suite": 4865,
      "proto": "h2",
      "server_name": "testing.example.com"
    }
  },
  "user_id": "",
  "duration": 0.001916437,
  "size": 16,
  "status": 404,
  "resp_headers": {
    "Server": [
      "Caddy"
    ],
    "Alt-Svc": [
      "h3=\":443\"; ma=2592000"
    ],
    "Status": [
      "404 Not Found"
    ],
    "X-Powered-By": [
      "PHP/8.1.10"
    ],
    "Content-Type": [
      "text/html; charset=UTF-8"
    ]
  }
}

5. What I already tried:

Binding it to /var/www/html in the Caddy container makes it work fine. But I don’t want this as I can’t have multiple wordpress because internally they all point to /var/www/html and I need to differentiate them.

I also can’t and don’t want to modify the Dockerfile for the wordpress image to change the internal route.

You can override the root in the php_fasctcgi directive to have Caddy tell the fastcgi responder to look in a different directory when running the PHP code. The gist:

root * /wordpress
encode gzip
php_fastcgi wordpress:9000 {
	root /var/www/html
}
file_server
3 Likes

This topic was automatically closed after 30 days. New replies are no longer allowed.