Docker-compose: Curl gets empty caddy response

1. Caddy version (`2.4.3):

2. How I run Caddy:

I am using 2 different docker-compose projects. The one I want to call via curl uses this configuration: symfony-docker/docker-compose.yml at main · dunglas/symfony-docker · GitHub

I added networks, extra_hosts… nothing worked.

a. System environment:

Docker-compose, Linux Mint 18.

b. Command:

Inside the different docker-compose project, I tried many variations of:

curl api.localost
curl apitest

d. My complete Caddyfile or JSON config:

version: "3.4"

#networks:
  
      
services:
  php:
#    networks:
#      - api
    container_name: commando_php
    build:
      context: .
      target: symfony_php
      args:
        SYMFONY_VERSION: ${SYMFONY_VERSION:-}
        SKELETON: ${SKELETON:-symfony/skeleton}
        STABILITY: ${STABILITY:-stable}
    restart: unless-stopped
    volumes:
      - php_socket:/var/run/php
    healthcheck:
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s
    environment:
      # Run "composer require symfony/orm-pack" to install and configure Doctrine ORM
      DATABASE_URL: postgresql://${POSTGRES_USER:-symfony}:${POSTGRES_PASSWORD:-ChangeMe}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-13}
      # Run "composer require symfony/mercure-bundle" to install and configure the Mercure integration
      MERCURE_URL: ${CADDY_MERCURE_URL:-http://caddy/.well-known/mercure}
      MERCURE_PUBLIC_URL: https://${SERVER_NAME:-localhost}/.well-known/mercure
      MERCURE_JWT_SECRET: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}

  caddy:
#    networks:
#      - api
#    networks:
#      api:
#        aliases:
#          - php.dock
    container_name: commando_caddy
    build:
      network: host
      context: .
      target: symfony_caddy
    depends_on:
      - php
    environment:
      SERVER_NAME: ${SERVER_NAME:-localhost, caddy:80}
      MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}
      MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeMe!}
    restart: unless-stopped
    volumes:
      - php_socket:/var/run/php
      - caddy_data:/data
      - caddy_config:/config
    ports:
      # HTTP
      - target: 80
        published: 80
        protocol: tcp
      # HTTPS
      - target: 443
        published: 443
        protocol: tcp
      # HTTP/3
      - target: 443
        published: 443
        protocol: udp
    extra_hosts:
      - "host.docker.internal:host-gateway"
      - "apitest:host-gateway"
        
###> doctrine/doctrine-bundle docker pull postgis/postgis:13-3.1-alpine ###
  database:
    image: postgis/postgis:13-3.1-alpine
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-app}
      # You should definitely change the password in production
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe}
      POSTGRES_USER: ${POSTGRES_USER:-symfony}
    volumes:
      - db-data:/var/lib/postgresql/data:rw
      # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
      # - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###

volumes:
  php_socket:
  caddy_data:
  caddy_config:

###> doctrine/doctrine-bundle ###
  db-data:
###< doctrine/doctrine-bundle ###

3. The problem I’m having:

Docker-compose works perfect when I run it with SERVER_NAME="api.localhost:80" docker-compose up -d --build.

But completely isolated project having its own docker-compose, doesn’t see it at all. The best I got was empty response when I curl-ed to IP address I found via inspect.

4. Error messages and/or full log output:

There are none. The only response I get is this when I curl -i 192.168.112.4:

HTTP/1.1 200 OK
Server: Caddy
Date: Mon, 26 Jul 2021 11:03:23 GMT
Content-Length: 0

5. What I already tried:

I have been trying to solve this problem for last 3-4 days, nothing worked. I am absolute Docker+caddy noob, my first time of using them and so far, probably tried about 100 different combinations.

Most recommendations are to use host.docker.internal:host-gateway but that didn’t work either; although I use latest docker and it should work on Linux.

6. Links to relevant resources:

Most of stackoverflow answers are telling to use network in docker-compose, but none worked.

Just for reference: this is 100% for my local development, not production.

Howdy @zmitic, welcome to the Caddy community.

Can you post your Caddyfile?

1 Like

Yes, here it is:

{
    # Debug
    {$DEBUG}
    # HTTP/3 support
    servers {
        protocol {
            experimental_http3
        }
    }
}

{$SERVER_NAME}

#{$CADDY_TLS_CONFIG}

log

route {
    root * /srv/app/public
    mercure {
        # Transport to use (default to Bolt)
        transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
        # Publisher JWT key
        publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
        # Subscriber JWT key
        subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
        # Allow anonymous subscribers (double-check that it's what you want)
        anonymous
        # Enable the subscription API (double-check that it's what you want)
        subscriptions
        # Extra directives
        {$MERCURE_EXTRA_DIRECTIVES}
    }
    vulcain
    push
    php_fastcgi unix//var/run/php/php-fpm.sock
    encode zstd gzip
    file_server
}

It is the same from symfony docker, I didn’t touch anything. To start a server, I use api.localhost:80 env variable and it works from browser.

Curl: just the headers.

This environment variable is what contains your site addresses, hostnames. See the docker-compose.yml:

Make sure you override this with the hostnames you need to do what you want. If none match a request to just an IP address, then Caddy will respond with an empty response, because it was not configured to do anything otherwise.

1 Like

I start docker with this command:

SERVER_NAME="api.localhost:80" docker-compose up -d --build

Make sure you override this with the hostnames you need to do what you want

This is the part I don’t understand. What should I do? I am an absolute noob in this, both docker and caddy.

How do I tell caddy to actually execute my PHP code like if it was called from browser?

This part is already done, Caddy will proxy requests to your php-fpm container with the php_fastcgi directive.

Your issue is that Caddy is matching requests by hostname, and the request you’re making doesn’t match any of the site addresses that you configured it with.

1 Like

Is that why my caddy log says:

"host":"172.17.0.1"

which doesn’t match configured api.localhost? When I call from browser, host value is detected and everything works.

If the above is correct: is there some way to force caddy to respond to all requests? Or better; do that via docker?

Sorry for these questions but I have absolutely no idea what I am doing.

1 Like

If you set SERVER_NAME to :80, Caddy will not match on the hostname and will respond to all HTTP requests.

2 Likes

Thank you, it worked. I am using dirty http://192.168.240.1 to access it but at least it works. You really saved me lots of time.

2 Likes

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