I have two dockerized laravel app, both are going to be used as an API.
One is the Main API, and the other is the Payment API
Docker compose of Main API:
version: '3.8'
services:
api:
image: 'myapp/api:1.0'
container_name: 'myapp-api'
restart: 'on-failure'
user: '1000:1000'
build:
context: .
dockerfile: '.docker/Dockerfile'
args:
UID: '1000'
GID: '1000'
ports:
- '${APP_PORT:-80}:80'
volumes:
- '.:/var/www/html'
networks:
- myapp
networks:
myapp:
driver: bridge
Docker compose of Payment API:
version: '3.8'
services:
payment-api:
image: 'myapp/payment-api:1.0'
container_name: 'myapp-payment-api'
restart: 'on-failure'
user: '1000:1000'
build:
context: .
dockerfile: '.docker/Dockerfile'
args:
UID: '1000'
GID: '1000'
ports:
- '${APP_PORT:-801}:80'
volumes:
- '.:/var/www/html'
networks:
- myapp
networks:
myapp:
driver: bridge
From the Main API, I tried calling the health check of Payment API:
use Illuminate\Support\Facades\Http;
Http::get('http://payment-api/api/health_check');
but I am getting cURL error:
cURL error 6: Could not resolve host: payment-api (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for http://payment-api/api/health_check
Note that health_check doesn't have any middleware attached to it. just plain and simple route to test if the route is reachable.
doing http://localhost:801/api/health_check in the browser works. but wont work when called inside the laravel app.
I am using the container's name as the host here since http://localhost doesn't work either.
Make sure your two container network is same, because docker compose will prefix your network name by folder name.
How to check:
Check both container settings.
use docker inspect <containerName or containerId>, replace "<...>" to your container name or container id, and check NetworkSettings > Networks, two container Networks should be same.
// Example
"NetworkSettings": {
...
"Networks": {
"my-app": { ... } // <- check Network name
}
}
Check from network.
use docker network inspect <networkName>, and check your container are using same network.
// Example
...
"Containers": {
...
"2248c433dae5d0a1b08bdd11dad86184785b89e269b42a76806b11cf6fbaccfa": {
"Name": "myapp-api", // <- should see your first container name
...
},
"3b64e3d359e13bdae60bbfe283a76516ca51678da69c0c81b6e83be315aea8f2": {
"Name": "myapp-payment-api", // <- should see your second container name
...
},
...
},
If this is what you are facing and your don't want docker compose prefix, can just simple add "name" in your yaml.
networks:
myapp:
driver: bridge
name: myapp // like this
Okay, after hours of troubleshooting, I found out that there's a command docker network ls, and my network isn't listed. So I searched, and noticed that the way I defined my network is the legacy-way, so maybe because of that that it wasn't created. Another is, for my Payment API container, I didn't specify the network as external, so even if the network was created, it still probably wont work because docker compose would've assumed that the network is not external and wont be in the same network as the Main API.
Related
I have two, windows-based images that I'm using with docker compose.
The docker-compose.yaml:
services:
application:
image: myapp-win:latest
container_name: "my-app"
# for diagnosis
entrypoint: ["cmd"]
stdin_open: true
tty: true
# /diagnosis
env_file: .myapp/.env
environment:
- POSTGRES_URI=jdbc:postgresql://db0:5432/mydatabase
depends_on:
db0:
condition: service_healthy
db0:
image: stellirin/postgres-windows:10.10
container_name: "my-db"
ports:
- 10000:5432 # this doesn't seem to work in windows
env_file:
- .postgres/.env
volumes:
- .postgres\initdb\:c:\docker-entrypoint-initdb.d\
healthcheck:
test: [ "CMD", "pg_isready", "-q", "-d", "${POSTGRES_DATABASE}", "-U", "${POSTGRES_USER}" ]
timeout: 45s
interval: 10s
retries: 10
restart: unless-stopped
With the two containers started, I accessed the terminal for the my-db container and got its IP address.
Next, I accessed the terminal for the my-app container. I was able to ping the my-db container by its IP address. However, it did not respond by its hostname:
c:\app> ping db0
Ping request could not find host db0.
This is symptommatic why the application can't reach the database using the POSTGRES_URI variable.
Is there a different syntax for the hostname in a Windows container?
** edit **
I'm not able to ping outside the network, from either container:
c:\app> ping 8.8.8.8
Request timed out.
Not sure if this is relevant.
Regardless of container OS, to my knowledge, referring to the other name (db0) directly won't directly work inside the container, but is simply exposed to the other compose entries
Instead, set an env var dependent on the name and read it in the container
environment:
- "ADDRESS_DB=db0"
Then, if you want to be able to ping db0 or similar, have a script set the env var as an available host name on start
Alternatively, you may have success setting it the extra_hosts field, but I haven't tested this and you may need to give it a different name to prevent interpolation
extra_hosts:
- db_url:db0
I'm facing this issue when trying to use a microservice in docker (this doesn't happen in local).
An exception occurred in RetryableException, in the line -2:
Connection refused executing GET http://localhost:8082/api/car/findAll
this is my docker-compose file
version: '3.9'
services:
people:
build:
context: peoplems
ports:
- '8081:8081'
networks:
- host
vehicles:
build:
context: vehiclesms
ports:
- '8082:8082'
networks:
- host
api:
build:
context: apigateway
dockerfile: Dockefile
ports:
- '8080:8080'
networks:
- host
networks:
host:
driver: bridge
The services are running
The error was that I was trying to call "localhost" using feignclient
url = http://localhost:8081/api/car
So, when the app was 'deployed' in docker, docker wouldn't find the localhost address. I had to change "localhost" by the name of the container where the service was deployed: parking-people-1. My new url in feignclient is now
url = http://parking-people-1:8081/api/car
and it works.
NOTE: with this solution, you don't have to create a new network anymore. (at least in this case.)
I hope this could be useful for someone.
I wanted to test a container locally before pushing it to aws ecs.
I ran unit tests against a docker-compose stack including a dynamodb-local container using a Go (aws-sdk-go-v2) endpoint resolver with http://localhost:8000 as the url.
So I wanted to build and test container locally and realised I needed to attach it to the default network created by docker-compose. I struggled with this a bit so I build a stripped down trial. I created an endpoint resolver with a url of http://dynamo-local:8000 (named the container dynamo-local in d-c) and attached it to the default network within docker run.
Now that all works, I can perform the various table operations successfully, but one of the things that confuses me is that if I run aws cli:
aws --endpoint-url=http://localhost:8000 dynamodb list-tables
then the output shows no tables exist when there is definitely a table existing. I had assumed, naively, that as I can access port 8000 of the same container with different endpoints I should be able to access the same resources. Wrong.
Obviously a gap in my education. What am I missing ? I need to expand the trial to a proper test of the full app, so its important to me that I understand what is going on here.
Is there a way I can use the aws cli to access the table?
docker-compose file :
version: '3.5'
services:
localstack:
image: localstack/localstack:latest
container_name: localstack_test
ports:
- '4566:4566'
environment:
- SERVICES=s3,sns,sqs, lambda
- DEBUG=1
- DATA_DIR=
volumes:
- './.AWSServices:/tmp/AWSServices'
- '/var/run/docker.sock:/var/run/docker.sock'
nginx:
build:
context: .
dockerfile: Dockerfile
image: chanonry/urlfiles-nginx:latest
container_name: nginx
ports:
- '8080:80'
dynamodb:
image: amazon/dynamodb-local:1.13.6
container_name: dynamo-local
ports:
- '8000:8000'
networks:
default:
name: test-net
I have the problem, that I want to create multiple docker container (with docker-compose) and call each container with the ip address.
On a Linux host it works but not in Windows as host.
Example:
container 1 (php) ip: 192.168.100.10
container 2 (mysql) ip: 192.168.100.11
container 3 (nginx) ip: 192.168.100.12
so I want to add a hosts item with the ip of the nginx to use a hostname like project.local for develop on browser.
Have anyone a idea what I must do on windows to realize this?
Each container use a internal IP for the base system that you using with your containers, for example if you are using Linux all container will have an internal IP that can be seen between container, but not for the principal host, if you want to connect to the containers you will need to use the ports for example for MySQL 3306, if the containers aren't seen between it you will need to create links or networks using a docker compose or the bash to set up this configuration, here I adjunct an example:
https://docs.docker.com/compose/networking/#specify-custom-networks
version: "3"
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
# Use a custom driver
driver: custom-driver-1
backend:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"
https://docs.docker.com/compose/networking/#links
version: "3"
services:
web:
build: .
links:
- "db:database"
db:
image: postgres
Tl;Dr; Trying to get WordPress docker-compose container to talk to another docker-compose container.
On my Mac I have a WordPress & MySQL container which I have built and configured with a linked MySQL server. In production I plan to use a Google Cloud MySQL storage instance, so plan on removing the MySQL container from the docker-compose file (unlinking it) and then separate shared container I can use from multiple docker containers.
The issue I'm having is that I cant connect the WordPress container to the separate MySQL container. Would anyone be able to shed any light on how I might go about this?
I have tried unsuccessfully to create a network as well as tried creating a fixed IP that the local box has reference to via the /etc/hosts file (my preferred configuration as I can update the file according to ENV)
WP:
version: '2'
services:
wordpress:
container_name: spmfrontend
hostname: spmfrontend
domainname: spmfrontend.local
image: wordpress:latest
restart: always
ports:
- 8080:80
# creates an entry in /etc/hosts
extra_hosts:
- "ic-mysql.local:172.20.0.1"
# Sets up the env, passwords etc
environment:
WORDPRESS_DB_HOST: ic-mysql.local:9306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
WORDPRESS_DB_NAME: wordpress
WORDPRESS_TABLE_PREFIX: spm
# sets the working directory
working_dir: /var/www/html
# creates a link to the volume local to the file
volumes:
- ./wp-content:/var/www/html/wp-content
# Any networks the container should be associated with
networks:
default:
external:
name: ic-network
MySQL:
version: '2'
services:
mysql:
container_name: ic-mysql
hostname: ic-mysql
domainname: ic-mysql.local
restart: always
image: mysql:5.7
ports:
- 9306:3306
# Create a static IP for the container
networks:
ipv4_address: 172.20.0.1
# Sets up the env, passwords etc
environment:
MYSQL_ROOT_PASSWORD: root # TODO: Change this
MYSQL_USER: root
MYSQL_PASS: root
MYSQL_DATABASE: wordpress
# saves /var/lib/mysql to persistant volume
volumes:
- perstvol:/var/lib/mysql
- backups:/backups
# creates a volume to persist data
volumes:
perstvol:
backups:
# Any networks the container should be associated with
networks:
default:
external:
name: ic-network
What you probably want to do is create a shared Docker network for the two containers to use, and point them both to it. You can create a network using docker network create <name>. I will use sharednet as an example below, but you can use any name you like.
Once the network is there, you can point both containers to it. When you're using docker-compose, you would do this at the bottom of your YAML file. This would go at the top level of the file, i.e. all the way to the left, like volumes:.
networks:
default:
external:
name: sharednet
To do the same thing on a normal container (outside compose), you can pass the --network argument.
docker run --network sharednet [ ... ]