basecamp / kamal

Deploy web apps anywhere.
https://kamal-deploy.org
MIT License
10.66k stars 410 forks source link

Bad Gateway for 'Caddy' Dockerfile #718

Closed ksylvest closed 4 months ago

ksylvest commented 7 months ago

I'm attempting to use Caddy to host some static HTML / files, but running into issues 'Bad Gateway' on every request.

This is the Dockerfile / Caddyfile being used:

# syntax = docker/dockerfile:1

FROM caddy:2.7.6

RUN apk --no-cache add curl

COPY Caddyfile /etc/caddy/Caddyfile

EXPOSE 4567
:4567

respond "Hello!"

Locally the image appears to build / run just fine:

docker build -t test . && docker run -t -p 4567:4567 test
curl localhost:4567 # Hello
curl localhost:4567/up # Hello

Deploying the image passes all health checks as expected:

kamal deploy
...
  INFO [34aad7e6] Running docker container ls --all --filter name=^frontend-web-...$ --quiet | xargs docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' on ...
  INFO [34aad7e6] Finished in 0.191 seconds with exit status 0 (successful).
  INFO Container is healthy!
...
Releasing the deploy lock...
  Finished all in 37.2 seconds

Attempting to access the service through Traefik fails (even when connected via SSH to the host) with 'Bad Gateway':

curl localhost:80 # Bad Gateway

If I run docker ps then grab the container IP I am able to curl and get back the result from Caddy:

docker ps
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 123...
curl 172.17.0.3:4567 # Hello

Swapping over to a very basic Sinatra app instead of a Caddy image and the deploys works fine. It seems to for some reason be tied to using a caddy image.

wenderjean commented 6 months ago

How does your deploy.yml look like?

ksylvest commented 6 months ago

Hi Wender,

I'm using the following:

service: frontend
image: REDACTED

registry:
  username: REDACTED
  password:
    - KAMAL_REGISTRY_PASSWORD

ssh:
  user: REDACTED

servers:
  web:
    hosts:
      - REDACTED
    labels:
      traefik.http.routers.frontend.rule: Host(`REDACTED`)
      traefik.http.routers.frontend.entrypoints: websecure
      traefik.http.routers.frontend.tls.certresolver: letsencrypt

healthcheck:
  port: 4567

traefik:
  options:
    publish:
      - "443:443"
    volume:
      - "/letsencrypt/acme.json:/letsencrypt/acme.json"
  args:
    entryPoints.web.address: ":80"
    entryPoints.websecure.address: ":443"
    entryPoints.web.http.redirections.entryPoint.to: websecure
    entryPoints.web.http.redirections.entryPoint.scheme: https
    entryPoints.web.http.redirections.entrypoint.permanent: true
    certificatesResolvers.letsencrypt.acme.email: "REDACTED"
    certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
    certificatesResolvers.letsencrypt.acme.httpchallenge: true
    certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web

Just as a callout, changing to run on port 80 (via Dockerfile / Caddyfile / healthcheck swap) is a workaround for the above issue. Very puzzled why though...

djmb commented 5 months ago

@ksylvest - there might be something useful in the Traefik container's logs (run docker logs traefik)