Use one single configuration file for prod and dev environments?

1. Caddy version (caddy version):

Caddy 2.4.6 through docker (image: caddy:alpine)

2. How I run Caddy:

I use Caddy in a docker-compose file as a reverse proxy.

a. System environment:

Docker

b. Command:

docker-compose up

c. Service/unit/compose file:

docker-compose.yaml

version: '3.3'

services:
  caddy:
    image: caddy:alpine
    ports:
      - "9000:9000"
    volumes:
      - $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config

  db:
    image: postgis/postgis:13-3.2-alpine
    environment:
      - "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}"
    volumes:
      - dbdata:/var/lib/postgresql/data
      - "./db/init-scripts:/docker-entrypoint-initdb.d"
    ports:
      - "5436:5432"

  back:
    build:
      context: .
    depends_on:
      - db

volumes:
  dbdata:
  caddy_data:
  caddy_config:

docker-compose.dev.yaml

version: '3.3'

services:
  caddy:
    image: caddy:alpine
    ports:
      - "9000:9000"
    volumes:
      - $PWD/caddy/Caddyfile.dev:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - back
      - node

  node:
    image: node:17-alpine3.13
    working_dir: /frontend
#    tty: true
    command: >
      sh -c "npm ci && npm run serve-dev"
    volumes:
      - ./frontend:/frontend
      - ./frontend/node_modules:/frontend/node_modules
    ports:
      - "8000:8000"

  pgadmin:
    image: dpage/pgadmin4
    ports:
      - "8081:80"
    volumes:
      - "./db/servers.json:/pgadmin4/servers.json"
    environment:
      - "PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL}"
      - "PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD}"
    logging:
      driver: none

volumes:
  dbdata:
  caddy_data:
  caddy_config:

d. My complete Caddyfile or JSON config:

:9000 {
	handle * {
		reverse_proxy back:8000
	}

    log {
        output stdout
        level INFO
    }
}

Caddyfile.dev:

:9000 {
    handle /static/frontend/* {
		reverse_proxy node:8000
    }

	handle * {
		reverse_proxy back:8000
	}

    log {
        output stdout
        level INFO
    }
}

3. The problem Iā€™m having:

This is my first time using Caddy. I switched from NGinx mainly because I want my containers to be as small as possible and I had the feeling that NGinX was way too complex for what I wanted to do.
Also, I hear a lot of people around me using Caddy and it was the proper opportunity for me to learn using it.

Basically what Iā€™m trying to achieve is the following:

I have a DJango app which requires Javascript files compiled with Webpack.
For the production environment, this JS is compiled during the making of the container, using a multi stage build: Dockerfile Ā· improve_docker_containers Ā· champs-libres / EGERIEC / egeriec-app Ā· GitLab

I would like to also provide a development environment in a docker-compose.dev.yaml file so I can enable live-reloading and hot reloading of the JS file.

The ā€œbackā€ service is the django app, the ā€œnodeā€ service is the NodeJS running webpack in server mode (serving JS file in HTTP).

The issue is that I would like to keep the Caddy configuration very simple and working for both use cases.

Basically, what Iā€™m trying to do is:

When a request comes in Caddy:

  1. Check if the file is available on the first reverse_proxy server ā€œnodeā€ (if the reverse_proxy can be resolved), if itā€™s there, use it and skip the next options
  2. Check if the file is available on the second reverse_proxy server ā€œbackā€.

I tried many options and I end up using 2 config files:

Is there a way to configure Caddy so it only uses one single config file for both use cases?

When I run the app using:

docker-compose up

I get this issue in the log:

caddy_1  | {"level":"error","ts":1648900115.9236927,"logger":"http.log.error.log0","msg":"dial tcp: lookup node on 127.0.0.11:53: no such host","request":{"remote_addr":"172.21.0.1:34312","proto":"HTTP/1.1","method":"GET","host":"localh
ost:9000","uri":"/static/main.bundle.js","headers":{"Accept":["*/*"],"User-Agent":["curl/7.81.0"]}},"duration":0.004499837,"status":502,"err_id":"tq7b3gf47","err_trace":"reverseproxy.statusError (reverseproxy.go:886)"}

And when I run docker with:

docker-compose up -f docker-compose.yaml -f docker-compose.dev.yaml up

It works fine.

Find the repository here: Files Ā· improve_docker_containers Ā· champs-libres / EGERIEC / egeriec-app Ā· GitLab

Thanks.

You can use import for snippets, and environment variables to do it.

For example:

(frontend) {
	handle /static/frontend/* {
		reverse_proxy node:8000
	}
}

:9000 {
	{$CADDY_EXTRA_DIRECTIVES}

	handle {
		reverse_proxy back:8000
	}

	log
}

Then in your docker-compose config and/or in a .env file, you can put this:

CADDY_EXTRA_DIRECTIVES="import frontend"

And you may leave that environment variable empty if you donā€™t want the frontend handler to be loaded in the config.

Read about env in docker-compose: Environment variables in Compose | Docker Documentation

See the Caddy docs for snippets and environment variables

3 Likes

Amazing, thanks for you amazing support and piece of software !!!

1 Like

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