cURL error 7 with PHP 8.1 + in multiple docker projects

Docker version 24.0.2
Ubuntu (WSL) 22.04
WSL version: 2.1.5.0

I have two unrelated docker projects both displaying cURL error 7 messages when upgrading from PHP 8.0 to PHP 8.1 and later. Both projects are WordPress stacks with reverse proxies, one is more complex with Apache which I’ll omit, the other is very simple with Nginx see details below.

Up to WordPress PHP 8.0 I experienced the following two WordPress Site Health check errors:

REST API Endpoint: https://wordpress.localhost/index.php?rest_route=%2Fwp%2Fv2%2Ftypes%2Fpost&context=edit
REST API Response: (http_request_failed) cURL error 7: Failed to connect to wordpress.localhost port 443 after 0 ms: Couldn't connect to server

The loopback request to your site failed, this means features relying on them are not currently working as expected.
Error: cURL error 7: Failed to connect to wordpress.localhost port 443 after 0 ms: Couldn't connect to server (http_request_failed)

These were both resolved by adding the following to the wordpress service in docker compose:

extra_hosts:
  - wordpress.localhost:172.17.0.1

Unfortunately with PHP 8.1 and later in Nginx and Apache the same errors are back.

If I execute:

docker exec -it wordpress bash

then

curl -Lv http://wordpress.localhost

there are no errors but if I execute the same command for ssl:

curl -Lv https://wordpress.localhost

I get the following error:

*   Trying 127.0.0.1:443...
* connect to 127.0.0.1 port 443 failed: Connection refused
*   Trying [::1]:443...
* Immediate connect fail for ::1: Cannot assign requested address
* Failed to connect to wordpress.localhost port 443 after 0 ms: Couldn't connect to server
* Closing connection 0
curl: (7) Failed to connect to wordpress.localhost port 443 after 0 ms: Couldn't connect to server

If I roll back WordPress to PHP 8.0 and execute the same cURL command in the same container:

curl -Lv https//wordpress.localhost

the error is different:

*   Trying 172.17.0.1:443...
* Connected to wordpress.localhost (172.17.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* 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 web page mentioned above.
root@71dcc56b92f6:/var/www/html#

I notice PHP 8.1 attempts to connect to 127.0.0.1 and PHP 8.0 to 172.17.0.1.

I can cURL both my projects from Ubuntu (WSL) without any errors using:

curl -Lv https://wordpress.localhost

Everything else appears correct and there are no SSL errors in the browser or elsewhere so it feels like an internal docker networking issue with SSL and reverse proxies. My project is public on GitHub here.

My Docker Compose YAML:

name: lemp

services:
  mariadb:
    image: mariadb:11.2.3-jammy
    container_name: mariadb
    restart: always
    expose:
      - 3306
    volumes:
      - lemp_db_data:/var/lib/mysql
    environment:
      MARIADB_DATABASE: rds_mysql
      MARIADB_USER: wpress
      MARIADB_PASSWORD: wpress_247x
      MARIADB_ROOT_PASSWORD: root_wpress_247x
    networks:
      - nginx

  wordpress:
    depends_on:
      - mariadb
    image: wordpress:6.4.1-php8.1
    container_name: wordpress
    restart: unless-stopped
    expose:
      - 80
      - 443
    extra_hosts:
      - wordpress.localhost:172.17.0.1
    environment:
      WORDPRESS_DB_HOST: mariadb
      WORDPRESS_DB_USER: wpress
      WORDPRESS_DB_PASSWORD: wpress_247x
      WORDPRESS_DB_NAME: rds_mysql
      WORDPRESS_DEBUG: 1
      WORDPRESS_CONFIG_EXTRA: |
        define( 'WP_DEBUG_DISPLAY', true );
        define( 'WP_DEBUG_LOG', true );
    networks:
      - nginx

  nginx:
    image: nginx:1.25.2
    container_name: nginx
    restart: unless-stopped
    depends_on:
      - wordpress
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/ssl/my_wpress_site.crt:/etc/nginx/my_wpress_site.crt
      - ./nginx/ssl/my_wpress_site.key:/etc/nginx/my_wpress_site.key
      - /var/log/nginx:/var/log/nginx
    networks:
      - nginx

volumes:
  lemp_db_data:
    external: true

networks:
  nginx:
    name: nginx

My Nginx default.conf:

server {
    listen            80;
    listen       [::]:80;
    server_name  wordpress.localhost;

    location / {
        access_log off;
        return 301 https://$server_name$request_uri;
        proxy_set_header      X-Forwarded-Proto http;
    }
}

server {

    listen            443 ssl;
    listen       [::]:443 ssl;

    server_name  wordpress.localhost;

    access_log   /var/log/nginx/wordpress-443-access.log main;
    error_log		 /var/log/nginx/wordpress-443-error.log debug;

    ssl_certificate		/etc/nginx/my_wpress_site.crt;
    ssl_certificate_key		/etc/nginx/my_wpress_site.key;

    location / {
        proxy_pass http://wordpress;
        proxy_redirect        off;
        proxy_read_timeout    90;
        proxy_connect_timeout 90;
        proxy_set_header      X-Forwarded-Proto https;
    }
}

I am not a programmer so I’m having to learn everything as I go along but I’m finding this last part difficult to resolve.

You know that at this point you are not using PHP at all, right? It is just a shell.
Domain name resolution in the shell has nothing to do with PHP or Wordpress, only the dns server or related services which are not running in any of the containers. So what can cause the issue is curl itself. New PHP base images use new Debian versions including new curl. See the following post on stack overflow

So the problem is that recent curl versions always resolve domains to 127.0.0.1 when the domain ends with .localhost. You can change the ending to .local and it will work.

1 Like

Hey thanks, I’m so grateful, I have to start my (real) job in five minutes but I’ll take a look after work this evening. Changing the domain suffix to .local means I’ll have to generate new SSL certificates for the new domain which will take a while so I’ll post back once I’ve had time to test everything but this looks really promising.

EDIT

You know that at this point you are not using PHP at all, right? It is just a shell.

Thanks yes, I figured that much :kissing_smiling_eyes: I worded it badly but I figured out it was probably a library bundled in the WordPress PHP version and probably cURL or OpenSSL, your solution should be ideal.

It works.

As I thought, I had to make a new SSL certificate with the tld “.local” instead of “.localhost”, it only took a few minutes because I only had to make the one. I also remembered to update the hosts files in Ubuntu (WSL) and Windows.

This project is currently used just for testing, now I can go back to my other docker project which has a couple of extra containers and update that one with the same fix.

So grateful for the help.

In case anyone else has the same issue, @rimelek’s solution also worked for my other project with an Apache network. Suddenly I’m a fan of Docker again :kissing_smiling_eyes: