Help moving Wordpress sites to docker-compose, caddy, frankenphp, mariadb

1. The problem I’m having:

I’m trying to take a simple “brochure” wordpress site I’ve been maintaining for years on a VPS with nginx, php, mariadb, and move it into a local setup where I want to use docker-compose, caddy, frankenphp, and mariadb.
I’ve hit all kinds of errors. I’ve tried with and without https, though I’m not sure I ever got that right.

2. Error messages and/or full log output:

curl -vL https://nocnocs-localhost:8443

  • Host nocnocs-localhost:8443 was resolved.
  • IPv6: (none)
  • IPv4: 127.0.0.1
  • Trying 127.0.0.1:8443…
  • ALPN: curl offers h2,http/1.1
  • TLSv1.3 (OUT), TLS handshake, Client hello (1):
  • CAfile: /etc/ssl/certs/ca-certificates.crt
  • CApath: none
  • TLSv1.3 (IN), TLS alert, internal error (592):
  • TLS connect error: error:0A000438:SSL routines::tlsv1 alert internal error
  • closing connection #0
    curl: (35) TLS connect error: error:0A000438:SSL routines::tlsv1 alert internal error


## 3. Caddy version:
docker-compose exec ca
ddy caddy version
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=

4. How I installed and ran Caddy:

a. System environment:

uname -a
Linux xps55202025 6.14.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 10 Apr 2025 18:43:59 +0000 x86_64 GNU/Linux.

b. Command:

docker-compose up

c. Service/unit/compose file:

 cat docker-compose.yml
services:
  mariadb:
    image: mariadb:latest
    container_name: mariadb
    volumes:
      - ./data/mariadb:/var/lib/mysql
      - ./conf/maria.env:/etc/mysql/conf.d/mariadb.cnf
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
    networks:
      - backend
    restart: always

  frankenphp:
    image: dunglas/frankenphp:latest
    container_name: frankenphp
    depends_on:
      - mariadb
    volumes:
      - ./wordpress:/var/www/html
      - ./conf/php.ini:/etc/php/8.3/fpm/php.ini
    environment:
      - SERVER_NAME=${SERVER_NAME}
      - WORDPRESS_DB_HOST=mariadb:3306
      - WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME}
      - WORDPRESS_DB_USER=${WORDPRESS_DB_USER}
      - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
    expose:
      - "80"  # Expose port 80 to other services in the same network
    restart: always
    networks:
      - backend

  caddy:
    image: caddy:2-alpine
    container_name: caddy
    depends_on:
      - frankenphp
    volumes:
      - ./data/caddy:/data
      - ./data/caddy/config:/config
      - ./Caddyfile:/etc/caddy/Caddyfile
    ports:
      - "8080:80"
      - "8443:443"
    restart: always
    networks:
      - backend

networks:
  backend:
    driver: bridge

d. My complete Caddy config:

 cat Caddyfile
{
    debug
}

nocnocs-localhost {
  reverse_proxy frankenphp:80
  file_server
}

5. Links to relevant resources:

I’ve been referring to the Caddy docs, using my not-great docker knowledge, and getting AI help.

frankenphp is already Caddy with PHP, so you kind of wrapping it in another Caddy by running another caddy container. But you certainly can do that.

Just something quick to help you move forward:

{
    debug
}

nocnocs-localhost {
    tls internal
    reverse_proxy frankenphp:80
}
1 Like

Thanks for your reply. I had actually tried “tls internal” but that was before I knew about the “debug” directive, so using them both I have at least a little more information to work with.

I maybe should have mentioned that ultimately I won’t even be needing SSL. My motivation here is to to develop locally, flatten things to a static site, and put it on Cloudflare, consolidating where I already have the sites’ registration and DNS. Cloudflare will supply the SSL.

This is interesting too what you say about Frankenphp including(?) Caddy, as I thought that was the case. At one point I was trying to use dunglas/frankenphp-caddy until I learned that’s no longer maintained and not recommended.

So I should figure out how to remove all the SSL stuff I guess? And if there’s a way I can strip out this “extra caddy”, can you point me towards docs for that?

Meanwhile, though it won’t really be relevant if I get rid of the SSL, just to show what I found with “tls internal” in conjunction with “debug”:

 curl -vL https://nocnocs-localhost:8443
* Host nocnocs-localhost:8443 was resolved.
* IPv6: (none)
* IPv4: 127.0.0.1
*   Trying 127.0.0.1:8443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* closing connection #0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.

That led me to trying with the -k option:

curl -vLk https://nocnocs-localhost:8443
* Host nocnocs-localhost:8443 was resolved.
* IPv6: (none)
* IPv4: 127.0.0.1
*   Trying 127.0.0.1:8443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: 
*  start date: Apr 15 13:42:54 2025 GMT
*  expire date: Apr 16 01:42:54 2025 GMT
*  issuer: CN=Caddy Local Authority - ECC Intermediate
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
* Connected to nocnocs-localhost (127.0.0.1) port 8443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://nocnocs-localhost:8443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: nocnocs-localhost:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.13.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: nocnocs-localhost:8443
> User-Agent: curl/8.13.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Request completely sent off
< HTTP/2 308 
< alt-svc: h3=":443"; ma=2592000
< date: Tue, 15 Apr 2025 13:44:59 GMT
< location: https://nocnocs-localhost/
< server: Caddy
< server: Caddy
< content-length: 0
* Ignoring the response-body
* setting size while ignoring
< 
* Connection #0 to host nocnocs-localhost left intact
* Clear auth, redirects to port from 8443 to 443
* Issue another request to this URL: 'https://nocnocs-localhost/'
* Host nocnocs-localhost:443 was resolved.
* IPv6: (none)
* IPv4: 127.0.0.1
*   Trying 127.0.0.1:443...
* connect to 127.0.0.1 port 443 from 127.0.0.1 port 39794 failed: Connection refused
* Failed to connect to nocnocs-localhost port 443 after 0 ms: Could not connect to server
* closing connection #1
curl: (7) Failed to connect to nocnocs-localhost port 443 after 0 ms: Could not connect to server

Just remove the caddy section from your docker-compose and do in frankenphp whatever you’d normally set up in caddy. There’s a Caddyfile built right into frankenphp.

Here’s one of many possible examples of how to run frankenphp with docker-compose:

You can find more details on their documentation site.

Thanks I’m almost there. The hardest part was just getting something served up over HTTP and forcing it to not use HTTPS, despite trying many ways, but I’m there now, it’s trying to serve my Wordpress site.

But it needs php_mysqli still.

When I sought answers, I first found this:

   command: >
      /bin/sh -c "
        install-php-extensions mysqli pdo_mysql &&
        exec /usr/local/bin/frankenphp"

which doesn’t play nicely with frankenphp, so then I found:

    command: >
      /bin/sh -c "
        docker-php-ext-install mysqli pdo pdo_mysql &&
        php-fpm"

which also doesn’t play nicely with frankenphp.

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