Wordpress with Caddy v2 on Docker

Continuing the discussion from Discourse with Caddy v2 on Docker:

1. Caddy version (2.0 / 2.1.0 beta):

2. How I run Caddy:

a. System environment:

Docker on Ubuntu 20.04

b. Command:

docker-compose up

c. Service/unit/compose file:

version: '3.3'

services:
  caddy:
    # env_file:
    #   - .env
    container_name: caddy
    build: .
    ports:
      - "80:80"
      - "443:443"
      - "80:80/udp"
      - "443:443/udp"
    volumes:
      - /var/discourse/shared/web-only:/sock
      - /var/caddy/Caddyfile:/etc/caddy/Caddyfile
      - /var/caddy:/root/.caddy
      - /var/caddy/data:/data
      - /var/caddy/config:/config
    restart: always

  wp1:
    env_file:
      - .env  
    image: $WP_IMAGE
    container_name: wordpress
    hostname: dev.xxxxxxxx.com
    # ports:
    #   - 8080:80
    # depends_on:
    #  - db1
    restart: always
    environment:
      WORDPRESS_DB_HOST: db1
      WORDPRESS_DB_USER: wpdrone
      WORDPRESS_DB_PASSWORD: $MYSQL_PASS_1
      WORDPRESS_DB_NAME: db-wp1
    volumes:
      - /var/www/wp1:/var/www/html

  db1:
    env_file:
      - .env  
    image: $DB_IMAGE
    restart: always
    environment:
      MYSQL_DATABASE: db-wp1
      MYSQL_USER: wpdrone
      MYSQL_PASSWORD: $MYSQL_PASS_1
      MYSQL_ROOT_PASSWORD: $MYSQL_PASS_1
#      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - /var/mysql/wp1:/var/lib/mysql

d. My complete Caddyfile or JSON config:

Working v1 Caddyfile, basically

forums.example.com {
  proxy / unix:/sock/nginx.http.sock {
    transparent
  }
}

dev.example.com {
  proxy / wordpress {
    transparent
  }
}

v2 Caddyfile, actual

{
	debug
}

forum.xxxxxxxx.com {
    reverse_proxy unix//sock/nginx.http.sock
    tls {
        dns cloudflare APIKEY
    }
}

dev.xxxxxxxx.com {
    # root * /var/www/wp1
    # root * /var/www/html
    reverse_proxy / wordpress
    # php_fastcgi / wp1
    # reverse_proxy wordpress
    # php_fastcgi wordrpess
    # php_fastcgi wordrpess:9000
    tls {
        dns cloudflare APIKEY
    }
}

3. The problem I’m having:

This is an attempt to move from working v1 to v2.x.

Discourse is working via the same Caddy docker-compose, but I get a blank page for Wordpress. Internal network issue?

I was getting apache errors from the Wordpress service about it not being able to determing the FQDN before specifying via this line in docker-compose. Not sure if something changed (I’ve never needed that before), or if it’s a symptom of another error:

hostname: dev.xxxxxxxx.com

…after adding that, all service containers build with no error messages.

Of course, these bits of the error log stand out, because they’re similar to the problem I was having with the Discourse setup, which ended up being a syntax error. But I’m not even finding a backslash to change.

upstream wordpress:: invalid dial address wordpress:: invalid start port: strconv.ParseUint: parsing \"\": invalid syntax"

Full error log below

4. Error messages and/or full log output:

invalid dial address, etc.

caddy | {“level”:“error”,“ts”:1593380833.556185,“logger”:“http.log.error”,“msg”:“making dial info: upstream wp1:: invalid dial address wp1:: invalid start port: strconv.ParseUint: parsing “”: invalid syntax”,“request”:{“method”:“GET”,“uri”:"/",“proto”:“HTTP/1.1”,“remote_addr”:“172.68.132.228:44600”,“host”:“dev.xxxxxxxx.com”,“headers”:{“Cookie”:["__cfduid=dc88b5462c50f9e7efa2c00ee103b2a071593329757"],“Cf-Connecting-Ip”:[“2001:5b0:49cc:8b0c:49e8:6443:305d:48f8”],“X-Forwarded-For”:[“2001:5b0:49cc:8b0c:49e8:6443:305d:48f8”],“X-Forwarded-Proto”:[“https”],“Accept”:[“text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8”],“Cf-Visitor”:["{“scheme”:“https”}"],“User-Agent”:[“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0”],“Upgrade-Insecure-Requests”:[“1”],“Cf-Request-Id”:[“039e7f20ed000002df5f066200000001”],“Accept-Encoding”:[“gzip”],“Cf-Ray”:[“5aaa9ae17a0302df-SJC”],“Connection”:[“Keep-Alive”],“Dnt”:[“1”],“Cache-Control”:[“max-age=0”],“Cf-Ipcountry”:[“US”],“Accept-Language”:[“en-US,en;q=0.5”],“Cdn-Loop”:[“cloudflare”]},“tls”:{“resumed”:false,“version”:772,“ciphersuite”:4867,“proto”:"",“proto_mutual”:true,“server_name”:“dev.xxxxxxxx.com”}},“duration”:0.000070497}

5. What I already tried:

  1. Building from Caddy v2.0.0 and v2.1.0 beta Docker images. Both seem to build fine. Side-note: v2.1.0 is released on regular builds. I don’t see a non-beta in Docker hub yet. Is that pending?
  2. Wordpress default (apache) and wordpress:php7.4-fpm. The FPM image seems to respond similarly whether I use php_fastcgi or reverse_proxy in Caddyfile. Pretty sure I was getting the same errors at from both at one point, but currently I don’t get errors with FPM, its just doesn’t seem to do anything.
  3. Various syntax, for example reverse_proxy / wp1 vs. reverse_proxy wp1
  4. Commented variations in Caddyfile and docker-compose.yml.
  5. Referencing variations in Docker network hostnames in Caddyfile. For example, the service name, specifying a container name in compose, using the name reported by Docker (usually has _1 appended to the service name), etc.
  6. I dunno. I’ve now been shuffling bits and pieces around since yesterday.

Compose output for wordpress fpm:

wordpress | [28-Jun-2020 23:02:19] NOTICE: fpm is running, pid 1
wordpress | [28-Jun-2020 23:02:19] NOTICE: ready to handle connections

And for wordpress apache:

wordpress | [Sun Jun 28 23:13:35.526415 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.4.7 configured -- resuming normal operations
wordpress | [Sun Jun 28 23:13:35.526536 2020] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

6. Links to relevant resources:




Thread where I eventually had this working in v1 2 years ago:

Try reverse_proxy http://wordpress or reverse_proxy wordpress:80. I don’t think Caddy assumes a port for the proxy upstream. If you specify http it will assume port 80, or you can explicitly specify port 80.

FYI Caddy v2 differs from v1 in that path matching is now exact-match, so if you put / as the path matcher, it will only match requests to the root of your site and nothing else. Omitting it is the same as * meaning “match all requests”. You can suffix a path matcher with * to match anything that has the given path prefix, e.g. /foo/*

1 Like

Worked!

    reverse_proxy wordpress:80

This is the line in the Upgrade Guide I should have listened to more closely. :laughing:

  • It might be best to go into Caddy 2 with no assumptions carried over from Caddy 1.
2 Likes

To explain this error message, this might read in a misleading manner because the error message is a JSON encoded string. " characters need to be escaped in JSON strings because " is the JSON character for enclosing strings; so the " double quotes are prefixed with \ as an escape character to tell JSON parsers "no, this isn’t the end of the string, it’s just a literal " here. So really the error message is this:

upstream wordpress:: invalid dial address wordpress:: invalid start port: strconv.ParseUint: parsing "": invalid syntax

Which is essentially saying “couldn’t parse an integer number out of an the empty string” or just “couldn’t read a port number”.

I think it’s somewhat of a misleading error message, I’ll look into improving that. Or maybe we’ll assume port 80 like Caddy v1 did in a future release (but Caddy tends to lean towards “HTTPS by default” so that might not happen). TBD.

That error does make sense in retrospect. It also said invalid port, which is pretty clear. I definitely held on to some incorrect assumptions from v1 while working through it.

Any similarly simple solutions for the FPM version? I did try specifying port 9000 with php_fastcgi before posting the thread.

Yeah - just something like this:

root * /var/www/wp1
php_fastcgi php-fpm:9000
file_server

Assumes you have a /var/www/wp1 volume shared with the Caddy container and that your FPM image is named php-fpm.

Thank you for reading the docs :pray: :smiley:

And yes I wish more people read this page! It is very very helpful despite what people say when they complain about our docs.

Anyway, from the directive docs, this part seems relevant:

Upstream addresses can take the form of a conventional Caddy network address or a URL that contains only scheme and host/port

And one of the examples shows example.com as a valid upstream, though now I wonder if that’s still true, and this is maybe leftover from a very early iteration of the reverse_proxy directive, when upstream address parsing was more naive. It could simply be a problem with our docs at this point. I am not sure it is a good idea for Caddy to assume a port to a backend. So I think it’s actually working as intended, just our docs need to be fixed there. Oops.

1 Like

I remember that somewhere in the github repo there used to be something like “code examples”, but that may have been on the v1 Docker repo. It’s possible that exists, and I just missed it, but a list of snippets for common apps with known-good docker-compose bits and the corresponding Caddyfile bits might be helpful. I have no complaints regarding the docs, but my brain sometimes does better adapting known-working configs than going from a generic example to a specific container/app.

My impression was that Docker was less official in v1. Now that the images live in an official Caddy repo on Docker hub, maybe a generic docker-compose.yml on the main page with links to example configs on GitHub? It’s sure helpful to me when the hub pages (like the official Wordpress) have a vanilla docker-compose that can get up and running in 90 seconds.

Y’all are doing great. Your work and responsiveness is appreciated.

Ah, that’s exactly what our wiki is for. We link to it on every page here in the forum and from our main docs nav as well.

Correct! We had no official Docker image in v1. But now we do. I’ll let @francislavoie and @hairyhenderson respond to your suggestion. Thanks!

Ha! Fair enough. I’m on it. I guess if my previous configuration hadn’t been stable for 2 years I would have been paying more attention regularly. Break my sites more often*, and I’ll keep up better. Geez. :grin:

*Caddy didn’t in any way break my sites, but that ruins the hyperbole.

1 Like

Yeah, a docker-compose example in the Docker config is definitely on my TODO list. Haven’t gotten around to that yet because the docs are on the docker-library repo which is a bit more tedious to make changes to than the caddy-docker repo.