Thanks for following up. I probably jumped over some key details. Here's a clearer explanation of the setup and where I'm stuck.
What I want to do
I'm working on a local Docker setup (Windows + Docker Desktop) and trying to connect Nextcloud and OpenProject via the official integration app in Nextcloud.
The idea is to enter http://openproject.lab.test
in the OpenProject integration settings in Nextcloud, and have it route correctly through Traefik, which handles all services via reverse proxy.
So the intended request path is:
Nextcloud (container) → Traefik (container) → OpenProject (container)
Both apps are on the same external Docker network (traefik-frontend
) along with Traefik.
Before introducing DNS proxy
Before trying any DNS solution, I had this setup:
- From my browser (host),
openproject.lab.test
worked fine thanks to Windows hosts
file:
127.0.0.1 openproject.lab.test
127.0.0.1 nextcloud.lab.test
- Inside Nextcloud, trying to connect to
openproject.lab.test
would fail during the integration process with a:
400 Bad Request — “There is no valid OpenProject instance at this URL”
- But the real issue seemed to be that Nextcloud was resolving the domain to itself, not OpenProject. I confirmed this by running:
curl openproject.lab.test
From within the Nextcloud container — it returned the Nextcloud login page, not OpenProject.
- So I assumed the problem was DNS resolution inside Docker: all containers were using Docker's internal resolver and couldn't resolve custom FQDNs.
After introducing defreitas/dns-proxy-server
I tried adding dns-proxy-server
as a DNS container, hoping to solve the internal resolution between containers. The proxy runs fine, and detects containers with MG_REGISTER_CONTAINER_NAMES=1
.
But since then, everything broke, including access Openproject from my browser. Even Traefik now throws:
Health check failed. error="HTTP request failed: Get "http://openproject.lab.test/login?...\": dial tcp: lookup openproject.lab.test on 127.0.0.11:53: no such host"
Files
Let me know if helpful :
traefik.yml
(static config)
global:
checkNewVersion: false
sendAnonymousUsage: false
log:
level: DEBUG
api:
dashboard: true
insecure: true
entryPoints:
web:
address: :80
websecure:
address: :443
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
network: traefik-frontend
exposedByDefault: false
Traefik
services:
reverse-proxy:
# The official v3 Traefik docker image
image: traefik:v3.4
# Enables the web UI and tells Traefik to listen to docker
#command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "80:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
- "443:443"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
networks:
- traefik-frontend
restart: unless-stopped
networks:
traefik-frontend:
external: true
Nextcloud
volumes:
nextcloud:
db:
services:
############################
# D A T A B A S E
############################
db:
image: mariadb:10.6
restart: unless-stopped
networks:
- nextcloud-internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 1m
start_interval: 10s
interval: 1m
timeout: 5s
retries: 3
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
volumes:
- "db:/var/lib/mysql"
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
############################
# A P P L I C A T I O N
############################
app:
image: nextcloud
restart: unless-stopped
networks:
- traefik-frontend
- nextcloud-internal
depends_on:
db:
condition: service_healthy
restart: true
labels:
# 1️ Active Traefik pour ce conteneur
- "traefik.enable=true"
# 2️ ROUTER – règle d’hôte + point d’entrée
- "traefik.http.routers.nextcloud.rule=Host(`${NEXTCLOUD_DOMAIN}`)"
- "traefik.http.routers.nextcloud.entrypoints=web"
# 3️ MIDDLEWARE retry (5 tentatives max si le conteneur répond 502/504)
- "traefik.http.routers.nextcloud.middlewares=retry"
- "traefik.http.middlewares.retry.retry.attempts=5"
# 4️ SERVICE – port exposé par Apache dans l’image Nextcloud
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
# 5️ HEALTH-CHECK – Traefik teste / toutes les 20 s
- "traefik.http.services.nextcloud.loadbalancer.healthcheck.path=/"
- "traefik.http.services.nextcloud.loadbalancer.healthcheck.hostname=${NEXTCLOUD_DOMAIN}"
- "traefik.http.services.nextcloud.loadbalancer.healthcheck.interval=20s"
- "traefik.http.services.nextcloud.loadbalancer.healthcheck.timeout=5s"
#ports:
# - 8080:80
volumes:
- "nextcloud:/var/www/html" # code + config (volume Docker)
- "${NEXTCLOUD_DATA_PATH}:/var/www/html/data" # fichiers utilisateurs
environment:
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_HOST=db
networks:
traefik-frontend:
external: true
nextcloud-internal:
internal: true
OpenProject
networks:
frontend:
backend:
volumes:
pgdata:
opdata:
x-op-restart-policy: &restart_policy
restart: unless-stopped
x-op-image: &image
image: openproject/openproject:${TAG:-16-slim}
x-op-app: &app
<<: [*image, *restart_policy]
environment:
OPENPROJECT_HTTPS: "${OPENPROJECT_HTTPS:-true}"
OPENPROJECT_HOST__NAME: "${OPENPROJECT_HOST__NAME:-localhost:8080}"
OPENPROJECT_HSTS: "${OPENPROJECT_HSTS:-true}"
RAILS_CACHE_STORE: "memcache"
OPENPROJECT_CACHE__MEMCACHE__SERVER: "cache:11211"
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}"
DATABASE_URL: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}?pool=20&encoding=unicode&reconnect=true"
RAILS_MIN_THREADS: ${RAILS_MIN_THREADS:-4}
RAILS_MAX_THREADS: ${RAILS_MAX_THREADS:-16}
# set to true to enable the email receiving feature. See ./docker/cron for more options
IMAP_ENABLED: "${IMAP_ENABLED:-false}"
volumes:
- "${OPDATA:-opdata}:/var/openproject/assets"
services:
db:
image: postgres:13
<<: *restart_policy
stop_grace_period: "3s"
volumes:
- "${PGDATA:-pgdata}:/var/lib/postgresql/data"
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-p4ssw0rd}
POSTGRES_DB: openproject
networks:
- backend
cache:
image: memcached
<<: *restart_policy
networks:
- backend
proxy:
build:
context: ./proxy
args:
APP_HOST: web
image: openproject/proxy
<<: *restart_policy
ports:
- "${PORT:-8080}:80"
depends_on:
- web
networks:
- frontend
web:
<<: *app
command: "./docker/prod/web"
networks:
- frontend
- backend
depends_on:
- db
- cache
- seeder
labels:
- autoheal=true
healthcheck:
test:
[
"CMD",
"curl",
"-f",
"http://localhost:8080${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}/health_checks/default",
]
interval: 10s
timeout: 3s
retries: 3
start_period: 30s
autoheal:
image: willfarrell/autoheal:1.2.0
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
environment:
AUTOHEAL_CONTAINER_LABEL: autoheal
AUTOHEAL_START_PERIOD: 600
AUTOHEAL_INTERVAL: 30
worker:
<<: *app
command: "./docker/prod/worker"
networks:
- backend
depends_on:
- db
- cache
- seeder
cron:
<<: *app
command: "./docker/prod/cron"
networks:
- backend
depends_on:
- db
- cache
- seeder
seeder:
<<: *app
command: "./docker/prod/seeder"
restart: on-failure
networks:
- backend
Openproject (Override)
services:
proxy:
profiles: ["disabled"] # Désactive le service proxy d'OpenProject
web:
networks:
- traefik-frontend
- backend
labels:
# Activation Traefik
- "traefik.enable=true"
# Route basée sur la variable .env
- "traefik.http.routers.openproject.rule=Host(`${OPENPROJECT_HOST__NAME}`)"
- "traefik.http.routers.openproject.entrypoints=web"
- "traefik.http.routers.openproject.middlewares=retry"
- "traefik.http.middlewares.retry.retry.attempts=5"
# Backend → conteneur OpenProject expose le port 8080
- "traefik.http.services.openproject.loadbalancer.server.port=8080"
# Health-check Traefik
- "traefik.http.services.openproject.loadbalancer.healthcheck.path=/"
- "traefik.http.services.openproject.loadbalancer.healthcheck.hostname=${OPENPROJECT_HOST__NAME}"
- "traefik.http.services.openproject.loadbalancer.healthcheck.interval=20s"
- "traefik.http.services.openproject.loadbalancer.healthcheck.timeout=5s"
db:
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-openproject}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-p4ssw0rd}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
start_period: 1m
start_interval: 10s
interval: 1m
timeout: 5s
retries: 3
networks:
traefik-frontend:
external: true
backend:
internal: true
DNS proxy
services:
dps:
image: defreitas/dns-proxy-server # identique au docker run
hostname: "${DPS_HOSTNAME:-dns.mageddo}"
container_name: "${CONTAINER_NAME:-dns}" # nom du conteneur
restart: unless-stopped
environment:
- MG_REGISTER_CONTAINER_NAMES=${MG_REGISTER_CONTAINER_NAMES:-1} # par défaut, oui
networks:
traefik-frontend: # réseau Traefik pour exposer le service
aliases:
- "dns"
- "${DPS_HOSTNAME:-dns.mageddo}"
# Les deux montages repris tels quels du docker run original
volumes:
- "${DOCKER_SOCK}:/var/run/docker.sock" # observe les conteneurs
- "${RESOLV_CONF}:/etc/resolv.conf" # relaie les DNS actuels
networks:
traefik-frontend:
external: true