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: https://github.com/dunglas/symfony-docker/blob/main/docker-compose.yml#L28

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?

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.

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.

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.

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

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.