Making requests to external host on Docker container - vpn

I am trying to connect to a database that has an IP of x.x.x.x from my Docker container
Getting this error
java.net.NoRouteToHostException: No route to host (Host unreachable)
Tried running container using --network=host which has a similar approach to the above attempt

As I mentioned in the comments, here is the sample docker-compose file.
version: '3.7'
services:
entitygraph:
image: entitygraph-by-jar:latest
container_name: entitygraph
restart: always
networks:
- eg-net
ports:
- 9999:8080
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://eg-mysql/customers?useSSL=false
SPRING_PROFILES_ACTIVE: mysql
eg-mysql:
image: mysql:5.7
restart: always
networks:
- eg-net
container_name: eg-mysql
environment:
MYSQL_DATABASE: customers
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_ROOT_PASSWORD:
networks:
eg-net:
name: eg-net
In this file, the application entitygraph is trying to talk to mysql. In my application, the connection string to mysql is as below,
spring.datasource.url=jdbc:mysql://localhost:3306/customers?useSSL=false
So, docker will replace the spring.datasource.url property with the one I specified on my docker-compose file. Note that host:port is eg-mysql, which docker resolves to it's internal IP and will use it to communicate.
I don't know about your application architecture. If I know, I could give you more specific answer to your problem.

Related

Bad Gateway for WordPress containers behind Traefik reverse proxy in docker-compose

Firstly, I'd like to say that I'm not a server admin. I'm a web programmer tasked with setting up a development server and I have no idea what I'm doing. I may not be doing things according to best practice or the way you might do them. Unfortunately, with Traefik, there are 3 ways to do everything and so 2/3 of the answers that I've come across aren't compatible with my implementation and I can't figure out how to make them work. Furthermore, this isn't my only (or even primary) job duty.
Here's the setup:
Single-server docker environment on a Linode server with Ubuntu 20.04
I have one stack with Traefik, Traefik Hub, Portainer, and WhoAmI configured and working (mostly) correctly. I don't have the DNS challenge working right with Let's Encrypt, but I don't really care about that at this point. I don't really need a wildcard certificate.
I created a mariadb container. We're mostly a WordPress shop and I'd like to have one container for all the databases we work with rather than configuring a database on an environment-by-environment basis.
I created an external bridge network, named "maverick-net" and all of the stacks are connected to it.
I have a self-hosted GitHub runner listening for changes to the "dev" branch of the project. The runner pulls down the latest repo, writes GitHub secrets to a local .env file, runs composer install and then docker-compose up -d. (That's the reason behind the obscenely-long bind mount paths.)
I'm trying to make the code for these WordPress projects reusable as much as possible, so there's a lot of .env variables in the different files. At some point I'll probably move those over to docker secrets, but at this point it's a development server and not as critical.
My issue is that I haven't been able to get a WordPress site up and running, and I keep hitting a "Bad Gateway" error. When I curl the URL from inside the traefik container, I get... wait for it... "Bad Gateway."
Clearly there's something I'm missing, but I've been slamming my head against a brick wall for weeks trying different approaches to get this running and I need help. There has to be something I'm not getting about docker networks in general because my wp-cli container never has been able to connect to the database, regardless of whether I start it in the same stack or if i try to connect to it on the maverick-net network.
My traefik stack (side note, I'd really like to split these command entries into static and dynamic config files, but that's a task for another day):
version: "3.9"
secrets:
linode_token:
file: "../secrets/linode_token.secret"
services:
traefik:
container_name: traefik
image: "traefik:latest"
command:
- --log.level=DEBUG
- --log.filePath=./traefik.log
- --accessLog=true
- --accessLog.filePath=./access.log
- --accessLog.bufferingSize=100
- --accessLog.filters.statusCodes=400-499
- --api
- --api.dashboard=true
- --api.insecure=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.docker
- --providers.docker.watch=true
- --providers.docker.exposedbydefault=false
- --certificatesresolvers.leresolver.acme.dnsChallenge=true
- --certificatesresolvers.leresolver.acme.dnsChallenge.provider=linodev4
- --certificatesresolvers.leresolver.acme.httpchallenge=true
- --certificatesresolvers.leresolver.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.leresolver.acme.email=xxxxxxxxxxx#xxxxxxxxx.xxx
- --certificatesresolvers.leresolver.acme.storage=./acme.json
#- --certificatesresolvers.leresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
- --certificatesresolvers.leresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
- --experimental.hub=true
- --hub.tls.insecure=true
- --metrics.prometheus.addrouterslabels=true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ~/certs-data/acme.json:/data/letsencrypt/acme.json
- ./static.yml:/static.yml:ro
- ./configs:/configs
- ~/certs-data/:/data/letsencrypt/
secrets:
- "linode_token"
environment:
TZ: America/Chicago
LINODE_TOKEN_FILE: "/run/secrets/linode_token"
labels:
- "traefik.enable=true"
- "traefik.docker.network=maverick-net"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.tls.certresolver=leresolver"
- "traefik.http.routers.traefik.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=XXXX:$$apr1$$XXXXX$$XXXXXXXXXXXXXXX"
- "traefik.http.routers.api.entrypoints=websecure"
networks:
- maverick-net
hub-agent:
image: ghcr.io/traefik/hub-agent-traefik:experimental
pull_policy: always
container_name: hub-agent
restart: on-failure
command:
- run
- --hub.token=XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
- --auth-server.advertise-url=http://hub-agent
- --traefik.host=traefik
- --traefik.tls.insecure=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- traefik
networks:
- maverick-net
portainer:
image: portainer/portainer-ce:latest
command: -H unix:///var/run/docker.sock
container_name: portainer
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
labels:
# Frontend
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
- "traefik.http.services.frontend.loadbalancer.server.port=9000"
- "traefik.http.routers.frontend.service=frontend"
- "traefik.http.routers.frontend.tls.certresolver=leresolver"
networks:
- maverick-net
whoami:
image: "traefik/whoami"
container_name: "whoami"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`XXXXX.XXXXXXXXXX.XXX`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.tls.certresolver=leresolver"
networks:
- maverick-net
volumes:
portainer_data:
networks:
maverick-net:
external: true
My mariadb stack:
version: "3"
networks:
# enable connection with Traefik
maverick-net:
external: true
services:
mariadb:
container_name: mariadb
image: mariadb:10.7
restart: always
volumes:
- "/home/xxxxxxxxxx/docker/mariadb/data:/var/lib/mysql"
expose:
- "3306"
env_file: .env
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PWD}
MYSQL_USER: ${ADMIN_DB_USER}
MYSQL_PASSWORD: ${ADMIN_DB_PWD}
networks:
- maverick-net
And finally my WordPress stack:
version: '3.8'
networks:
maverick-net:
external: true
# volumes:
# db_data:
services:
# mariadb:
# container_name: ${WORDPRESS_DB_NAME}-db
# image: mariadb:10.7
# restart: always
# volumes:
# - "db_data:/var/lib/mysql"
# env_file: .env
# environment:
# MYSQL_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
# MYSQL_USER: ${ADMIN_DB_USER}
# MYSQL_PASSWORD: ${ADMIN_DB_PWD}
wordpress:
container_name: ${WORDPRESS_DB_NAME}-wp
image: wordpress:6.0.2-fpm
volumes:
- type: bind
source: ${PROJECT_ROOT}/${WORDPRESS_DB_NAME}/${PROJECT_NAME}/${PROJECT_NAME}/wp
target: /var/www/html
restart: always
env_file: .env
environment:
WORDPRESS_DB_HOST: mariadb
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
WORDPRESS_DATABASE_USER: ${WORDPRESS_DB_USER}
WORDPRESS_DATABASE_PASSWORD: ${WORDPRESS_DB_PASSWORD}
WORDPRESS_DATABASE_NAME: ${WORDPRESS_DB_NAME}
labels:
# The labels are useful for Traefik only
- "traefik.enable=true"
- "traefik.docker.network=maverick-net"
# Get the routes from https
- "traefik.http.routers.${WORDPRESS_DB_NAME}.rule=Host(`${DEV_URL}`)"
- "traefik.http.routers.${WORDPRESS_DB_NAME}.entrypoints=websecure"
- "traefik.http.routers.${WORDPRESS_DB_NAME}.tls.certresolver=leresolver"
networks:
- maverick-net
wordpress-cli:
container_name: ${WORDPRESS_DB_NAME}-cli
image: wordpress:cli
volumes:
- type: bind
source: ${PROJECT_ROOT}/${WORDPRESS_DB_NAME}/${PROJECT_NAME}/${PROJECT_NAME}/wp
target: /var/www/html
env_file: .env
environment:
WORDPRESS_DB_HOST: mariadb
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
WORDPRESS_DATABASE_USER: ${WORDPRESS_DB_USER}
WORDPRESS_DATABASE_PASSWORD: ${WORDPRESS_DB_PASSWORD}
WORDPRESS_DATABASE_NAME: ${WORDPRESS_DB_NAME}
networks:
- maverick-net
depends_on:
- wordpress
As far as I know, you can connect to containers in the same network by using their service name.
So for example you are trying to curl to the Wordpress container from the Traefik Container.
curl 'http://wordpress/'
Should work.
In another project I use an nginx container with php-fpm.
I need to send my curl requests to the nginx container, because the php-fpm container does not handle server requests directly:
// does not work
curl 'http://php-debug/index.html'
// result
curl: (7) Failed to connect to php-debug port 80: Connection refused
// https also does not work
curl 'https://php-fpm/index.html'
// result
curl: (7) Failed to connect to php-fpm port 443: Connection refused
// This does work
curl 'http://nginx/index.html'
// result
<HTML...
For some reason https: curl requests fail, but on http I get the correct result so for local development I think it's ok.
If you are interested in a more managed solution, you can check out warden.dev. It contains a template for Wordpress too (which I use succesfully for local development). I have been using this exclusively. If you have questions how to setup WP CLI on this solution, feel free to contact me.
It comes with portainer, traefik, ssl and dns and mailhog.
Configuration is pretty straight forward, I can set up a new project within an hour and connect to the database and containers in my IDE.
https://docs.warden.dev/environments/types.html#wordpress

Wordpress on Docker (Synology NAS) with different networks

first, sorry for my bad english, hope you can understand me.
i have the following task.
I want to run a (maybe more) wordpress installation on my synology nas. Therefore, i installed Docker and run portainer for creating some stuff.
My main idea is to create the following:
Create different container with separated wordpress installations
Create mysql container for hosting the different wordpress databases, each for every wordpress app
for the wordpress container there is a own network called "app_network" (bridge, attachable)
for the mysql container there is another network called "db_backend" (bridge, attachable)
So far, so god. At the moment i created one WP container, the mysql container and the two networks. Everything seems to be fine.
wordpress container is created with docker-compose (stack in portainer)
mysql container is created with docker-compose (stack in portainer)
I created a db for wordpress in the mysql container manually - local login on container works perfect.
the mysql container is in the network db_backend
the woordpress container is in the network app_network and additionally connected to the db_backend network (assigend ip´s looks correct)
But...if i am calling the wordpress page i got "Error establishing a database connection"
My yaml looks like this:
#mysql.yaml
version: '3.9'
services:
db:
image: mysql:latest
restart: on-failure:3
volumes:
- /volume1/docker/databases:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: mysuperstrongpassword
container_name: db_mysql
networks:
- db_backend
networks:
db_backend:
driver: bridge
external: true
#worppess.yaml
version: '3.9'
services:
#frontend
wp_app:
image: wordpress:latest
restart: on-failure:3
ports:
- '49200:80'
- '49201:443'
volumes:
- /volume1/docker/wp_app/wp_t:/var/www/html
environment:
WORDPRESS_DB_HOST: db_mysql:3306 //wrong entry? tried hostname, ip, service
WORDPRESS_DB_NAME: mydb
WORDPRESS_DB_USER: myuser
WORDPRESS_DB_PASSWORD: mypassword
networks:
- db_backend
- app_network
networks:
#172.168.29.1/24
db_backend:
driver: bridge
external: true
#172.168.30.1/24
app_network:
driver: bridge
external: true
After all i was able to read about docker, docker-networking and docker compose i thought my solution should work, all can be deployed without any errors, except the database connection error :( ...
Is the way of connection the container between the networks correct?
May i edit the wp-config.php with the information and add them to the wordpress containe?
Can anyone help?
Replace this WORDPRESS_DB_HOST: db_mysql:3306 with WORDPRESS_DB_HOST: db

Connection Refused when connecting two containers in docker-compose

I'm new to docker and I'm facing a problem when trying to connect to a container from within another. The wierd stuff is that some containers can indeed be contacted, and others, configured in the same way, not. I tried a zillion fixes found while crawling google, nothing works. I guess this is a simple noob mistake though.
Here's my docker-compose file:
version: '3.4'
services:
mssql.db.posm:
image: "microsoft/mssql-server-linux"
environment:
SA_PASSWORD: "mypassword"
ACCEPT_EULA: "Y"
MSSQL_PID: "Express"
volumes:
- mssql-data:/var/opt/mssql
ports:
- "1433:1433"
networks:
posm:
api.posm:
image: ${DOCKER_REGISTRY}posm.api
build:
context: .
dockerfile: Posm.Api/Dockerfile
expose:
- "6869"
ports:
- "6869:80"
networks:
posm:
cloud.subscription:
image: ${DOCKER_REGISTRY}cloud.subscription
build:
context: ./Services
dockerfile: Cloud.Subscription/Dockerfile
ports:
- "80"
networks:
posm:
catalogmanager.services.posm:
image: ${DOCKER_REGISTRY}posm.services.catalogmanager
build:
context: ./Services
dockerfile: CatalogManager/Dockerfile
ports:
- "80"
networks:
posm:
aliases:
- services.posm
- catalogmanager
productmanager.services.posm:
image: ${DOCKER_REGISTRY}posm.services.productmanager
build:
context: ./Services
dockerfile: ProductManager/Dockerfile
ports:
- "80"
networks:
posm:
aliases:
- services.posm
- productmanager
localizer.services.posm:
image: ${DOCKER_REGISTRY}posm.services.localizer
build:
context: ./Services
dockerfile: Localizer/Dockerfile
ports:
- "80"
networks:
posm:
aliases:
- services.posm
- localizer
networks:
posm:
volumes:
mssql-data:
So, when I connect to the api.posm, the latter is able to successfully connect to mssql.db.posm and to cloud.subscription. It however fails, with a connection refused error, to connect to 'catalogmanager' and 'productmanager', even though I can resolve their hostname from within api.posm... What is happening?
You are giving the alias services.posm both to 'catalogmanager' and 'productmanager':
posm:
aliases:
- services.posm
- catalogmanager
As you now per the documentation (https://docs.docker.com/compose/compose-file/#aliases), this will give the hostname "services.posm" to the containers in the posm network. This means that you are having 2 times the "services.posm" host in the network, and both exposing the port 80. This will not work. Remove the "services.posm" line on both containers aliases, restart and you will be able of accessing them using the catalogmanager and productmanager hosts.
So, the problem was a stack overflow exception in one of my images that was unhandled by my debugger, and that I therefore did not see.
Concerning your answer, Moreno...
You are giving the alias services.posm both to 'catalogmanager' and
'productmanager'
I had duplicated this post on Docker forums for increasing my chances to get a relevant answer, and someone suggested the same. The reason I was using the same aliases for three different services is that I read somewhere (cannot find it now, of course) that you could tag multiple services with the same alias for discovery purposes. I probably got that wrong but Docker doesn't seem to mind at all anyways.
So, thanks for your time nonetheless, sorry that I bothered for such stupid mishandling of my code.
Bottom line is: DOCKER ROCKS

Docker: connection refused on exposed port

I have two Docker containers: node-a, node-b. One of them (node-b) should send http request to other (node-a). I'm starting them with Docker Compose. When I'm trying to up them with Compose I face an error:
Get http://node-a:9098: dial tcp 172.18.0.3:9098: getsockopt: connection refused
EXPOSE is declared in Docker file of a-node:
EXPOSE 9098
docker-compose.yml:
version: '3'
services:
node-a:
image: a
ports:
- 9098:9098
volumes:
- ./:/a-src
depends_on:
- redis
node-b:
image: b
volumes:
- ./:/b-src
depends_on:
- node-a
Forwarding is enabled. I believe a server starts because it works well without Docker.
Where I should pay attention? What could cause a problem?
EDIT:
I've tried to add links but it had no effect:
node-b:
image: b
volumes:
- ./:/b-src
links:
- node-a
depends_on:
- node-a
Also links seemed to be deprecated and does the same thing as depends_on in 2+ version of docker-compose.yml:
docker-compose execute V2 files, it will automatically build a network between all of the containers defined in the file, and every container will be immediately able to refer to the others just using the names defined in the docker-compose.yml file.
Link a container to the service using links. (docker-compose documentation on links).
Example:
node-b:
image: b
volumes:
- ./:/b-src
depends_on:
- node-a
links:
- node-a

Docker container can't connect to DB on external network

I have a docker container (Windows 10) running on a new docker network I've defined. The container runs a pentaho transformation that tries to connect to an OpenEdge database.
Within my transformation set up, I have the following DB connection parameters:
#Connection URL
jdbc:datadirect:openedge://<machine_name>:<machine_port>;databaseName=<db_name>;user=<user_name>;password=<pass_word>
#Driver
com.ddtek.jdbc.openedge.OpenEdgeDriver
#User
user_name
#Pass
password
I have the correct drivers in the pentaho lib folder with the correct permissions.
I'm running the transformation from docker-compose and successfully connecting to a mysql DB in another container:
version: "2"
services:
db:
image: mysql:latest
container_name: my-pdi-mysql
networks:
- my-pdi-network
environment:
- MYSQL_ROOT_PASSWORD=tbitter
- MYSQL_DATABASE=mysql-db
ports:
- "3307:3306"
volumes:
- ./goldbi:/var/lib/mysql
pdi:
image: my-pdi-image-with-pan:latest
container_name: my-pdi-container
networks:
- my-pdi-network
volumes:
- C:\Docker-Pentaho\resource:/home/pentaho/data-integration/resources
#entrypoint:
# - C:\Docker-Pentaho\docker-entrypoint-2.sh
networks:
my-pdi-network:
How do I also connect to a DB on an external machine on the same network as the host from my container? I've done a lot of 'googling' on this but I'm a bit confused!
Any help would be greatly appreciated.
Thanks.

Resources