Reverse proxy dockerized nodejs app

1. Caddy version (caddy version):

2.4.6

2. How I run Caddy:

I’m running Caddy in a container as a reverse proxy for another container in which is running a nodejs application.

a. System environment:

Docker on Ubuntu.

b. Command:

docker-compose up -d --build

c. Service/unit/compose file:

docker and docker-compose

Dockerfile of the nodejs app

# Use Node.js 14 Alpine
FROM node:14-alpine as base

WORKDIR /src
COPY package*.json ./
EXPOSE 3000

FROM base as production
ENV NODE_ENV=production
#RUN npm ci
RUN npm install --quiet
COPY . ./
CMD ["node", "server.js"]

docker-compose

version: '3.7'

services:
  node-app:
    container_name: node-app-service
    build:
      context: ./
      target: production
    volumes:
      - .:/src
      - /src/node_modules
      - /src/images
    command: npm run start
    restart: unless-stopped
    environment:
      NODE_ENV: production
    depends_on:
      - caddy
       
  caddy:
      image: caddy:alpine
      container_name: caddy-service
      restart: unless-stopped
      ports:
          - 80:80
          - 443:443
      volumes:            
          - ./caddy_data:/data
          - ./caddy_config:/config
          - ./Caddyfile:/etc/caddy/Caddyfile

d. My complete Caddyfile or JSON config:

localhost {
    reverse_proxy node-app:3000
}

3. The problem I’m having:

When I try to load some resource as images or css a 404 is returned.

i.e.,

GET https://localhost/site.webmanifest 404
GET https://localhost/images/logo.png 404
...

Does node server.js actually run a file server as well, or does it output the assets as static files?

If you need to serve static files, then you’ll need to make sure Caddy has a volume that gives it access to the files, then configure Caddy with the root + file_server directives to serve the static files, probably with a file matcher to only serve requests to files that exist on disk. Something like this:

localhost {
	encode gzip

	@staticFile file
	handle @staticFile {
		root * /srv
		file_server
	}

	handle {
		reverse_proxy node-app:3000
	}
}

Hello @francislavoie and thanks for your answer. The node application actually is a basic node express application that is serving an index.html file on the port 3000.

const express = require('express');

const app = express();
const path = require('path');

app.use((req, res, next) => {
  console.log('Time: ', Date.now());
  next();
});

app.use('/request-type', (req, res, next) => {
  console.log('Request type: ', req.method);
  next();
});

app.get('/', (req, res) => {
  //res.send('Successful response.');
  res.sendFile(path.join(__dirname, 'index.html'))
});

app.listen(3000, () => console.log('Example app is listening on port 3000.'));

This is the app tree (node_modules excluded)

projects/app-localhost
├── caddy_config
│   └── caddy 
├── caddy_data
│   └── caddy 
├── Caddyfile
├── docker-compose.yml
├── Dockerfile
├── favicon.ico
├── images
│   ├── image1.png
│   ├──image2.png
├── index.html
├── package.json
├── server.js
└── site.webmanifest

Well, the 404 comes from your node app, not from Caddy. So either adjust your node app to properly respond to requests to static files, or configure Caddy to serve the static files.

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