DDEV not serving Symfony Mercure-Hub over HTTPS - docker

I am running a Symfony Project via drud/ddev (nginx) for local development.
I did this many times before and had no issues whatsoever.
In my recent project I have to use the Mercure-Hub to push Notifications from the server to the client.
I required the symfony/mercure-bundle via composer and copied the generated docker-compose content into a docker-compose.mercure.yaml (.ddev/docker-compose.mercure.yaml)
After starting the container the Mercure-Hub works seamlessly but is only reachable over http.
My problem: I only have beginner knowledge in the field of nginx and docker-compose.
I am thankful for every bit of advice! :)
Steps to reproduce
Setup basic Symfony Project and run it via DDEV.
Require symfony/mercure-bundle.
Copy docker-compose.yaml and docker-compose.override.yaml content to a docker-compose.mercure.yaml in the .ddev folder (change the port).
Configure Mercure-Hub URL in .env.
Start the container and visit [DDEV-URL]:[MERCURE-PORT] / subscribe a Mercure topic.
My problem
Mercure-Hub only reachable via http.
HTTPS call gets an 'ERR_SSL_PROTOCOL_ERROR'
My wish
Access the Mercure-Hub URL / subscribe to Mercure topics via HTTPS.
What I've tried
Reading the Mercure-Hub Docs and trying to adapt the Docker SSL / HTTPS instructions to my local drud/ddev environment
Adding another server to the nginx configuration as in the Mercure-Cookbook "Using NGINX as an HTTP/2 Reverse Proxy in Front of the Hub"
Googling a bunch
Hours of trial and error
Files
ddev config.yaml
name: project-name
type: php
docroot: public
php_version: "8.1"
webserver_type: nginx-fpm
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: true
additional_hostnames: []
additional_fqdns: []
database:
type: mariadb
version: "10.4"
nfs_mount_enabled: true
mutagen_enabled: false
use_dns_when_possible: true
composer_version: "2"
web_environment: []
nodejs_version: "16"
docker-compose.mercure.yaml
version: '3'
services:
###> symfony/mercure-bundle ###
mercure:
image: dunglas/mercure
restart: unless-stopped
environment:
SERVER_NAME: ':3000'
MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
# Set the URL of your Symfony project (without trailing slash!) as value of the cors_origins directive
MERCURE_EXTRA_DIRECTIVES: |
cors_origins http://127.0.0.1:8000
# Comment the following line to disable the development mode
command: /usr/bin/caddy run -config /etc/caddy/Caddyfile.dev
volumes:
- mercure_data:/data
- mercure_config:/config
ports:
- "3000:3000"
###< symfony/mercure-bundle ###
volumes:
###> symfony/mercure-bundle ###
mercure_data:
mercure_config:
###< symfony/mercure-bundle ###
.env
###> symfony/mercure-bundle ###
# See https://symfony.com/doc/current/mercure.html#configuration
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
MERCURE_URL=http://ddev-pnp-master-mercure-1:3000/.well-known/mercure
# The public URL of the Mercure hub, used by the browser to connect
MERCURE_PUBLIC_URL=http://ddev-pnp-master-mercure-1:3000/.well-known/mercure
# The secret used to sign the JWTs
MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
###< symfony/mercure-bundle ###
Edit 1
I changed my docker-compose thanks to the advice from rfay.
(only showing the relevant part below)
[...]
services:
mercure:
image: dunglas/mercure
restart: unless-stopped
expose:
- "3000"
environment:
- SERVER_NAME=":3000"
- HTTP_EXPOSE=9998:3000
- HTTPS_EXPOSE=9999:3000
[...]
replaced ports with expose
added HTTP_EXPOSE & HTTPS_EXPOSE
Problem with this
Now my problem is that the container doesn't expose any ports (see docker desktop screenshot below).
docker desktop port screenshot

Solution
With the help of rfay I found the solution (which consisted of reading the ddev documentation properly lol).
What I did
replacing ports with expose
adding VIRTUAL_HOST, HTTP_EXPOSE and HTTPS_EXPOSE under environment
adding container_name & labels (see code below)
My final docker-compose.mercure.yaml
version: '3'
services:
mercure:
image: dunglas/mercure
restart: unless-stopped
container_name: "ddev-${DDEV_SITENAME}-mercure-hub"
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: ${DDEV_APPROOT}
expose:
- "3000"
environment:
VIRTUAL_HOST: $DDEV_HOSTNAME
SERVER_NAME: ":3000"
HTTP_EXPOSE: "9998:3000"
HTTPS_EXPOSE: "9999:3000"
MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
MERCURE_EXTRA_DIRECTIVES: |
cors_origins https://project-name.ddev.site
# Comment the following line to disable the development mode
command: /usr/bin/caddy run -config /etc/caddy/Caddyfile.dev
volumes:
- mercure_data:/data
- mercure_config:/config
volumes:
mercure_data:
mercure_config:
With this docker-compose in place my mercure container is available via HTTPS over the port 9999.
For further information see the ddev documentation: https://ddev.readthedocs.io/en/latest/users/extend/custom-compose-files/#docker-composeyaml-examples

The solution in https://stackoverflow.com/a/74735903/21252828 does not work until you add a minus before the config option at the command:
...
command: /usr/bin/caddy run --config /etc/caddy/Caddyfile.dev
...
Otherwise the container fails (and restarts endless).
Maybe you can edit your post Christian Neugebauer?

Related

Can't access web container from outside (Windows Docker-Desktop)

i'm using Docker-Desktop on Windows and i'm trying to get running 3 containers inside docker-desktop.
After few research and test, i get the 3 container running [WEB - API - DB], everything seems to compile/run without issue in the logs but i'can't access my web container from outside.
Here's my dockerfile and docker-compose, what did i miss or get wrong ?
[WEB] dockerfile
FROM node:16.17.0-bullseye-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
CMD ["npm", "run", "start"]
[API] dockerfile
FROM openjdk:17.0.1-jdk-slim
WORKDIR /app
COPY ./target/test-0.0.1-SNAPSHOT.jar /app
#EXPOSE 2022 (the issue is the same with or without this line)
CMD ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
Docker-compose file
version: "3.8"
services:
### FRONTEND ###
web:
container_name: wallet-web
restart: always
build: ./frontend
ports:
- "80:4200"
depends_on:
- "api"
networks:
customnetwork:
ipv4_address: 172.20.0.12
#networks:
# - "api"
# - "web"
### BACKEND ###
api:
container_name: wallet-api
restart: always
build: ./backend
ports:
- "2022:2022"
depends_on:
- "db"
networks:
customnetwork:
ipv4_address: 172.20.0.11
#networks:
# - "api"
# - "web"
### DATABASE ###
db:
container_name: wallet-db
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
customnetwork:
ipv4_address: 172.20.0.10
#networks:
# - "api"
# - "web"
networks:
customnetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# api:
# web:
Listening on:
enter image description here
I found several issue similar to mine but the solution didn't worked for me.
If i understand you are trying to access on port 80. To do that, you have to map your container port 4200 to 80 in yaml file 80:4200 instead of 4200:4200.
https://docs.docker.com/config/containers/container-networking/
Have you looked in the browsers development console, if there comes any error. Your docker-compose seems not to have any issue.
How ever lets try to debug it:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6245eaffd67e nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:4200->80/tcp test-api-1
copy the container id then execute:
docker exec -it 6245eaffd67e bin/bash
Now you are inside the container. Instead of the id you can use also the containers name.
curl http://localhost:80
Note: in my case here i just create a container from an nginx image.
In your case use the port where your app is running. Control it in your code if you arent sure. A lot of Javascript-frameworks start default on 3000.
If you get an error: curl command not found, install it in your image:
FROM node:16.17.0-bullseye-slim
USER root # to install dependencies you need sudo permissions su we tell the image that it is root
RUN apt update -y && apt install curl -y
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
USER node # we dont want to execute the image as root so we put user node (this user is defined in the node:16.17.0-bullseye-slim image)
CMD ["npm", "run", "start"]
Now the curl should work (if it doesnt already).
The same should work from your host.
Here is an important thing:
The localhost, always refers to the fisical computer, or the container itselfs where you are refering. Every container and your PC have localhost and they are not the same.
In the docker-compose you just map the port host/container, so your PC (host) where docker is running can access the docker network from the host on the host port you defined, inside the port of the container.
If you cant still access from your host, try to change the host ports 2022, 4200 ecc. Could be possible that something conflicts on your Windows machine.
It happens sometimes that the docker networks can create some conflicts.
Execute a docker-compose down, so it should be delete and recreated.
Still not working?
Reset docker-desktop to factory settings, control if you have last version (this is always better).
If all this doesnt help, let me know so we can debugg further.
For the sake of clarity i post you here the docker-compose which i used to check. I just used nginx to test the ports as i dont have your images.
version: "3.8"
services:
### FRONTEND ###
web:
restart: always
image: nginx
ports:
- "4200:80"
depends_on:
- "api"
networks:
- "web"
### BACKEND ###
api:
restart: always
image: nginx
ports:
- "2022:80"
depends_on:
- "db"
networks:
- "api"
- "web"
### DATABASE ###
db:
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
- "api"
networks:
api:
web:
```
Update:
You can log what happens in the conatiner like so:
```
docker logs containerid/name
```
If you are using Visualcode there is excellent extension for docker build also by Microsoft:
Just search docker in the extensions. Has something like 20.000.000 downloads and can help you a lot debugging containers ecc. After installing it you see the dockericon on the left toolbar.
If you can see directly the errors that occurs in the logs, maybe you can post them partially. So it would be possible to understand. Please tell also something about your Frontendapp architecture, (react-app, angular). There are some frameworks that need to be startet on 0.0.0.0 instead of 127.0.0.1 or they dont work.

Api-platform docker deployment behind nginx-proxy

I'm trying to deploy a quick demo of api-platform.
In advance, my apologize if I missed something in a discssion or a documentation, I'm not used to work on deployment and maybe not looking at the right places.
I use a server where I already have some docker containers running, for that I use nginxproxy/nginx-proxy docker container as reverse proxy.
I looked at the api-platofrm documentation on how to deploy with docker-compose : https://api-platform.com/docs/deployment/docker-compose/#deploying but since I'm working on this subject I evolve between "502 bad gateway" or "The page is not redirected correctly" errors.
Actually I've got this docker-compose.yml :
version: "3.4"
services:
php:
build:
context: ./api
target: api_platform_php
depends_on:
- database
restart: unless-stopped
volumes:
- php_socket:/var/run/php
healthcheck:
interval: 10s
timeout: 3s
retries: 3
start_period: 30s
networks:
- 'cloud'
caddy:
build:
context: api/
target: api_platform_caddy
depends_on:
- php
environment:
PWA_UPSTREAM: pwa:3000
SERVER_NAME: ${SERVER_NAME:-localhost, caddy:80}
MERCURE_PUBLISHER_JWT_KEY: ${MERCURE_PUBLISHER_JWT_KEY:-!ChangeMe!}
MERCURE_SUBSCRIBER_JWT_KEY: ${MERCURE_SUBSCRIBER_JWT_KEY:-!ChangeMe!}
restart: unless-stopped
volumes:
- php_socket:/var/run/php
- caddy_data:/data
- caddy_config:/config
ports:
# HTTP
- target: 80
published: 7000
protocol: tcp
# HTTPS
- target: 443
published: 7001
protocol: tcp
# HTTP/3
- target: 443
published: 7001
protocol: udp
networks:
- 'cloud'
database:
image: postgres:13-alpine
environment:
- POSTGRES_DB=api
- POSTGRES_PASSWORD=!ChangeMe!
- POSTGRES_USER=api-platform
volumes:
- db_data:/var/lib/postgresql/data:rw
# you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
# - ./api/docker/db/data:/var/lib/postgresql/data:rw
networks:
- 'cloud'
volumes:
php_socket:
db_data:
caddy_data:
caddy_config:
networks:
cloud:
external: true
and this docker-compose.preprod.yml file :
version: "3.4"
# Preproduction environment override
services:
php:
environment:
APP_ENV: prod
APP_SECRET: ${APP_SECRET}
caddy:
environment:
MERCURE_PUBLISHER_JWT_KEY: ${MERCURE_PUBLISHER_JWT_KEY:-!ChangeMe!}
MERCURE_SUBSCRIBER_JWT_KEY: ${MERCURE_SUBSCRIBER_JWT_KEY:-!ChangeMe!}
VIRTUAL_HOST: api-preprod.melofeel.com
VIRTUAL_PORT: 80
LETSENCRYPT_HOST: api-preprod.melofeel.com
I'm deploying it with gitlab-ci and launching it with this command :
SERVER_NAME=******.*****.com APP_SECRET=testdeploy POSTGRES_PASSWORD=testdeploy CADDY_MERCURE_JWT_SECRET=testdeploy docker-compose -f api_preprod/docker-compose.yml -f api_preprod/docker-compose.preprod.yml up -d
I've tried to run it with and without Caddy, without I always get "502 bad gateway".
The 3 containers are running, but when I look on Caddy logs I've got this messages :
{"level":"error","ts":1648201680.3190682,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"*****.*****.com","challenge_type":"http-01","problem":{"type":"urn:ietf:params:acme:error:unauthorized","title":"","detail":"Invalid response from http://*****.*****.com/.well-known/acme-challenge/O9zJRdytI8vlf7yZLRcV9pzUlmI73ysCqQJTHg8XWTw [188.165.218.39]: 404","instance":"","subproblems":[]}}
I've tried to deactivate the automatic https from caddy, nginx-proxy is already responsible for doing it, but it's seems to not work.
My Caddyfile :
{
# Debug
{$DEBUG}
# HTTP/3 support
servers {
protocol {
experimental_http3
},
auto_https disable_redirects
}
}
{$SERVER_NAME}
log
# Matches requests for HTML documents, for static files and for Next.js files,
# except for known API paths and paths with extensions handled by API Platform
#pwa expression `(
{header.Accept}.matches("\\btext/html\\b")
&& !{path}.matches("(?i)(?:^/docs|^/graphql|^/bundles/|^/_profiler|^/_wdt|\\.(?:json|html$|csv$|ya?ml$|xml$))")
)
|| {path} == "/favicon.ico"
|| {path} == "/manifest.json"
|| {path} == "/robots.txt"
|| {path}.startsWith("/_next")
|| {path}.startsWith("/sitemap")`
route {
root * /srv/api/public
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
# Allow anonymous subscribers (double-check that it's what you want)
anonymous
# Enable the subscription API (double-check that it's what you want)
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
vulcain
push
# Add links to the API docs and to the Mercure Hub if not set explicitly (e.g. the PWA)
header ?Link `</docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation", </.well-known/mercure>; rel="mercure"`
# Comment the following line if you don't want Next.js to catch requests for HTML documents.
# In this case, they will be handled by the PHP app.
reverse_proxy #pwa http://{$PWA_UPSTREAM}
php_fastcgi unix//var/run/php/php-fpm.sock
encode zstd gzip
file_server
}
Thanks in advance for any help and explanation that allow me to understand what the problem is.
I managed to get it working by changing the caddy server name to
SERVER_NAME: ${SERVER_NAME:-localhost, caddy}:80
Then in Nginx Proxy redirect it to the IP over http to port 80 with a HTTPS certificate etc but I've found this breaks Vulcain for preloading fetch requests with the following error
A preload for '<URL>' is found, but is not used because the request credentials mode does not match. Consider taking a look at crossorigin attribute.
I haven't manage to fix it yet and can confirm my setup works when I point my DNS record directly to the Server running the docker as opposed to Nginx-Proxy

how to run ory/hydra on docker with custom config hyda.yaml file

How to run ory/hydra as docker container with a custom configuration file.
Is it the best way to run or providing environment variable is better.
Need help!!
I use a dockerfile with this content:
FROM oryd/hydra:latest
COPY hydra.yml /home/ory/.hydra
COPY hydra.yml /.hydra
EXPOSE 4444 4445 5555
only one copy is needed but i never know which :)
you can run with env. variables as well, but I prefer the yaml, it's easier
Apart from the solution mentioned above, you can also try Docker Compose. Personally, I prefer this as I find it easy to follow and manage.
The official 5-minute tutorial also uses Docker Compose which can be found here: https://www.ory.sh/hydra/docs/5min-tutorial/
I am using PostgreSQL as the database here but you can replace it with any other of the supported databases such as MySQL.
More information about supported Database configurations are here: https://www.ory.sh/hydra/docs/dependencies-environment/#database-configuration
First, you create docker-compose.yml like below and then just docker-compose up
version: '3.7'
networks:
intranet:
driver: bridge
services:
hydra-migrate:
depends_on:
- auth-db
container_name: hydra-migrate
image: oryd/hydra:v1.10.6
environment:
- DSN=postgres://auth:secret#auth-db:5432/auth?sslmode=disable&max_conns=20&max_idle_conns=4
command: migrate sql -e --yes
networks:
- intranet
hydra:
container_name: hydra
image: oryd/hydra:v1.10.6
depends_on:
- auth-db
- hydra-migrate
ports:
- "4444:4444" # Public port
- "4445:4445" # Admin port
- "5555:5555" # Port for hydra token user
command:
serve -c /etc/hydra/config/hydra.yml all --dangerous-force-http
restart: on-failure
networks:
- intranet
volumes:
- type: bind
source: ./config
target: /etc/hydra/config
auth-db:
image: postgres:alpine
container_name: auth-db
ports:
- "5432:5432"
environment:
- POSTGRES_USER=auth
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=auth
networks:
- intranet
hydra-migrate service takes care of the database migrations and we don't actually need to specify an external configuration file for this and just the DSN as an environment variable would suffice.
hydra service starts up the hydra container and here I have done a volume mount where I have bound my local config folder to /etc/hydra/config within the container.
And then when the container spins up the following command is executed
serve -c /etc/hydra/config/hydra.yml all --dangerous-force-http which uses the bound config file.
And here is how my hydra config file looks like:
## ORY Hydra Configuration
version: v1.10.6
serve:
public:
cors:
enabled: true
dsn: postgres://auth:secret#auth-db:5432/auth?sslmode=disable&max_conns=20&max_idle_conns=4
oidc:
subject_identifiers:
supported_types:
- public
- pairwise
pairwise:
salt: youReallyNeedToChangeThis
urls:
login: http://localhost:4455/auth/login
consent: http://localhost:4455/auth/consent
logout: http://localhost:4455/consent
error: http://localhost:4455/error
post_logout_redirect: http://localhost:3000/
self:
public: http://localhost:4444/
issuer: http://localhost:4444/
ttl:
access_token: 1h
refresh_token: 1h
id_token: 1h
auth_code: 1h
oauth2:
expose_internal_errors: true
secrets:
cookie:
- youReallyNeedToChangeThis
system:
- youReallyNeedToChangeThis
log:
leak_sensitive_values: true
format: json
level: debug

How to connect frontend to backend via docker-compose networks

I'm trying to dockerize my angular + express application. I have a docker-compose file that creates the two containers, and I am able to hit the containers from my host machine(using my browser), but I'll just get a "ERR_NAME_NOT_RESOLVED" whenever I try to hit the backend from http requests made by my frontend.
I've looked up the issue, and it seems like most suggest that the service name and container port should be enough to hit the the other container when they're on the same network. I've tried to hit "http://express:8000/user?user=030f0e70-9a8f-11e9-b5d1-f5cb6c0f3616" which I think should work given what I've seen from other places, but regardless, I get the same error.
My docker-compose file looks like
version: '3' # specify docker-compose version
# Define the services/containers to be run
services:
angular: # name of the first service
build: ./ # specify the directory of the Dockerfile
ports:
- "4200:80" # specify port forewarding
links:
- "express"
depends_on:
- "express"
express: #name of the second service
build: # specify the directory of the Dockerfile
context: ./
dockerfile: dockerfile.be
ports:
- "8000:8000" #specify ports forewarding
expose:
- "8000"
Ideally, I'd like my frontend to be able to hit the other container with a set endpoint, so I could deploy the application with minimal changes. I'd appreciate any advice. I feel like I'm missing something really simple, but after a few hours of tinkering, I still haven't caught it.
Thanks!
In fact your traffic is as next:
User browser request page from angular container, then all pages will rendered to user's browser.
The front javascript code using angular HttpClient to fetch the data from express container.
At that time, although docker-compose setup a customized network for you which afford auto-dns to resolve angular & express, but this dns just works among containers, not effect for host.
But, your augular HttpClient which call http://express was happened on user's browser which not in container, so the auto-dns defintly not work for you to resolve the name express.
For you, if you just want to open browser from your docker host, you can use localhost, but if you also want the user from other machine to visit your web, you had to use the ip of your dockerhost.
Then, in angular HttpClient you need to use something like http://your_dockerhost_ip:8000 to visit express container.
If interested, you can visit this to see User-defined bridges provide automatic DNS resolution between containers.
A few things:
By using expose, you are making the container's published ports only available to linked/networked services. This is one reason why you are unable to access it locally.
Instead of hitting http://express:8000/ you should try to hit http://localhost:8000. The service is being published to your localhost system and is not being served by anything by default (e.g., IIS, NGINX).
Add a custom defined network in your compose file instead of using links. This is now the main way to network containers together:
version: '3' # specify docker-compose version
services:
angular: # name of the first service
build: ./ # specify the directory of the Dockerfile
ports:
- "4200:80" # maps port 4200 on localhost to 80 in container
network:
- mynetwork
depends_on:
- "express"
express: # name of the second service
build: # specify the directory of the Dockerfile
context: ./
dockerfile: dockerfile.be
ports:
- "8000:8000" # maps port 8000 on localhost to 8000 in container
networks:
- mynetwork
networks:
mynetwork:
2: https://docs.docker.com/compose/compose-file/#expose
**sample docker-compose.yaml**
version: '3.5'
services:
angular:
image: "angular-alpine:0.0.1"
container_name: angular
tty: true
stdin_open: true
networks:
app_net:
ipv4_address: 172.16.238.05
depends_on:
- express
express:
image: "express:0.0.1"
container_name: express
tty: true
stdin_open: true
networks:
app_net:
ipv4_address: 172.16.238.10
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.16.238.0/24
>"1. Angular will run on 172.16.238.05:4200 and express will run on 172.16.238.10:some-port.
2. modify your config.ts or parameter.ts or anyfile where you configure express url into 172.16.238.10:some-port. now your angular will connect to express."

How to set custom IP for Solr server from Docker compose file?

In short:
I have a hard time figuring out how to set custom IP for a Solr container from the docker-compose.yml file.
Detailed
We want to deploy local dev environments, for Drupal instances, via Docker.
The propblem is, that while from the browser I can access the Solr server via the "traditional" http://localhost:8983/solr, Drupal cannot connect to it this way. The internal 0.0.0.0, and 127.0.0.1 doesn't work either. The only way Drupal can connect to the Solr server is via lan IP, which differs for every station obviously, and since the configuration in Drupal needs to be updated anyway, I thought that specifying a custom IP on which they can communicate would be my best choice, but it's not straightforward.
I am aware that assigning static IP to the container is not the best solution, but it seems more feasible than tinkering with solr.in.sh, and if someone has a different approach to achieve this, I am opened to solutions.
Most likely I could use some command line parameter along with docker run, but we need to run the containers with docker-compose up -d, so this wouldn't be an optimal solution.
Ideal would be a Solr container section example for the compose file. Thanks.
Note:
This link shows an example how to set it, but I can't understand it well. Please keep in mind that I am by no means an expert.
Forgot to mention that the host is based on Linux, mostly Ubuntu and Debian.
Edit:
As requested, here is my compose file:
version: "2"
services:
db:
image: wodby/drupal-mariadb
environment:
MYSQL_RANDOM_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
# command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # The simple way to override the mariadb config.
volumes:
- ./data/mysql:/var/lib/mysql
- ./docker-runtime/mariadb-init:/docker-entrypoint-initdb.d # Place init .sql file(s) here.
php:
image: wodby/drupal-php:7.0 # Allowed: 7.0, 5.6.
environment:
DEPLOY_ENV: dev
PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S mailhog:1025
PHP_XDEBUG_ENABLED: 1 # Set 1 to enable.
# PHP_SITE_NAME: dev
# PHP_HOST_NAME: localhost:8000
# PHP_DOCROOT: public # Relative path inside the /var/www/html/ directory.
# PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S mailhog:1025
# PHP_XDEBUG_ENABLED: 1
# PHP_XDEBUG_AUTOSTART: 1
# PHP_XDEBUG_REMOTE_CONNECT_BACK: 0 # This is needed to respect remote.host setting bellow
# PHP_XDEBUG_REMOTE_HOST: "10.254.254.254" # You will also need to 'sudo ifconfig lo0 alias 10.254.254.254'
links:
- db
volumes:
- ./docroot:/var/www/html
nginx:
image: wodby/drupal-nginx
hostname: testing
environment:
# NGINX_SERVER_NAME: localhost
NGINX_UPSTREAM_NAME: php
# NGINX_DOCROOT: public # Relative path inside the /var/www/html/ directory.
DRUPAL_VERSION: 7 # Allowed: 7, 8.
volumes_from:
- php
ports:
- "${PORT_WEB}:80"
pma:
image: phpmyadmin/phpmyadmin
environment:
PMA_HOST: db
PMA_USER: ${MYSQL_USER}
PMA_PASSWORD: ${MYSQL_PASSWORD}
ports:
- '${PORT_PMA}:80'
links:
- db
mailhog:
image: mailhog/mailhog
ports:
- "8002:8025"
redis:
image: redis:3.2-alpine
# memcached:
# image: memcached:1.4-alpine
# memcached-admin:
# image: phynias/phpmemcachedadmin
# ports:
# - "8006:80"
solr:
image: makuk66/docker-solr:4.10.3
volumes:
- ./docker-runtime/solr:/opt/solr/server/solr/mycores
# entrypoint:
# - docker-entrypoint.sh
# - solr-precreate
ports:
- "8983:8983"
# varnish:
# image: wodby/drupal-varnish
# depends_on:
# - nginx
# environment:
# VARNISH_SECRET: secret
# VARNISH_BACKEND_HOST: nginx
# VARNISH_BACKEND_PORT: 80
# VARNISH_MEMORY_SIZE: 256M
# VARNISH_STORAGE_SIZE: 1024M
# ports:
# - "8004:6081" # HTTP Proxy
# - "8005:6082" # Control terminal
# sshd:
# image: wodby/drupal-sshd
# environment:
# SSH_PUB_KEY: "ssh-rsa ..."
# volumes_from:
# - php
# ports:
# - "8006:22"
A docker run example would be
IP_ADDRESS=$(hostname -I)
docker run -d -p 8983:8983 solr bin/solr start -h ${IP_ADDRESS} -p 8983
Instead of assigning static IPs, you could use the following method to get the container's IP dynamically.
When you link containers together, they share there network information (IP, port) to each other. The information is stored in each container as environmental variables.
Example
docker-compose.yml
service:
build: .
links:
- redis
ports:
- "3001:3001"
redis:
build: .
ports:
- "6369:6369"
The service container will now have the following environmental variables:
Dynamic IP Address Stored Within "service" container:
REDIS_PORT_6379_TCP_ADDR
Dynamic PORT Stored Within "service" container:
REDIS_PORT_6379_TCP_PORT
You can always check this out by shelling into the container and looking yourself.
docker exec -it [ContainerID] bash
printenv
Inside your nodeJS app you can use the environmental variable in your connection function by using process.env.
let client = redis.createClient({
port: process.env.REDIS_PORT_6379_TCP_ADDR,
host: process.env.REDIS_PORT_6379_TCP_PORT
});
Edit
Here is the updated docker-compose.yml "solr" section:
solr:
image: makuk66/docker-solr:4.10.3
volumes:
- ./docker-runtime/solr:/opt/solr/server/solr/mycores
entrypoint:
- docker-entrypoint.sh
- solr-precreate
ports:
- "8983:8983"
links:
- db
In the above example the "solr" container is now linked with the "db" container. this is done using the "links" field.
You can do the same thing if you wanted to link the solr container to any other container within the docker-compose.yml file.
The db containers information will now be available to the solr container (via the enviromental variables I mentioned earlier).
Without the linking, you will not see those enviromental variables listed when you do the printenv command.

Resources