I made simple docker based application with NGINX, PHP, PostgreSQL, Node, Mercure and Symfony just to test the capabilities of Mercure.
The problem is that I'm not getting any updates from Symfony publisher service, there's no errors in logs, no errors in Symfony profiler, CORS is working properly. Sending updates trough mercure ui is working just fine.
I'm using latest dunglas/mercure image along with PHP 7.4 and Symfony 5.2.2
My docker-compose file:
version: '3'
networks:
backend:
services:
# nginx
nginx-service:
image: nginx:stable-alpine
container_name: nginx-container
ports:
- "8080:80"
volumes:
- ./app:/var/www/project
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php74-service
- postgres11-service
networks:
- backend
# php
php74-service:
build:
context: .
dockerfile: ./php/Dockerfile
container_name: php74-container
ports:
- "9000:9000"
volumes:
- ./app:/var/www/project
networks:
- backend
#postgres
postgres11-service:
image: postgres:11-alpine
container_name: postgres11-container
ports:
- "5432:5432"
volumes:
- ./postgres:/var/libpostgresql/data
restart: always
environment:
POSTGRES_USER: main
POSTGRES_PASSWORD: secret
networks:
- backend
# node
node-service:
image: node:latest
container_name: node-container
volumes:
- ./app:/var/www/project
working_dir: /var/www/project
networks:
- backend
# mercure
mercure:
image: dunglas/mercure:latest
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
container_name: mercure-container
ports:
- 9090:80
networks:
- backend
My Caddyfile configuration
{
# Debug mode (disable it in production!)
debug
# HTTP/3 support
experimental_http3
}
# The address of your server
localhost:80
# enable logs
log
route {
# redirect to ui
redir / /.well-known/mercure/ui/
mercure {
demo
# Publisher JWT key
publisher_jwt !ChangeMe!
# Subscriber JWT key
subscriber_jwt !ChangeMe!
cors_origins http://localhost:8080
publish_origins http://localhost:8080
anonymous
}
respond "Not Found" 404
}
My .env cofiguration of mercure: (default token with !ChangeMe! key)
MERCURE_PUBLISH_URL=http://mercure/.well-known/mercure
MERCURE_JWT_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOltdfX0.Oo0yg7y4yMa1vr_bziltxuTCqb8JVHKxp-f_FwwOim0
Symfony function:
public function push(PublisherInterface $publisher): Response
{
$update = new Update(
'test',
json_encode(['status' => 'new update'])
);
// The Publisher service is an invokable object
$publisher($update);
return new Response('published!');
}
Related
I'm new in traefik, and couldn't understand why it doesn't redirect.
I saw a lot ways how to do redirect , and this one pretty match for me, because i want, that redirect works on the all routers.
Especially I don't want to write redirect to labels of every router
docker-compose.yml
services:
traefik:
image: traefik:v2.5
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
- 8082:8082
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/custom/:/custom/:ro
- ./data/acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=letsEncrypt"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.services.traefik-traefik.loadbalancer.server.port=888"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$yTyey7a2$$CDmIjg/aratMfqENIHcQW1"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
traefik.yml
api:
dashboard: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
permanent: true
https:
address: ":443"
metrics:
address: ":8082"
metrics:
prometheus:
entryPoint: metrics
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
directory: /custom
watch: true
certificatesResolvers:
letsEncrypt:
acme:
email: postmaster#example.com
storage: acme.json
#caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
httpChallenge:
entryPoint: http
A few months ago I have configured a reverse proxy with Traefik, basically, I have an authentication server and an API. Traefik redirects the traffic toward the authentication server if the request url has the auth path prefix and toward the API if the request url has the api path prefix. Here you go all my configuration using docker-compose.yaml:
version: '3'
services:
reverse-proxy:
image: traefik:v2.5
container_name: selling-point-reverse-proxy
ports:
- 80:80
- 8080:8080
volumes:
# Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
command:
# Enables the web UI
- --api.insecure=true
# Tells Traefik to listen to docker
- --providers.docker
# Creates a new entrypoint called web
- --entrypoints.web.address=:80
# Disable container exposition
- --providers.docker.exposedByDefault=false
# Traefik matches against the container's labels to determine whether to create any route for that container
- --providers.docker.constraints=Label(`traefik.scope`,`selling-point`)
networks:
- selling-point
api:
image: selling-point-api
container_name: selling-point-api
build:
context: ./selling-point-api
labels:
# Tells Traefik where to redirect the request if the url has the specified prefix
- traefik.http.routers.api.rule=PathPrefix(`/api`)
# Attaches a middleware for forwarding the authentication
- traefik.http.routers.api.middlewares=forward-auth,latency-check
# Attaches entrypoints
- traefik.http.routers.api.entrypoints=web
# Exposes container
- traefik.enable=true
# Matcher for creating a route
- traefik.scope=selling-point
# Creates a service called selling-point-api
- traefik.http.services.selling-point-api.loadbalancer.server.port=3000
# Attach the container to a service
- traefik.http.routers.api.service=selling-point-api
# Creates circuit breaker middleware
- traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100
volumes:
- ./selling-point-api/src:/app/src
networks:
- selling-point
environment:
WAIT_HOSTS: mysql:3306
DATABASE_URL: mysql://root:huachinango#mysql:3306/selling_point
NODE_ENV: development
auth:
image: selling-point-auth
container_name: selling-point-auth
build:
context: ./selling-point-auth
labels:
# Tells Traefik where to redirect the request if the url has the specified prefix
- traefik.http.routers.auth.rule=PathPrefix(`/auth`)
# Creates a forward auth middleware
- traefik.http.middlewares.forward-auth.forwardauth.address=http://auth:3000/auth/authorize
# Attaches entrypoints
- traefik.http.routers.auth.entrypoints=web
# Exposes container
- traefik.enable=true
# Matcher for creating a route
- traefik.scope=selling-point
# Creates a service called selling-point-auth
- traefik.http.services.selling-point-auth.loadbalancer.server.port=3000
# Attach the container to a service
- traefik.http.routers.auth.service=selling-point-auth
# Attaches a circuit breaker middleware
- traefik.http.routers.auth.middlewares=latency-check
environment:
WAIT_HOSTS: mysql:3306
IGNORE_ENV_FILE: 'true'
DATABASE_URL: mysql://root:huachinango#mysql:3306/selling_point
PASSWORD_SALT: $$2b$$10$$g0OI8KtIE3j6OQqt1ZUDte
NODE_ENV: development
volumes:
- ./selling-point-auth/src:/app/src
networks:
- selling-point
mysql:
image: mysql:5
environment:
MYSQL_ROOT_PASSWORD: huachinango
MYSQL_DATABASE: selling_point
networks:
- selling-point
volumes:
- mysql-db:/var/lib/mysql
volumes:
mysql-db:
networks:
selling-point:
name: selling-point
driver: bridge
I have the following docker-compose.yml, but need to model a public/private network split where the Redis instance must only be accessible to localhost.
version: "2.2" # for compatibility, I can upgrade if needed
services:
nginx:
image: nginx
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
This seems straightforward if I needed to restrict it to being accessible only within the docker network. Consider:
version: "2.2"
services:
nginx:
image: nginx
ports:
- 8080:80
networks:
- frontend
- backend
redis:
image: redis
ports:
- 6379:6379
networks:
- backend
networks:
frontend: {}
backend:
internal: true
However our local web developers need to be able to access that Redis instance from their host machine (outside of the docker network) when they build, run, and debug locally.
Just bind the service port of redis to localhost(127.0.0.1).
Try follows...
...
redis:
image: redis
ports:
- 127.0.0.1:6379:6379
...
Run Redis Web UI called redis-commander.
Use env vars to point to the running redis.
Expose this new container & access it instead of exposing Redis container.
services:
redis:
# Do comment ports! no need to expose it
# ports:
# - 6379:6379
// ....
redis-commander:
image: rediscommander/redis-commander:latest
restart: unless-stopped
environment:
REDIS_HOST: redis:6379 # <-- 🔴 Here you point to your redis
# REDIS_PASSWORD # <- in case redis is protected with password
ports:
- "8081:8081"
Let your developers go to http://localhost:8081 and enjoy.
Find more details about that image
I've set up Traefik and Portainer on my server running Ubuntu 20.04 that is in my front room (I used this guide and this one, but didn't set up the default IP whitelist in the second tutorial as I want it to be a publicly accessible webserver). Both apps work and appear to be using HTTPS. I can manage and create containers in Portainer.
To test out my configuration, I added two containers - MySQL and Wordpress. I added in the Traefik labels from the above tutorials like when I set up Traefik, and I set the Wordpress container's domain name in Portainer, but whenever I try to access the Wordpress site at that domain, I get a Bad Gateway error (just the words 'Bad Gateway', not even a status code).
I'm not sure where I've gone wrong. Here are my configuration files:
traefik.yml:
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
version: '3'
services:
traefik:
image: traefik:v2.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.mywebsite.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=michael:$$apr1$$.m1mfSB0$$6Ypx6rfih8y.vHkNQe9rJ0"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.mywebsite.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=http"
- "traefik.http.routers.traefik-secure.service=api#internal"
networks:
proxy:
external: true
certificatesResolvers:
http:
acme:
email: me#myemail.com
storage: acme.json
httpChallenge:
entryPoint: http
config.yml:
http:
middlewares:
https-redirect:
redirectScheme:
scheme: https
docker-compose.yml:
version: '3'
services:
traefik:
image: traefik:v2.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
- ./data/config.yml:/config.yml:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.mywebsite.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=michael:$$apr1$$.m1mfSB0$$6Ypx6rfih8y.vHkNQe9rJ0"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.mywebsite.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=http"
- "traefik.http.routers.traefik-secure.service=api#internal"
networks:
proxy:
external: true
Wordpress/MySQL docker-compose.yml:
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: admin
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: wordpressdb
volumes:
- wordpress:/var/www/html
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.wordpress.entrypoints=http"
- "traefik.http.routers.wordpress.rule=Host(`myblog.com`)"
- "traefik.http.routers.wordpress.middlewares=https-redirect#file"
- "traefik.http.routers.wordpress-secure.entrypoints=https"
- "traefik.http.routers.wordpress-secure.rule=Host(`myblog.com`)"
- "traefik.http.routers.wordpress-secure.tls=true"
- "traefik.http.routers.wordpress-secure.tls.certresolver=http"
- "traefik.http.routers.wordpress-secure.service=wordpress"
- "traefik.http.services.wordpress.loadbalancer.server.port=9000"
- "traefik.docker.network=proxy"
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: username
MYSQL_PASSWORD: password
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.mysql.entrypoints=http"
- "traefik.http.routers.mysql.middlewares=https-redirect#file"
- "traefik.http.routers.mysql-secure.entrypoints=https"
- "traefik.http.routers.mysql-secure.tls=true"
- "traefik.http.routers.mysql-secure.tls.certresolver=http"
- "traefik.http.routers.mysql-secure.service=mysql"
- "traefik.http.services.mysql.loadbalancer.server.port=9000"
- "traefik.docker.network=proxy"
volumes:
wordpress:
db:
networks:
proxy:
external: true
I can provide the Portainer docker-compose.yml file too if needed, but I don't really think it's necessary. Any help here would be great!
For network connectivity between the different applications you must create the network in one of your applications. I would do that in your traefik docker-compose.yml
Meaning, that in your traefik compose file you must NOT specify the proxy network as external, because you create it internally in that application like this:
networks:
proxy:
In your Wordpress/MySQL docker-compose.yml you must specify a name for the external network like this:
networks:
proxy:
external:
name: "traefik_proxy"
When you create a new application using compose, everything in the application gets a prefix, that is the directoryname in which the compose file is placed.
Meaning the above example only works if your traefik compose file is placed in a directory named "traefik"
This should fix your issue with connectivity.
I am trying to run an ASP.NET Core 2.0 application (REDIS + RabbitMQ + NGINX) on Docker.
When I upload these containers via docker-compose, these services work and are even accessible by Windows, since they are mapped by "HostPORT: ContainerPORT".
However, when testing the App itself, .NET informs in console that it was not possible to connect to the REDIS, for example.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HLDGDJNAEB9E", Request id "0HLDGDJNAEB9E:00000001": An unhandled exception was thrown by the application.
StackExchange.Redis.RedisConnectionException: It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. SocketFailure on PING.
My docker-compose.yml:
version: '3'
services:
nginx:
build:
dockerfile: ./nginx/nginx.dockerfile
context: .
image: nginx
container_name: nginx
ports:
- "80:80"
networks:
- production-network
depends_on:
- "wordSearcherApp"
wordSearcherApp:
image: wordsearcherapplication
container_name: wordsearcherapp
build:
context: .
dockerfile: WordSearcher/Dockerfile
networks:
- production-network
ports:
- "61370"
volumes:
- repository:/repository
depends_on:
- redis
- rabbit
redis:
image: redis
container_name: redis
ports:
- "6379:6379"
networks:
- production-network
rabbit:
image: rabbitmq
container_name: rabbitmq
ports:
- "5672:5672"
- "15672:15672"
networks:
- production-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:15672"]
interval: 30s
timeout: 10s
retries: 5
networks:
production-network:
driver: bridge
volumes:
repository:
driver: local
For Connection in C#, i use this connectionString localhost:6379
How can i do this?
Thanks.
Use redis:6379 instead of localhost:6379.
Docker-Compose will use the name you've defined for a service in the docker-compose.yml file as the hostname for its container.
This is my docker-compose.yml
yml
version: '2'
services:
admin_db:
build:
context: .
dockerfile: postgres.dockerfile
args:
- DB_NAME=admin_db
- DB_USER=admin
- DB_PASSWORD=admin_pass
network_mode: "default"
admin:
build:
context: .
dockerfile: admin.dockerfile
args:
- UID=$UID
- GID=$GID
- UNAME=$UNAME
command: /bin/bash
depends_on:
- admin_db
ports:
- "8000:8000"
links:
- admin_db
network_mode: "bridge"
If with networking_mode:"bridge" I should be able to access my app (admin) on http://127.0.0.1:8000/ from localhost, but currently, I'm able to access it only on random-ip:8000 from localhost.
I'm able to http://127.0.0.1:8000/ access when networking_mode is "host", but then I'm unable to link containers.
Is there any solution to have both things ?
- linked containers
- app running on http://127.0.0.1:8000/ from localhost
If for some unknown reason normal linking doesn't work you can always create another bridged network and connect directly to that docker image. By doing that IP address of that running image will always be the same.
I would edit it like this:
version: '2'
services:
admin_db:
build:
context: .
dockerfile: postgres.dockerfile
args:
- DB_NAME=admin_db
- DB_USER=admin
- DB_PASSWORD=admin_pass
networks:
back_net:
ipv4_address: 11.0.0.2
admin:
build:
context: .
dockerfile: admin.dockerfile
args:
- UID=$UID
- GID=$GID
- UNAME=$UNAME
command: /bin/bash
depends_on:
- admin_db
ports:
- "8000:8000"
extra_hosts:
- "admin_db:11.0.0.2"
networks:
back_net:
ipv4_address: 11.0.0.3
networks:
back_net:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "false"
com.docker.network.bridge.name: "back"
ipam:
driver: default
config:
- subnet: 11.0.0.0/24
gateway: 11.0.0.1
Hope that helps.